summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.depend180
-rw-r--r--.gitignore33
-rw-r--r--.skipped-commit-ids47
-rw-r--r--Android.bp261
-rw-r--r--Android.mk310
-rw-r--r--CREDITS5
-rw-r--r--ChangeLog8584
-rw-r--r--INSTALL116
-rw-r--r--LICENCE25
-rw-r--r--METADATA17
-rw-r--r--Makefile.in462
-rw-r--r--OVERVIEW24
-rw-r--r--PROTOCOL73
-rw-r--r--PROTOCOL.agent563
-rw-r--r--PROTOCOL.certkeys89
-rw-r--r--PROTOCOL.chacha20poly13056
-rw-r--r--PROTOCOL.krl18
-rw-r--r--PROTOCOL.mux150
-rw-r--r--PROTOCOL.sshsig99
-rw-r--r--PROTOCOL.u2f337
-rw-r--r--README51
-rw-r--r--README.dns8
-rw-r--r--README.md79
-rw-r--r--README.platform8
-rw-r--r--README.privsep24
-rw-r--r--README.version4
-rw-r--r--TODO12
-rw-r--r--aclocal.m423
-rw-r--r--addrmatch.c30
-rw-r--r--atomicio.c36
-rw-r--r--atomicio.h4
-rw-r--r--audit-bsm.c5
-rw-r--r--audit-linux.c30
-rw-r--r--audit.c6
-rw-r--r--audit.h6
-rw-r--r--auth-bsdauth.c10
-rw-r--r--auth-chall.c127
-rw-r--r--auth-krb5.c9
-rw-r--r--auth-options.c1230
-rw-r--r--auth-options.h117
-rw-r--r--auth-pam.c522
-rw-r--r--auth-pam.h13
-rw-r--r--auth-passwd.c69
-rw-r--r--auth-rh-rsa.c108
-rw-r--r--auth-rhosts.c38
-rw-r--r--auth-rsa.c349
-rw-r--r--auth-shadow.c23
-rw-r--r--auth-sia.c5
-rw-r--r--auth-skey.c108
-rw-r--r--auth.c819
-rw-r--r--auth.h153
-rw-r--r--auth1.c444
-rw-r--r--auth2-chall.c135
-rw-r--r--auth2-gss.c182
-rw-r--r--auth2-hostbased.c143
-rw-r--r--auth2-kbdint.c20
-rw-r--r--auth2-none.c15
-rw-r--r--auth2-passwd.c38
-rw-r--r--auth2-pubkey.c1185
-rw-r--r--auth2.c394
-rw-r--r--authfd.c348
-rw-r--r--authfd.h20
-rw-r--r--authfile.c395
-rw-r--r--authfile.h10
-rw-r--r--bitmap.c10
-rw-r--r--bitmap.h1
-rw-r--r--blocks.c248
-rw-r--r--bufaux.c259
-rw-r--r--bufbn.c109
-rw-r--r--bufec.c74
-rw-r--r--buffer.c118
-rw-r--r--buffer.h99
-rw-r--r--buildpkg.sh.in2
-rw-r--r--canohost.c266
-rw-r--r--canohost.h13
-rw-r--r--chacha.h3
-rw-r--r--channels.c4568
-rw-r--r--channels.h244
-rw-r--r--cipher-3des1.c155
-rw-r--r--cipher-bf1.c103
-rw-r--r--cipher-chachapoly-libcrypto.c166
-rw-r--r--cipher-chachapoly.c31
-rw-r--r--cipher-chachapoly.h13
-rw-r--r--cipher.c464
-rw-r--r--cipher.h54
-rw-r--r--clientloop.c1867
-rw-r--r--clientloop.h35
-rw-r--r--compat.c222
-rw-r--r--compat.h34
-rwxr-xr-xconfig.guess1015
-rw-r--r--config.h.in1707
-rwxr-xr-xconfig.sub2528
-rwxr-xr-xconfigure36621
-rw-r--r--configure.ac1343
-rw-r--r--contrib/Makefile7
-rw-r--r--contrib/README2
-rw-r--r--contrib/aix/README3
-rwxr-xr-xcontrib/aix/buildbff.sh17
-rwxr-xr-xcontrib/aix/inventory.sh1
-rw-r--r--contrib/cygwin/Makefile11
-rw-r--r--contrib/cygwin/README5
-rw-r--r--contrib/cygwin/ssh-host-config104
-rw-r--r--contrib/cygwin/ssh-user-config2
-rw-r--r--contrib/findssl.sh2
-rw-r--r--contrib/gnome-ssh-askpass2.c143
-rw-r--r--contrib/redhat/openssh.spec118
-rwxr-xr-xcontrib/redhat/sshd.init1
-rwxr-xr-xcontrib/redhat/sshd.init.old17
-rw-r--r--contrib/solaris/README2
-rw-r--r--contrib/ssh-copy-id72
-rw-r--r--contrib/ssh-copy-id.17
-rw-r--r--contrib/suse/openssh.spec10
-rw-r--r--crc32.c105
-rw-r--r--crc32.h30
-rw-r--r--crypto_api.h26
-rw-r--r--deattack.c165
-rw-r--r--deattack.h38
-rw-r--r--defines.h122
-rw-r--r--dh.c252
-rw-r--r--dh.h19
-rw-r--r--digest-libc.c45
-rw-r--r--digest-openssl.c40
-rw-r--r--digest.h13
-rw-r--r--dispatch.c41
-rw-r--r--dispatch.h21
-rw-r--r--dns.c10
-rw-r--r--dns.h5
-rw-r--r--entropy.c84
-rw-r--r--entropy.h9
-rwxr-xr-xfixprogs72
-rw-r--r--groupaccess.c23
-rw-r--r--gss-genr.c63
-rw-r--r--gss-serv-krb5.c5
-rw-r--r--gss-serv.c54
-rw-r--r--hash.c89
-rw-r--r--hmac.c9
-rw-r--r--hostfile.c91
-rw-r--r--includes.h9
-rwxr-xr-xinstall-sh682
-rw-r--r--kex.c869
-rw-r--r--kex.h130
-rw-r--r--kexc25519.c179
-rw-r--r--kexc25519c.c170
-rw-r--r--kexc25519s.c158
-rw-r--r--kexdh.c202
-rw-r--r--kexdhc.c212
-rw-r--r--kexdhs.c216
-rw-r--r--kexecdh.c239
-rw-r--r--kexecdhc.c228
-rw-r--r--kexecdhs.c208
-rw-r--r--kexgen.c340
-rw-r--r--kexgex.c32
-rw-r--r--kexgexc.c186
-rw-r--r--kexgexs.c197
-rw-r--r--kexsntrup4591761x25519.c219
-rw-r--r--key.c426
-rw-r--r--key.h105
-rw-r--r--krl.c283
-rw-r--r--krl.h10
-rw-r--r--log.c57
-rw-r--r--log.h9
-rw-r--r--loginrec.c26
-rw-r--r--loginrec.h5
-rw-r--r--mac.c33
-rw-r--r--mac.h4
-rw-r--r--match.c115
-rw-r--r--match.h9
-rw-r--r--md-sha256.c86
-rw-r--r--md5crypt.c4
-rw-r--r--md5crypt.h2
-rw-r--r--mdoc2man.awk4
-rw-r--r--misc.c1426
-rw-r--r--misc.h67
-rwxr-xr-xmkinstalldirs2
-rw-r--r--moduli675
-rw-r--r--moduli.074
-rw-r--r--moduli.c36
-rw-r--r--monitor.c1477
-rw-r--r--monitor.h25
-rw-r--r--monitor_fdpass.c8
-rw-r--r--monitor_mm.c357
-rw-r--r--monitor_mm.h62
-rw-r--r--monitor_wrap.c968
-rw-r--r--monitor_wrap.h53
-rw-r--r--msg.c16
-rw-r--r--mux.c1307
-rw-r--r--myproposal.h167
-rw-r--r--nchan.c437
-rw-r--r--opacket.c349
-rw-r--r--opacket.h168
-rw-r--r--openbsd-compat/.cvsignore1
-rw-r--r--openbsd-compat/Makefile.in90
-rw-r--r--openbsd-compat/arc4random.c20
-rw-r--r--openbsd-compat/base64.h4
-rw-r--r--openbsd-compat/bcrypt_pbkdf.c20
-rw-r--r--openbsd-compat/bindresvport.c1
-rw-r--r--openbsd-compat/blowfish.c2
-rw-r--r--openbsd-compat/bsd-asprintf.c23
-rw-r--r--openbsd-compat/bsd-closefrom.c90
-rw-r--r--openbsd-compat/bsd-cray.c817
-rw-r--r--openbsd-compat/bsd-cray.h61
-rw-r--r--openbsd-compat/bsd-cygwin_util.c156
-rw-r--r--openbsd-compat/bsd-cygwin_util.h5
-rw-r--r--openbsd-compat/bsd-err.c77
-rw-r--r--openbsd-compat/bsd-flock.c81
-rw-r--r--openbsd-compat/bsd-getline.c113
-rw-r--r--openbsd-compat/bsd-getpagesize.c25
-rw-r--r--openbsd-compat/bsd-malloc.c57
-rw-r--r--openbsd-compat/bsd-misc.c232
-rw-r--r--openbsd-compat/bsd-misc.h92
-rw-r--r--openbsd-compat/bsd-nextstep.c2
-rw-r--r--openbsd-compat/bsd-nextstep.h4
-rw-r--r--openbsd-compat/bsd-openpty.c46
-rw-r--r--openbsd-compat/bsd-poll.c2
-rw-r--r--openbsd-compat/bsd-poll.h4
-rw-r--r--openbsd-compat/bsd-setres_id.c14
-rw-r--r--openbsd-compat/bsd-setres_id.h2
-rw-r--r--openbsd-compat/bsd-signal.c35
-rw-r--r--openbsd-compat/bsd-signal.h36
-rw-r--r--openbsd-compat/bsd-snprintf.c16
-rw-r--r--openbsd-compat/bsd-statvfs.c23
-rw-r--r--openbsd-compat/bsd-statvfs.h5
-rw-r--r--openbsd-compat/bsd-waitpid.c8
-rw-r--r--openbsd-compat/bsd-waitpid.h4
-rw-r--r--openbsd-compat/explicit_bzero.c24
-rw-r--r--openbsd-compat/fake-rfc2553.c38
-rw-r--r--openbsd-compat/fake-rfc2553.h12
-rw-r--r--openbsd-compat/fmt_scaled.c51
-rw-r--r--openbsd-compat/fnmatch.c495
-rw-r--r--openbsd-compat/fnmatch.h66
-rw-r--r--openbsd-compat/freezero.c (renamed from roaming_serv.c)23
-rw-r--r--openbsd-compat/getcwd.c2
-rw-r--r--openbsd-compat/getgrouplist.c2
-rw-r--r--openbsd-compat/getrrsetbyname.c2
-rw-r--r--openbsd-compat/getrrsetbyname.c.orig610
-rw-r--r--openbsd-compat/glob.c158
-rw-r--r--openbsd-compat/glob.h17
-rw-r--r--openbsd-compat/inet_aton.c10
-rw-r--r--openbsd-compat/libressl-api-compat.c642
-rw-r--r--openbsd-compat/memmem.c69
-rw-r--r--openbsd-compat/openbsd-compat.h117
-rw-r--r--openbsd-compat/openssl-compat.c24
-rw-r--r--openbsd-compat/openssl-compat.h185
-rw-r--r--openbsd-compat/port-aix.c51
-rw-r--r--openbsd-compat/port-aix.h12
-rw-r--r--openbsd-compat/port-irix.c50
-rw-r--r--openbsd-compat/port-irix.h2
-rw-r--r--openbsd-compat/port-linux.c18
-rw-r--r--openbsd-compat/port-linux.h2
-rw-r--r--openbsd-compat/port-net.c (renamed from openbsd-compat/port-tun.c)202
-rw-r--r--openbsd-compat/port-net.h (renamed from openbsd-compat/port-tun.h)21
-rw-r--r--openbsd-compat/port-solaris.c138
-rw-r--r--openbsd-compat/port-solaris.h9
-rw-r--r--openbsd-compat/port-uw.c11
-rw-r--r--openbsd-compat/pwcache.c4
-rw-r--r--openbsd-compat/readpassphrase.c106
-rw-r--r--openbsd-compat/readpassphrase.c.orig213
-rw-r--r--openbsd-compat/recallocarray.c90
-rw-r--r--openbsd-compat/regress/.cvsignore6
-rw-r--r--openbsd-compat/regress/Makefile.in4
-rw-r--r--openbsd-compat/regress/snprintftest.c3
-rw-r--r--openbsd-compat/regress/utimensattest.c118
-rw-r--r--openbsd-compat/rmd160.c376
-rw-r--r--openbsd-compat/rmd160.h61
-rw-r--r--openbsd-compat/setproctitle.c13
-rw-r--r--openbsd-compat/sha1.c13
-rw-r--r--openbsd-compat/sha2.c336
-rw-r--r--openbsd-compat/sha2.h138
-rw-r--r--openbsd-compat/strcasestr.c69
-rw-r--r--openbsd-compat/strndup.c43
-rw-r--r--openbsd-compat/strnlen.c4
-rw-r--r--openbsd-compat/sys-queue.h6
-rw-r--r--openbsd-compat/vis.c54
-rw-r--r--openbsd-compat/vis.h5
-rw-r--r--openbsd-compat/xcrypt.c63
-rw-r--r--openbsd-compat/xmmap.c88
-rwxr-xr-xopensshd.init.in4
-rw-r--r--packet.c1726
-rw-r--r--packet.h71
-rw-r--r--pathnames.h24
-rw-r--r--platform-misc.c35
-rw-r--r--platform-pledge.c71
-rw-r--r--platform-tracing.c51
-rw-r--r--platform.c32
-rw-r--r--platform.h8
-rw-r--r--prebuilt-intermediates/config.h (renamed from config.h)62
-rw-r--r--progressmeter.c77
-rw-r--r--progressmeter.h3
-rw-r--r--readconf.c1142
-rw-r--r--readconf.h59
-rw-r--r--readpass.c143
-rw-r--r--regress/Makefile262
-rw-r--r--regress/README.regress161
-rw-r--r--regress/addrmatch.sh56
-rw-r--r--regress/agent-getpeereid.sh57
-rw-r--r--regress/agent-pkcs11.sh124
-rw-r--r--regress/agent-ptrace.sh66
-rw-r--r--regress/agent-timeout.sh38
-rw-r--r--regress/agent.sh164
-rw-r--r--regress/allow-deny-users.sh45
-rw-r--r--regress/authinfo.sh17
-rw-r--r--regress/banner.sh44
-rw-r--r--regress/broken-pipe.sh12
-rw-r--r--regress/brokenkeys.sh23
-rw-r--r--regress/cert-file.sh166
-rw-r--r--regress/cert-hostkey.sh325
-rw-r--r--regress/cert-userkey.sh404
-rw-r--r--regress/cfginclude.sh293
-rw-r--r--regress/cfgmatch.sh158
-rw-r--r--regress/cfgmatchlisten.sh202
-rw-r--r--regress/cfgparse.sh75
-rw-r--r--regress/check-perm.c205
-rw-r--r--regress/cipher-speed.sh32
-rw-r--r--regress/conch-ciphers.sh28
-rw-r--r--regress/connect-privsep.sh35
-rw-r--r--regress/connect-uri.sh29
-rw-r--r--regress/connect.sh18
-rw-r--r--regress/dhgex.sh61
-rw-r--r--regress/dsa_ssh2.prv14
-rw-r--r--regress/dsa_ssh2.pub13
-rw-r--r--regress/dynamic-forward.sh61
-rw-r--r--regress/envpass.sh60
-rw-r--r--regress/exit-status.sh22
-rw-r--r--regress/forcecommand.sh35
-rw-r--r--regress/forward-control.sh235
-rw-r--r--regress/forwarding.sh136
-rw-r--r--regress/host-expand.sh16
-rw-r--r--regress/hostkey-agent.sh53
-rw-r--r--regress/hostkey-rotate.sh121
-rw-r--r--regress/integrity.sh76
-rw-r--r--regress/kextype.sh25
-rw-r--r--regress/key-options.sh124
-rw-r--r--regress/keygen-change.sh22
-rw-r--r--regress/keygen-comment.sh52
-rw-r--r--regress/keygen-convert.sh41
-rw-r--r--regress/keygen-knownhosts.sh220
-rw-r--r--regress/keygen-moduli.sh27
-rw-r--r--regress/keys-command.sh81
-rw-r--r--regress/keyscan.sh25
-rw-r--r--regress/keytype.sh83
-rw-r--r--regress/krl.sh217
-rw-r--r--regress/limit-keytype.sh133
-rw-r--r--regress/localcommand.sh13
-rw-r--r--regress/login-timeout.sh18
-rw-r--r--regress/misc/Makefile3
-rw-r--r--regress/misc/fuzz-harness/Makefile38
-rw-r--r--regress/misc/fuzz-harness/README1
-rw-r--r--regress/misc/fuzz-harness/authopt_fuzz.cc33
-rw-r--r--regress/misc/fuzz-harness/privkey_fuzz.cc21
-rw-r--r--regress/misc/fuzz-harness/pubkey_fuzz.cc18
-rw-r--r--regress/misc/fuzz-harness/sig_fuzz.cc62
-rw-r--r--regress/misc/fuzz-harness/ssh-sk-null.cc51
-rw-r--r--regress/misc/fuzz-harness/sshsig_fuzz.cc37
-rw-r--r--regress/misc/fuzz-harness/sshsigopt_fuzz.cc29
-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/Makefile66
-rw-r--r--regress/misc/sk-dummy/fatal.c20
-rw-r--r--regress/misc/sk-dummy/sk-dummy.c532
-rw-r--r--regress/mkdtemp.c61
-rw-r--r--regress/modpipe.c150
-rw-r--r--regress/moduli.in3
-rw-r--r--regress/multiplex.sh197
-rw-r--r--regress/multipubkey.sh66
-rw-r--r--regress/netcat.c1671
-rw-r--r--regress/percent.sh88
-rw-r--r--regress/portnum.sh34
-rw-r--r--regress/principals-command.sh174
-rw-r--r--regress/proto-mismatch.sh17
-rw-r--r--regress/proto-version.sh30
-rw-r--r--regress/proxy-connect.sh27
-rw-r--r--regress/putty-ciphers.sh26
-rw-r--r--regress/putty-kex.sh22
-rw-r--r--regress/putty-transfer.sh44
-rw-r--r--regress/reconfigure.sh43
-rw-r--r--regress/reexec.sh57
-rw-r--r--regress/rekey.sh172
-rw-r--r--regress/rsa_openssh.prv15
-rw-r--r--regress/rsa_openssh.pub1
-rw-r--r--regress/rsa_ssh2.prv16
-rw-r--r--regress/scp-ssh-wrapper.sh71
-rw-r--r--regress/scp-uri.sh70
-rw-r--r--regress/scp.sh136
-rw-r--r--regress/servcfginclude.sh154
-rw-r--r--regress/setuid-allowed.c (renamed from roaming_dummy.c)78
-rw-r--r--regress/sftp-badcmds.sh65
-rw-r--r--regress/sftp-batch.sh55
-rw-r--r--regress/sftp-chroot.sh31
-rw-r--r--regress/sftp-cmds.sh228
-rw-r--r--regress/sftp-glob.sh75
-rw-r--r--regress/sftp-perm.sh269
-rw-r--r--regress/sftp-uri.sh63
-rw-r--r--regress/sftp.sh32
-rw-r--r--regress/ssh-com-client.sh130
-rw-r--r--regress/ssh-com-keygen.sh74
-rw-r--r--regress/ssh-com-sftp.sh65
-rw-r--r--regress/ssh-com.sh119
-rwxr-xr-xregress/ssh2putty.sh34
-rw-r--r--regress/sshcfgparse.sh108
-rw-r--r--regress/sshd-log-wrapper.sh11
-rw-r--r--regress/sshsig.sh196
-rw-r--r--regress/stderr-after-eof.sh24
-rw-r--r--regress/stderr-data.sh27
-rw-r--r--regress/t11.ok1
-rw-r--r--regress/t4.ok1
-rw-r--r--regress/t5.ok1
-rw-r--r--regress/test-exec.sh702
-rw-r--r--regress/transfer.sh23
-rw-r--r--regress/try-ciphers.sh28
-rw-r--r--regress/unittests/Makefile7
-rw-r--r--regress/unittests/Makefile.inc89
-rw-r--r--regress/unittests/authopt/Makefile27
-rw-r--r--regress/unittests/authopt/testdata/all_permit.cert1
-rw-r--r--regress/unittests/authopt/testdata/bad_sourceaddr.cert1
-rw-r--r--regress/unittests/authopt/testdata/force_command.cert1
-rw-r--r--regress/unittests/authopt/testdata/host.cert1
-rw-r--r--regress/unittests/authopt/testdata/mktestdata.sh48
-rw-r--r--regress/unittests/authopt/testdata/no_agentfwd.cert1
-rw-r--r--regress/unittests/authopt/testdata/no_permit.cert1
-rw-r--r--regress/unittests/authopt/testdata/no_portfwd.cert1
-rw-r--r--regress/unittests/authopt/testdata/no_pty.cert1
-rw-r--r--regress/unittests/authopt/testdata/no_user_rc.cert1
-rw-r--r--regress/unittests/authopt/testdata/no_x11fwd.cert1
-rw-r--r--regress/unittests/authopt/testdata/only_agentfwd.cert1
-rw-r--r--regress/unittests/authopt/testdata/only_portfwd.cert1
-rw-r--r--regress/unittests/authopt/testdata/only_pty.cert1
-rw-r--r--regress/unittests/authopt/testdata/only_user_rc.cert1
-rw-r--r--regress/unittests/authopt/testdata/only_x11fwd.cert1
-rw-r--r--regress/unittests/authopt/testdata/sourceaddr.cert1
-rw-r--r--regress/unittests/authopt/testdata/unknown_critical.cert1
-rw-r--r--regress/unittests/authopt/tests.c573
-rw-r--r--regress/unittests/bitmap/Makefile14
-rw-r--r--regress/unittests/bitmap/tests.c139
-rw-r--r--regress/unittests/conversion/Makefile15
-rw-r--r--regress/unittests/conversion/tests.c53
-rw-r--r--regress/unittests/hostkeys/Makefile25
-rw-r--r--regress/unittests/hostkeys/mktestdata.sh86
-rw-r--r--regress/unittests/hostkeys/test_iterate.c1065
-rw-r--r--regress/unittests/hostkeys/testdata/dsa_1.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/dsa_2.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/dsa_3.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/dsa_4.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/dsa_5.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/dsa_6.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ecdsa_1.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ecdsa_2.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ecdsa_3.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ecdsa_4.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ecdsa_5.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ecdsa_6.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ed25519_1.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ed25519_2.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ed25519_3.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ed25519_4.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ed25519_5.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ed25519_6.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/known_hosts50
-rw-r--r--regress/unittests/hostkeys/testdata/rsa1_1.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa1_2.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa1_3.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa1_4.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa1_5.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa1_6.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa_1.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa_2.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa_3.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa_4.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa_5.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa_6.pub1
-rw-r--r--regress/unittests/hostkeys/tests.c16
-rw-r--r--regress/unittests/kex/Makefile40
-rw-r--r--regress/unittests/kex/test_kex.c205
-rw-r--r--regress/unittests/kex/tests.c14
-rw-r--r--regress/unittests/match/Makefile16
-rw-r--r--regress/unittests/match/tests.c132
-rw-r--r--regress/unittests/misc/Makefile16
-rw-r--r--regress/unittests/misc/tests.c79
-rw-r--r--regress/unittests/sshbuf/Makefile21
-rw-r--r--regress/unittests/sshbuf/test_sshbuf.c240
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_fixed.c126
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_fuzz.c132
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_getput_basic.c713
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_getput_crypto.c281
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c131
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_misc.c218
-rw-r--r--regress/unittests/sshbuf/tests.c30
-rw-r--r--regress/unittests/sshkey/Makefile26
-rw-r--r--regress/unittests/sshkey/common.c164
-rw-r--r--regress/unittests/sshkey/common.h25
-rwxr-xr-xregress/unittests/sshkey/mktestdata.sh181
-rw-r--r--regress/unittests/sshkey/test_file.c427
-rw-r--r--regress/unittests/sshkey/test_fuzz.c390
-rw-r--r--regress/unittests/sshkey/test_sshkey.c526
-rw-r--r--regress/unittests/sshkey/testdata/dsa_112
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1-cert.fp1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1-cert.pub1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.fp1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.param.g1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.param.priv1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.param.pub1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.pub1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1_pw15
-rw-r--r--regress/unittests/sshkey/testdata/dsa_212
-rw-r--r--regress/unittests/sshkey/testdata/dsa_2.fp1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_2.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_2.pub1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_n21
-rw-r--r--regress/unittests/sshkey/testdata/dsa_n_pw21
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_15
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1-cert.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1-cert.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.param.curve1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.param.priv1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.param.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1_pw8
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_27
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.param.curve1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.param.priv1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.param.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_n8
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_n_pw9
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_17
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1-cert.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1-cert.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1_pw8
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_27
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_2.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_2.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_2.pub1
-rw-r--r--regress/unittests/sshkey/testdata/pw1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_115
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1-cert.fp1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1-cert.pub1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.fp1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.param.n1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.param.p1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.param.q1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.pub1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1_pw18
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1_sha115
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1_sha1-cert.pub1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1_sha1.pub1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1_sha51215
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1_sha512-cert.pub1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1_sha512.pub1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_227
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.fp1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.param.n1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.param.p1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.param.q1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.pub1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_n16
-rw-r--r--regress/unittests/sshkey/testdata/rsa_n_pw17
-rw-r--r--regress/unittests/sshkey/tests.c22
-rw-r--r--regress/unittests/test_helper/Makefile15
-rw-r--r--regress/unittests/test_helper/fuzz.c438
-rw-r--r--regress/unittests/test_helper/test_helper.c594
-rw-r--r--regress/unittests/test_helper/test_helper.h326
-rw-r--r--regress/unittests/utf8/Makefile14
-rw-r--r--regress/unittests/utf8/tests.c104
-rwxr-xr-xregress/valgrind-unit.sh22
-rw-r--r--regress/yes-head.sh13
-rw-r--r--rijndael.c2
-rw-r--r--roaming.h45
-rw-r--r--roaming_client.c271
-rw-r--r--roaming_common.c241
-rw-r--r--rsa.c188
-rw-r--r--rsa.h26
-rw-r--r--sandbox-capsicum.c2
-rw-r--r--sandbox-darwin.c3
-rw-r--r--sandbox-pledge.c77
-rw-r--r--sandbox-rlimit.c3
-rw-r--r--sandbox-seccomp-filter.c250
-rw-r--r--sandbox-solaris.c114
-rw-r--r--sandbox-systrace.c42
-rw-r--r--scp.0164
-rw-r--r--scp.1102
-rw-r--r--scp.c784
-rw-r--r--servconf.c1560
-rw-r--r--servconf.h157
-rw-r--r--serverloop.c1242
-rw-r--r--serverloop.h7
-rw-r--r--session.c1393
-rw-r--r--session.h22
-rw-r--r--sftp-client.c167
-rw-r--r--sftp-client.h15
-rw-r--r--sftp-common.c34
-rw-r--r--sftp-glob.c4
-rw-r--r--sftp-realpath.c (renamed from openbsd-compat/realpath.c)75
-rw-r--r--sftp-server-main.c5
-rw-r--r--sftp-server.096
-rw-r--r--sftp-server.86
-rw-r--r--sftp-server.c142
-rw-r--r--sftp.0383
-rw-r--r--sftp.1232
-rw-r--r--sftp.c482
-rw-r--r--sk-api.h95
-rw-r--r--sk-usbhid.c1055
-rw-r--r--sntrup4591761.c1083
-rw-r--r--sntrup4591761.sh57
-rw-r--r--ssh-add.0128
-rw-r--r--ssh-add.169
-rw-r--r--ssh-add.c466
-rw-r--r--ssh-agent.0109
-rw-r--r--ssh-agent.1188
-rw-r--r--ssh-agent.c1132
-rw-r--r--ssh-dss.c135
-rw-r--r--ssh-ecdsa-sk.c209
-rw-r--r--ssh-ecdsa.c46
-rw-r--r--ssh-ed25519-sk.c164
-rw-r--r--ssh-ed25519.c23
-rw-r--r--ssh-gss.h9
-rw-r--r--ssh-keygen.0566
-rw-r--r--ssh-keygen.1739
-rw-r--r--ssh-keygen.c2703
-rw-r--r--ssh-keyscan.0109
-rw-r--r--ssh-keyscan.1114
-rw-r--r--ssh-keyscan.c303
-rw-r--r--ssh-keysign.053
-rw-r--r--ssh-keysign.88
-rw-r--r--ssh-keysign.c57
-rw-r--r--ssh-pkcs11-client.c314
-rw-r--r--ssh-pkcs11-helper.025
-rw-r--r--ssh-pkcs11-helper.829
-rw-r--r--ssh-pkcs11-helper.c336
-rw-r--r--ssh-pkcs11.c1701
-rw-r--r--ssh-pkcs11.h20
-rw-r--r--ssh-rsa.c281
-rw-r--r--ssh-sk-client.c449
-rw-r--r--ssh-sk-helper.866
-rw-r--r--ssh-sk-helper.c360
-rw-r--r--ssh-sk.c807
-rw-r--r--ssh-sk.h69
-rw-r--r--ssh-xmss.c186
-rw-r--r--ssh.0951
-rw-r--r--ssh.1498
-rw-r--r--ssh.c1592
-rw-r--r--ssh.h22
-rw-r--r--ssh1.h92
-rw-r--r--ssh2.h14
-rw-r--r--ssh_api.c198
-rw-r--r--ssh_api.h4
-rw-r--r--ssh_config13
-rw-r--r--ssh_config.0981
-rw-r--r--ssh_config.51336
-rw-r--r--sshbuf-getput-basic.c183
-rw-r--r--sshbuf-getput-crypto.c82
-rw-r--r--sshbuf-io.c117
-rw-r--r--sshbuf-misc.c130
-rw-r--r--sshbuf.c135
-rw-r--r--sshbuf.h161
-rw-r--r--sshconnect.c827
-rw-r--r--sshconnect.h50
-rw-r--r--sshconnect1.c771
-rw-r--r--sshconnect2.c1737
-rw-r--r--sshd.0634
-rw-r--r--sshd.8309
-rw-r--r--sshd.c1816
-rw-r--r--sshd_config23
-rw-r--r--sshd_config.0946
-rw-r--r--sshd_config.51258
-rw-r--r--sshd_config.android117
-rw-r--r--ssherr.c14
-rw-r--r--ssherr.h7
-rw-r--r--sshkey-xmss.c1112
-rw-r--r--sshkey-xmss.h56
-rw-r--r--sshkey.c3440
-rw-r--r--sshkey.h151
-rw-r--r--sshlogin.c25
-rw-r--r--sshpty.c81
-rw-r--r--sshpty.h3
-rw-r--r--sshsig.c1041
-rw-r--r--sshsig.h104
-rw-r--r--start-ssh6
-rw-r--r--ttymodes.c224
-rw-r--r--ttymodes.h24
-rw-r--r--uidswap.c98
-rw-r--r--uidswap.h3
-rw-r--r--umac.c218
-rw-r--r--umac.h6
-rw-r--r--umac128.c17
-rw-r--r--utf8.c355
-rw-r--r--utf8.h28
-rw-r--r--uuencode.c95
-rw-r--r--uuencode.h29
-rw-r--r--version.h4
-rw-r--r--xmalloc.c55
-rw-r--r--xmalloc.h7
-rw-r--r--xmss_commons.c36
-rw-r--r--xmss_commons.h21
-rw-r--r--xmss_fast.c1106
-rw-r--r--xmss_fast.h111
-rw-r--r--xmss_hash.c140
-rw-r--r--xmss_hash.h22
-rw-r--r--xmss_hash_address.c66
-rw-r--r--xmss_hash_address.h40
-rw-r--r--xmss_wots.c192
-rw-r--r--xmss_wots.h64
711 files changed, 74532 insertions, 89583 deletions
diff --git a/.depend b/.depend
new file mode 100644
index 00000000..1ccc1dcc
--- /dev/null
+++ b/.depend
@@ -0,0 +1,180 @@
+# Automatically generated by makedepend.
+# 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
+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
+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
+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
+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
+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
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..34a95721
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,33 @@
+Makefile
+buildpkg.sh
+config.h
+config.h.in
+config.log
+config.status
+configure
+openbsd-compat/Makefile
+openbsd-compat/regress/Makefile
+openssh.xml
+opensshd.init
+survey.sh
+**/*.0
+**/*.o
+**/*.lo
+**/*.so
+**/*.out
+**/*.a
+autom4te.cache/
+scp
+sftp
+sftp-server
+ssh
+ssh-add
+ssh-agent
+ssh-keygen
+ssh-keyscan
+ssh-keysign
+ssh-pkcs11-helper
+ssh-sk-helper
+sshd
+!regress/misc/fuzz-harness/Makefile
+tags
diff --git a/.skipped-commit-ids b/.skipped-commit-ids
new file mode 100644
index 00000000..611d1093
--- /dev/null
+++ b/.skipped-commit-ids
@@ -0,0 +1,47 @@
+5317f294d63a876bfc861e19773b1575f96f027d remove libssh from makefiles
+a337e886a49f96701ccbc4832bed086a68abfa85 Makefile changes
+f2c9feb26963615c4fece921906cf72e248b61ee more Makefile
+fa728823ba21c4b45212750e1d3a4b2086fd1a62 more Makefile refactoring
+1de0e85522051eb2ffa00437e1885e9d7b3e0c2e moduli update
+814b2f670df75759e1581ecef530980b2b3d7e0f remove redundant make defs
+04431e8e7872f49a2129bf080a6b73c19d576d40 moduli update
+c07772f58028fda683ee6abd41c73da3ff70d403 moduli update
+db6375fc302e3bdf07d96430c63c991b2c2bd3ff moduli update
+5ea3d63ab972691f43e9087ab5fd8376d48e898f uuencode.c Makefile accident
+99dd10e72c04e93849981d43d64c946619efa474 include sshbuf-misc.c
+9e1c23476bb845f3cf3d15d9032da3ed0cb2fcf5 sshbuf-misc.c in regress
+569f08445c27124ec7c7f6c0268d844ec56ac061 Makefile tweaks for !openssl
+58ec755be4e51978ecfee73539090eb68652a987 moduli update
+4bd5551b306df55379afe17d841207990eb773bf Makefile.inc
+14806a59353152f843eb349e618abbf6f4dd3ada Makefile.inc
+8ea4455a2d9364a0a04f9e4a2cbfa4c9fcefe77e Makefile.inc
+d9b910e412d139141b072a905e66714870c38ac0 Makefile.inc
+7b7b619c1452a459310b0cf4391c5757c6bdbc0f moduli update
+5010ff08f7ad92082e87dde098b20f5c24921a8f moduli regen script update
+3bcae7a754db3fc5ad3cab63dd46774edb35b8ae moduli regen script update
+
+Old upstream tree:
+
+321065a95a7ccebdd5fd08482a1e19afbf524e35 Update DH groups
+d4f699a421504df35254cf1c6f1a7c304fb907ca Remove 1k bit groups
+aafe246655b53b52bc32c8a24002bc262f4230f7 Remove intermediate moduli
+8fa9cd1dee3c3339ae329cf20fb591db6d605120 put back SSH1 for 6.9
+f31327a48dd4103333cc53315ec53fe65ed8a17a Generate new moduli
+edbfde98c40007b7752a4ac106095e060c25c1ef Regen moduli
+052fd565e3ff2d8cec3bc957d1788f50c827f8e2 Switch to tame-based sandbox
+7cf73737f357492776223da1c09179fa6ba74660 Remove moduli <2k
+180d84674be1344e45a63990d60349988187c1ae Update moduli
+f6ae971186ba68d066cd102e57d5b0b2c211a5ee systrace is dead.
+96c5054e3e1f170c6276902d5bc65bb3b87a2603 remove DEBUGLIBS from Makefile
+6da9a37f74aef9f9cc639004345ad893cad582d8 Update moduli file
+77bcb50e47b68c7209c7f0a5a020d73761e5143b unset REGRESS_FAIL_EARLY
+38c2133817cbcae75c88c63599ac54228f0fa384 Change COMPILER_VERSION tests
+30c20180c87cbc99fa1020489fe7fd8245b6420c resync integrity.sh shell
+1e6b51ddf767cbad0a4e63eb08026c127e654308 integrity.sh reliability
+fe5b31f69a60d47171836911f144acff77810217 Makefile.inc bits
+5781670c0578fe89663c9085ed3ba477cf7e7913 Delete sshconnect1.c
+ea80f445e819719ccdcb237022cacfac990fdc5c Makefile.inc warning flags
+b92c93266d8234d493857bb822260dacf4366157 moduli-gen.sh tweak
+b25bf747544265b39af74fe0716dc8d9f5b63b95 Updated moduli
+1bd41cba06a7752de4df304305a8153ebfb6b0ac rsa.[ch] already removed
+e39b3902fe1d6c4a7ba6a3c58e072219f3c1e604 Makefile changes
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 00000000..a38451a8
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,261 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_defaults {
+ name: "ssh_defaults",
+ vendor: true,
+ cflags: [
+ "-Wno-incompatible-pointer-types",
+ "-Wno-pointer-sign",
+ "-Wno-unused-parameter",
+ ],
+ include_dirs: [
+ "external/openssh/openbsd-compat",
+ "external/openssh/prebuilt-intermediates",
+ ],
+ shared_libs: [
+ "libdl",
+ "libcrypto",
+ "libssl",
+ "libz",
+ ],
+}
+
+cc_library {
+ name: "libssh",
+ defaults: ["ssh_defaults"],
+ cflags: ["-DENABLE_SK"],
+ srcs: [
+ "addrmatch.c",
+ "atomicio.c",
+ "authfd.c",
+ "authfile.c",
+ "bitmap.c",
+ "canohost.c",
+ "chacha.c",
+ "channels.c",
+ "cipher-aes.c",
+ "cipher-aesctr.c",
+ "cipher-chachapoly.c",
+ "cipher-ctr.c",
+ "cipher.c",
+ "cleanup.c",
+ "compat.c",
+ "dh.c",
+ "digest-openssl.c",
+ "dispatch.c",
+ "dns.c",
+ "ed25519.c",
+ "entropy.c",
+ "fatal.c",
+ "fe25519.c",
+ "ge25519.c",
+ "gss-genr.c",
+ "hash.c",
+ "hmac.c",
+ "hostfile.c",
+ "kex.c",
+ "kexc25519.c",
+ "kexdh.c",
+ "kexecdh.c",
+ "kexgen.c",
+ "kexgex.c",
+ "kexgexc.c",
+ "kexsntrup4591761x25519.c",
+ "krl.c",
+ "log.c",
+ "mac.c",
+ "match.c",
+ "misc.c",
+ "moduli.c",
+ "monitor_fdpass.c",
+ "msg.c",
+ "nchan.c",
+ "openbsd-compat/bcrypt_pbkdf.c",
+ "openbsd-compat/bindresvport.c",
+ "openbsd-compat/blowfish.c",
+ "openbsd-compat/bsd-closefrom.c",
+ "openbsd-compat/bsd-err.c",
+ "openbsd-compat/bsd-getpagesize.c",
+ "openbsd-compat/bsd-getpeereid.c",
+ "openbsd-compat/bsd-malloc.c",
+ "openbsd-compat/bsd-misc.c",
+ "openbsd-compat/bsd-openpty.c",
+ "openbsd-compat/bsd-signal.c",
+ "openbsd-compat/bsd-statvfs.c",
+ "openbsd-compat/explicit_bzero.c",
+ "openbsd-compat/fmt_scaled.c",
+ "openbsd-compat/freezero.c",
+ "openbsd-compat/getopt_long.c",
+ "openbsd-compat/glob.c",
+ "openbsd-compat/libressl-api-compat.c",
+ "openbsd-compat/openssl-compat.c",
+ "openbsd-compat/port-linux.c",
+ "openbsd-compat/port-net.c",
+ "openbsd-compat/pwcache.c",
+ "openbsd-compat/readpassphrase.c",
+ "openbsd-compat/reallocarray.c",
+ "openbsd-compat/recallocarray.c",
+ "openbsd-compat/rresvport.c",
+ "openbsd-compat/setproctitle.c",
+ "openbsd-compat/strcasestr.c",
+ "openbsd-compat/strmode.c",
+ "openbsd-compat/strtonum.c",
+ "openbsd-compat/timingsafe_bcmp.c",
+ "openbsd-compat/vis.c",
+ "packet.c",
+ "platform-misc.c",
+ "platform-pledge.c",
+ "poly1305.c",
+ "readpass.c",
+ "rijndael.c",
+ "sc25519.c",
+ "sntrup4591761.c",
+ "smult_curve25519_ref.c",
+ "ssh-dss.c",
+ "ssh-ecdsa.c",
+ "ssh-ecdsa-sk.c",
+ "ssh-ed25519.c",
+ "ssh-ed25519-sk.c",
+ "ssh-rsa.c",
+ "ssh-sk.c",
+ "sshbuf-io.c",
+ "sshbuf-getput-basic.c",
+ "sshbuf-getput-crypto.c",
+ "sshbuf-misc.c",
+ "sshbuf.c",
+ "ssherr.c",
+ "sshkey.c",
+ "ttymodes.c",
+ "uidswap.c",
+ "umac.c",
+ "umac128.c",
+ "utf8.c",
+ "verify.c",
+ "xmalloc.c",
+ ],
+}
+
+cc_binary {
+ name: "ssh",
+ defaults: ["ssh_defaults"],
+ srcs: [
+ "clientloop.c",
+ "mux.c",
+ "readconf.c",
+ "ssh.c",
+ "sshconnect.c",
+ "sshconnect2.c",
+ "sshtty.c",
+ ],
+ shared_libs: ["libssh"],
+}
+
+cc_binary {
+ name: "sftp",
+ defaults: ["ssh_defaults"],
+ srcs: [
+ "sftp.c",
+ "sftp-client.c",
+ "sftp-common.c",
+ "sftp-glob.c",
+ "progressmeter.c",
+ ],
+ shared_libs: ["libssh"],
+}
+
+cc_binary {
+ name: "scp",
+ defaults: ["ssh_defaults"],
+ srcs: [
+ "scp.c",
+ "progressmeter.c",
+ ],
+ shared_libs: ["libssh"],
+}
+
+cc_binary {
+ name: "sshd",
+ defaults: ["ssh_defaults"],
+ srcs: [
+ "audit-bsm.c",
+ "audit-linux.c",
+ "audit.c",
+ "auth-bsdauth.c",
+ "auth-krb5.c",
+ "auth-options.c",
+ "auth-pam.c",
+ "auth-rhosts.c",
+ "auth-shadow.c",
+ "auth-sia.c",
+ "auth.c",
+ "auth2-chall.c",
+ "auth2-gss.c",
+ "auth2-hostbased.c",
+ "auth2-kbdint.c",
+ "auth2-none.c",
+ "auth2-passwd.c",
+ "auth2-pubkey.c",
+ "auth2.c",
+ "groupaccess.c",
+ "gss-serv-krb5.c",
+ "gss-serv.c",
+ "kexgexs.c",
+ "loginrec.c",
+ "md5crypt.c",
+ "monitor.c",
+ "monitor_wrap.c",
+ "platform.c",
+ "platform-tracing.c",
+ "sandbox-null.c",
+ "sandbox-rlimit.c",
+ "sandbox-systrace.c",
+ "servconf.c",
+ "serverloop.c",
+ "session.c",
+ "sftp-common.c",
+ "sftp-realpath.c",
+ "sftp-server.c",
+ "sshd.c",
+ "sshlogin.c",
+ "sshpty.c",
+ ],
+ shared_libs: [
+ "libcutils",
+ "libssh",
+ ],
+}
+
+cc_binary {
+ name: "ssh-keygen",
+ defaults: ["ssh_defaults"],
+ srcs: [
+ "ssh-keygen.c",
+ "sshsig.c",
+ ],
+ shared_libs: ["libssh"],
+}
+
+prebuilt_etc {
+ name: "sshd_config",
+ vendor: true,
+ src: "sshd_config.android",
+ relative_install_path: "ssh",
+}
+
+sh_binary {
+ name: "start-ssh",
+ vendor: true,
+ src: "start-ssh",
+}
diff --git a/Android.mk b/Android.mk
deleted file mode 100644
index 7b259d73..00000000
--- a/Android.mk
+++ /dev/null
@@ -1,310 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-###################### libssh ######################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- addrmatch.c \
- atomicio.c \
- authfd.c \
- authfile.c \
- bitmap.c \
- blocks.c \
- bufaux.c \
- bufbn.c \
- bufec.c \
- buffer.c \
- canohost.c \
- chacha.c \
- channels.c \
- cipher-aes.c \
- cipher-aesctr.c \
- cipher-chachapoly.c \
- cipher-ctr.c \
- cipher.c \
- cleanup.c \
- compat.c \
- crc32.c \
- deattack.c \
- dh.c \
- digest-openssl.c \
- dispatch.c \
- dns.c \
- ed25519.c \
- entropy.c \
- fatal.c \
- fe25519.c \
- ge25519.c \
- gss-genr.c \
- hash.c \
- hmac.c \
- hostfile.c \
- kex.c \
- kexc25519.c \
- kexc25519c.c \
- kexdh.c \
- kexdhc.c \
- kexecdh.c \
- kexecdhc.c \
- kexgex.c \
- kexgexc.c \
- key.c \
- krl.c \
- log.c \
- mac.c \
- match.c \
- md-sha256.c \
- misc.c \
- moduli.c \
- monitor_fdpass.c \
- msg.c \
- nchan.c \
- opacket.c \
- openbsd-compat/bcrypt_pbkdf.c \
- openbsd-compat/bindresvport.c \
- openbsd-compat/blowfish.c \
- openbsd-compat/bsd-closefrom.c \
- openbsd-compat/bsd-getpeereid.c \
- openbsd-compat/bsd-misc.c \
- openbsd-compat/bsd-openpty.c \
- openbsd-compat/bsd-statvfs.c \
- openbsd-compat/explicit_bzero.c \
- openbsd-compat/fmt_scaled.c \
- openbsd-compat/getopt_long.c \
- openbsd-compat/glob.c \
- openbsd-compat/openssl-compat.c \
- openbsd-compat/port-linux.c \
- openbsd-compat/port-tun.c \
- openbsd-compat/pwcache.c \
- openbsd-compat/readpassphrase.c \
- openbsd-compat/reallocarray.c \
- openbsd-compat/rresvport.c \
- openbsd-compat/setproctitle.c \
- openbsd-compat/strmode.c \
- openbsd-compat/strtonum.c \
- openbsd-compat/timingsafe_bcmp.c \
- openbsd-compat/vis.c \
- openbsd-compat/xmmap.c \
- packet.c \
- poly1305.c \
- readpass.c \
- rijndael.c \
- roaming_dummy.c \
- rsa.c \
- sc25519.c \
- smult_curve25519_ref.c \
- ssh-dss.c \
- ssh-ecdsa.c \
- ssh-ed25519.c \
- ssh-rsa.c \
- sshbuf-getput-basic.c \
- sshbuf-getput-crypto.c \
- sshbuf-misc.c \
- sshbuf.c \
- ssherr.c \
- sshkey.c \
- ttymodes.c \
- uidswap.c \
- umac.c \
- umac128.c \
- uuencode.c \
- verify.c \
- xmalloc.c
-
-LOCAL_C_INCLUDES := \
- external/zlib \
- external/openssl/include \
- external/openssh/openbsd-compat
-
-LOCAL_SHARED_LIBRARIES += libssl libcrypto libdl libz
-
-LOCAL_MODULE := libssh
-
-LOCAL_CFLAGS+=-O3 -Wno-unused-parameter
-
-LOCAL_CFLAGS += -DGCE_PLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
-
-include $(BUILD_SHARED_LIBRARY)
-
-###################### ssh ######################
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- ssh.c readconf.c clientloop.c sshtty.c \
- sshconnect.c sshconnect1.c sshconnect2.c mux.c \
- roaming_common.c roaming_client.c
-
-LOCAL_MODULE := ssh
-
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-
-LOCAL_C_INCLUDES := \
- external/zlib \
- external/openssl/include \
- external/openssh/openbsd-compat
-
-LOCAL_SHARED_LIBRARIES += libssh libssl libcrypto libdl libz
-
-include $(BUILD_EXECUTABLE)
-
-###################### sftp ######################
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- sftp.c sftp-client.c sftp-common.c sftp-glob.c progressmeter.c
-
-LOCAL_MODULE := sftp
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-
-LOCAL_C_INCLUDES := \
- external/zlib \
- external/openssl/include \
- external/openssh/openbsd-compat
-
-LOCAL_SHARED_LIBRARIES += libssh libssl libcrypto libdl libz
-
-include $(BUILD_EXECUTABLE)
-
-###################### scp ######################
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- scp.c progressmeter.c
-
-LOCAL_MODULE := scp
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-
-LOCAL_C_INCLUDES := \
- external/zlib \
- external/openssl/include \
- external/openssh/openbsd-compat
-
-LOCAL_SHARED_LIBRARIES += libssh libssl libcrypto libdl libz
-
-include $(BUILD_EXECUTABLE)
-
-###################### sshd ######################
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- audit-bsm.c \
- audit-linux.c \
- audit.c \
- auth-bsdauth.c \
- auth-chall.c \
- auth-krb5.c \
- auth-options.c \
- auth-pam.c \
- auth-rh-rsa.c \
- auth-rhosts.c \
- auth-rsa.c \
- auth-shadow.c \
- auth-sia.c \
- auth-skey.c \
- auth.c \
- auth1.c \
- auth2-chall.c \
- auth2-gss.c \
- auth2-hostbased.c \
- auth2-kbdint.c \
- auth2-none.c \
- auth2-passwd.c \
- auth2-pubkey.c \
- auth2.c \
- groupaccess.c \
- gss-serv-krb5.c \
- gss-serv.c \
- kexc25519s.c \
- kexdhs.c \
- kexecdhs.c \
- kexgexs.c \
- loginrec.c \
- md5crypt.c \
- monitor.c \
- monitor_mm.c \
- monitor_wrap.c \
- platform.c \
- roaming_common.c \
- roaming_serv.c \
- sandbox-null.c \
- sandbox-rlimit.c \
- sandbox-systrace.c \
- servconf.c \
- serverloop.c \
- session.c \
- sftp-common.c \
- sftp-server.c \
- sshd.c \
- sshlogin.c \
- sshpty.c
-
-LOCAL_MODULE := sshd
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-
-LOCAL_C_INCLUDES := \
- external/zlib \
- external/openssl/include \
- external/openssh/openbsd-compat
-
-LOCAL_SHARED_LIBRARIES += libssh libssl libcrypto libdl libz libcutils
-
-include $(BUILD_EXECUTABLE)
-
-###################### ssh-keygen ######################
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- ssh-keygen.c
-
-LOCAL_MODULE := ssh-keygen
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-
-LOCAL_C_INCLUDES := \
- external/zlib \
- external/openssl/include \
- external/openssh/openbsd-compat
-
-LOCAL_SHARED_LIBRARIES += libssh libssl libcrypto libdl libz
-
-include $(BUILD_EXECUTABLE)
-
-###################### sshd_config ######################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := sshd_config
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/ssh
-LOCAL_SRC_FILES := sshd_config.android
-include $(BUILD_PREBUILT)
-
-###################### start-ssh ######################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := start-ssh
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_SRC_FILES := start-ssh
-include $(BUILD_PREBUILT)
diff --git a/CREDITS b/CREDITS
index eaf105a9..6cc35125 100644
--- a/CREDITS
+++ b/CREDITS
@@ -33,7 +33,7 @@ David Agraz <dagraz@jahoopa.com> - Build fixes
David Del Piero <David.DelPiero@qed.qld.gov.au> - bug fixes
David Hesprich <darkgrue@gue-tech.org> - Configure fixes
David Rankin <drankin@bohemians.lexington.ky.us> - libwrap, AIX, NetBSD fixes
-Dag-Erling Smørgrav <des at freebsd.org> - Challenge-Response PAM code.
+Dag-Erling Smørgrav <des at freebsd.org> - Challenge-Response PAM code.
Dhiraj Gulati <dgulati@sco.com> - UnixWare long passwords
Ed Eden <ede370@stl.rural.usda.gov> - configure fixes
Garrick James <garrick@james.net> - configure fixes
@@ -100,6 +100,3 @@ Zack Weinberg <zack@wolery.cumb.org> - GNOME askpass enhancement
Apologies to anyone I have missed.
Damien Miller <djm@mindrot.org>
-
-$Id: CREDITS,v 1.81 2006/08/30 17:24:41 djm Exp $
-
diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644
index 092cc48e..00000000
--- a/ChangeLog
+++ /dev/null
@@ -1,8584 +0,0 @@
-commit 9f82e5a9042f2d872e98f48a876fcab3e25dd9bb
-Author: Tim Rice <tim@multitalents.net>
-Date: Mon Mar 16 22:49:20 2015 -0700
-
- portability fix: Solaris systems may not have a grep that understands -q
-
-commit 8ef691f7d9ef500257a549d0906d78187490668f
-Author: Damien Miller <djm@google.com>
-Date: Wed Mar 11 10:35:26 2015 +1100
-
- fix compile with clang
-
-commit 4df590cf8dc799e8986268d62019b487a8ed63ad
-Author: Damien Miller <djm@google.com>
-Date: Wed Mar 11 10:02:39 2015 +1100
-
- make unit tests work for !OPENSSH_HAS_ECC
-
-commit 307bb40277ca2c32e97e61d70d1ed74b571fd6ba
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Mar 7 04:41:48 2015 +0000
-
- upstream commit
-
- unbreak for w/SSH1 (default) case; ok markus@ deraadt@
-
-commit b44ee0c998fb4c5f3c3281f2398af5ce42840b6f
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Mar 5 18:39:20 2015 -0800
-
- unbreak hostkeys test for w/ SSH1 case
-
-commit 55e5bdeb519cb60cc18b7ba0545be581fb8598b4
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 6 01:40:56 2015 +0000
-
- upstream commit
-
- fix sshkey_certify() return value for unsupported key types;
- ok markus@ deraadt@
-
-commit be8f658e550a434eac04256bfbc4289457a24e99
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Mar 4 15:38:03 2015 -0800
-
- update version numbers to match version.h
-
-commit ac5e8acefa253eb5e5ba186e34236c0e8007afdc
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Mar 4 23:22:35 2015 +0000
-
- upstream commit
-
- make these work with !SSH1; ok markus@ deraadt@
-
-commit 2f04af92f036b0c87a23efb259c37da98cd81fe6
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Mar 4 21:12:59 2015 +0000
-
- upstream commit
-
- make ssh-add -D work with !SSH1 agent
-
-commit a05adf95d2af6abb2b7826ddaa7a0ec0cdc1726b
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Mar 4 00:55:48 2015 -0800
-
- netcat needs poll.h portability goop
-
-commit dad2b1892b4c1b7e58df483a8c5b983c4454e099
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue Mar 3 22:35:19 2015 +0000
-
- upstream commit
-
- make it possible to run tests w/o ssh1 support; ok djm@
-
-commit d48a22601bdd3eec054794c535f4ae8d8ae4c6e2
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Mar 4 18:53:53 2015 +0000
-
- upstream commit
-
- crank; ok markus, deraadt
-
-commit bbffb23daa0b002dd9f296e396a9ab8a5866b339
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Mar 3 13:50:27 2015 -0800
-
- more --without-ssh1 fixes
-
-commit 6c2039286f503e2012a58a1d109e389016e7a99b
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Mar 3 13:48:48 2015 -0800
-
- fix merge both that broke --without-ssh1 compile
-
-commit 111dfb225478a76f89ecbcd31e96eaf1311b59d3
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Mar 3 21:21:13 2015 +0000
-
- upstream commit
-
- add SSH1 Makefile knob to make it easier to build without
- SSH1 support; ok markus@
-
-commit 3f7f5e6c5d2aa3f6710289c1a30119e534e56c5c
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Mar 3 20:42:49 2015 +0000
-
- upstream commit
-
- expand __unused to full __attribute__ for better portability
-
-commit 2fab9b0f8720baf990c931e3f68babb0bf9949c6
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Mar 4 07:41:27 2015 +1100
-
- avoid warning
-
-commit d1bc844322461f882b4fd2277ba9a8d4966573d2
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Mar 4 06:31:45 2015 +1100
-
- Revert "define __unused to nothing if not already defined"
-
- This reverts commit 1598419e38afbaa8aa5df8dd6b0af98301e2c908.
-
- Some system headers have objects named __unused
-
-commit 00797e86b2d98334d1bb808f65fa1fd47f328ff1
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Mar 4 05:02:45 2015 +1100
-
- check for crypt and DES_crypt in openssl block
-
- fixes builds on systems that use DES_crypt; based on patch
- from Roumen Petrov
-
-commit 1598419e38afbaa8aa5df8dd6b0af98301e2c908
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Mar 4 04:59:13 2015 +1100
-
- define __unused to nothing if not already defined
-
- fixes builds on BSD/OS
-
-commit d608a51daad4f14ad6ab43d7cf74ef4801cc3fe9
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Mar 3 17:53:40 2015 +0000
-
- upstream commit
-
- reorder logic for better portability; patch from Roumen
- Petrov
-
-commit 68d2dfc464fbcdf8d6387884260f9801f4352393
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Mar 3 06:48:58 2015 +0000
-
- upstream commit
-
- Allow "ssh -Q protocol-version" to list supported SSH
- protocol versions. Useful for detecting builds without SSH v.1 support; idea
- and ok markus@
-
-commit 39e2f1229562e1195169905607bc12290d21f021
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Sun Mar 1 15:44:40 2015 +0000
-
- upstream commit
-
- Make sure we only call getnameinfo() for AF_INET or AF_INET6
- sockets. getpeername() of a Unix domain socket may return without error on
- some systems without actually setting ss_family so getnameinfo() was getting
- called with ss_family set to AF_UNSPEC. OK djm@
-
-commit e47536ba9692d271b8ad89078abdecf0a1c11707
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Feb 28 08:20:11 2015 -0800
-
- portability fixes for regress/netcat.c
-
- Mostly avoiding "err(1, NULL)"
-
-commit 02973ad5f6f49d8420e50a392331432b0396c100
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Feb 28 08:05:27 2015 -0800
-
- twiddle another test for portability
-
- from Tom G. Christensen
-
-commit f7f3116abf2a6e2f309ab096b08c58d19613e5d0
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 27 15:52:49 2015 -0800
-
- twiddle test for portability
-
-commit 1ad3a77cc9d5568f5437ff99d377aa7a41859b83
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Feb 26 20:33:22 2015 -0800
-
- make regress/netcat.c fd passing (more) portable
-
-commit 9e1cfca7e1fe9cf8edb634fc894e43993e4da1ea
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Feb 26 20:32:58 2015 -0800
-
- create OBJ/valgrind-out before running unittests
-
-commit bd58853102cee739f0e115e6d4b5334332ab1442
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Feb 25 16:58:22 2015 -0800
-
- valgrind support
-
-commit f43d17269194761eded9e89f17456332f4c83824
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Feb 26 20:45:47 2015 +0000
-
- upstream commit
-
- don't printf NULL key comments; reported by Tom Christensen
-
-commit 6e6458b476ec854db33e3e68ebf4f489d0ab3df8
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Feb 25 23:05:47 2015 +0000
-
- upstream commit
-
- zero cmsgbuf before use; we initialise the bits we use
- but valgrind still spams warning on it
-
-commit a63cfa26864b93ab6afefad0b630e5358ed8edfa
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Feb 25 19:54:02 2015 +0000
-
- upstream commit
-
- fix small memory leak when UpdateHostkeys=no
-
-commit e6b950341dd75baa8526f1862bca39e52f5b879b
-Author: Tim Rice <tim@multitalents.net>
-Date: Wed Feb 25 09:56:48 2015 -0800
-
- Revert "Work around finicky USL linker so netcat will build."
-
- This reverts commit d1db656021d0cd8c001a6692f772f1de29b67c8b.
-
- No longer needed with commit 678e473e2af2e4802f24dd913985864d9ead7fb3
-
-commit 6f621603f9cff2a5d6016a404c96cb2f8ac2dec0
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Feb 25 17:29:38 2015 +0000
-
- upstream commit
-
- don't leak validity of user in "too many authentication
- failures" disconnect message; reported by Sebastian Reitenbach
-
-commit 6288e3a935494df12519164f52ca5c8c65fc3ca5
-Author: naddy@openbsd.org <naddy@openbsd.org>
-Date: Tue Feb 24 15:24:05 2015 +0000
-
- upstream commit
-
- add -v (show ASCII art) to -l's synopsis; ok djm@
-
-commit 678e473e2af2e4802f24dd913985864d9ead7fb3
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Feb 26 04:12:58 2015 +1100
-
- Remove dependency on xmalloc.
-
- Remove ssh_get_progname's dependency on xmalloc, which should reduce
- link order problems. ok djm@
-
-commit 5d5ec165c5b614b03678afdad881f10e25832e46
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Feb 25 15:32:49 2015 +1100
-
- Restrict ECDSA and ECDH tests.
-
- ifdef out some more ECDSA and ECDH tests when built against an OpenSSL
- that does not have eliptic curve functionality.
-
-commit 1734e276d99b17e92d4233fac7aef3a3180aaca7
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Feb 25 13:40:45 2015 +1100
-
- Move definition of _NSIG.
-
- _NSIG is only unsed in one file, so move it there prevent redefinition
- warnings reported by Kevin Brott.
-
-commit a47ead7c95cfbeb72721066c4da2312e5b1b9f3d
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Feb 25 13:17:40 2015 +1100
-
- Add includes.h for compatibility stuff.
-
-commit 38806bda6d2e48ad32812b461eebe17672ada771
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 24 16:50:06 2015 -0800
-
- include netdb.h to look for MAXHOSTNAMELEN; ok tim
-
-commit d1db656021d0cd8c001a6692f772f1de29b67c8b
-Author: Tim Rice <tim@multitalents.net>
-Date: Tue Feb 24 10:42:08 2015 -0800
-
- Work around finicky USL linker so netcat will build.
-
-commit cb030ce25f555737e8ba97bdd7883ac43f3ff2a3
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 24 09:23:04 2015 -0800
-
- include includes.h to avoid build failure on AIX
-
-commit 13af342458f5064144abbb07e5ac9bbd4eb42567
-Author: Tim Rice <tim@multitalents.net>
-Date: Tue Feb 24 07:56:47 2015 -0800
-
- Original portability patch from djm@ for platforms missing err.h.
- Fix name space clash on Solaris 10. Still more to do for Solaris 10
- to deal with msghdr structure differences. ok djm@
-
-commit 910209203d0cd60c5083901cbcc0b7b44d9f48d2
-Author: Tim Rice <tim@multitalents.net>
-Date: Mon Feb 23 22:06:56 2015 -0800
-
- cleaner way fix dispatch.h portion of commit
- a88dd1da119052870bb2654c1a32c51971eade16
- (some systems have sig_atomic_t in signal.h, some in sys/signal.h)
- Sounds good to me djm@
-
-commit 676c38d7cbe65b76bbfff796861bb6615cc6a596
-Author: Tim Rice <tim@multitalents.net>
-Date: Mon Feb 23 21:51:33 2015 -0800
-
- portability fix: if we can't dind a better define for HOST_NAME_MAX, use 255
-
-commit 1221b22023dce38cbc90ba77eae4c5d78c77a5e6
-Author: Tim Rice <tim@multitalents.net>
-Date: Mon Feb 23 21:50:34 2015 -0800
-
- portablity fix: s/__inline__/inline/
-
-commit 4c356308a88d309c796325bb75dce90ca16591d5
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Feb 24 13:49:31 2015 +1100
-
- Wrap stdint.h includes in HAVE_STDINT_H.
-
-commit c9c88355c6a27a908e7d1e5003a2b35ea99c1614
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Feb 24 13:43:57 2015 +1100
-
- Add AI_NUMERICSERV to fake-rfc2553.
-
- Our getaddrinfo implementation always returns numeric values already.
-
-commit ef342ab1ce6fb9a4b30186c89c309d0ae9d0eeb4
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Feb 24 13:39:57 2015 +1100
-
- Include OpenSSL's objects.h before bn.h.
-
- Prevents compile errors on some platforms (at least old GCCs and AIX's
- XLC compilers).
-
-commit dcc8997d116f615195aa7c9ec019fb36c28c6228
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Feb 24 12:30:59 2015 +1100
-
- Convert two macros into functions.
-
- Convert packet_send_debug and packet_disconnect from macros to
- functions. Some older GCCs (2.7.x, 2.95.x) see to have problems with
- variadic macros with only one argument so we convert these two into
- functions. ok djm@
-
-commit 2285c30d51b7e2052c6526445abe7e7cc7e170a1
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 23 22:21:21 2015 +0000
-
- upstream commit
-
- further silence spurious error message even when -v is
- specified (e.g. to get visual host keys); reported by naddy@
-
-commit 9af21979c00652029e160295e988dea40758ece2
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 24 09:04:32 2015 +1100
-
- don't include stdint.h unless HAVE_STDINT_H set
-
-commit 62f678dd51660d6f8aee1da33d3222c5de10a89e
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 24 09:02:54 2015 +1100
-
- nother sys/queue.h -> sys-queue.h fix
-
- spotted by Tom Christensen
-
-commit b3c19151cba2c0ed01b27f55de0d723ad07ca98f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 23 20:32:15 2015 +0000
-
- upstream commit
-
- fix a race condition by using a mux socket rather than an
- ineffectual wait statement
-
-commit a88dd1da119052870bb2654c1a32c51971eade16
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 24 06:30:29 2015 +1100
-
- various include fixes for portable
-
-commit 5248429b5ec524d0a65507cff0cdd6e0cb99effd
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 23 16:55:51 2015 +0000
-
- upstream commit
-
- add an XXX to remind me to improve sshkey_load_public
-
-commit e94e4b07ef2eaead38b085a60535df9981cdbcdb
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 23 16:55:31 2015 +0000
-
- upstream commit
-
- silence a spurious error message when listing
- fingerprints for known_hosts; bz#2342
-
-commit f2293a65392b54ac721f66bc0b44462e8d1d81f8
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 23 16:33:25 2015 +0000
-
- upstream commit
-
- fix setting/clearing of TTY raw mode around
- UpdateHostKeys=ask confirmation question; reported by Herb Goldman
-
-commit f2004cd1adf34492eae0a44b1ef84e0e31b06088
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Feb 23 05:04:21 2015 +1100
-
- Repair for non-ECC OpenSSL.
-
- Ifdef out the ECC parts when building with an OpenSSL that doesn't have
- it.
-
-commit 37f9220db8d1a52c75894c3de1e5f2ae5bd71b6f
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Feb 23 03:07:24 2015 +1100
-
- Wrap stdint.h includes in ifdefs.
-
-commit f81f1bbc5b892c8614ea740b1f92735652eb43f0
-Author: Tim Rice <tim@multitalents.net>
-Date: Sat Feb 21 18:12:10 2015 -0800
-
- out of tree build fix
-
-commit 2e13a1e4d22f3b503c3bfc878562cc7386a1d1ae
-Author: Tim Rice <tim@multitalents.net>
-Date: Sat Feb 21 18:08:51 2015 -0800
-
- mkdir kex unit test directory so testing out of tree builds works
-
-commit 1797f49b1ba31e8700231cd6b1d512d80bb50d2c
-Author: halex@openbsd.org <halex@openbsd.org>
-Date: Sat Feb 21 21:46:57 2015 +0000
-
- upstream commit
-
- make "ssh-add -d" properly remove a corresponding
- certificate, and also not whine and fail if there is none
-
- ok djm@
-
-commit 7faaa32da83a609059d95dbfcb0649fdb04caaf6
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Feb 22 07:57:27 2015 +1100
-
- mkdir hostkey and bitmap unit test directories
-
-commit bd49da2ef197efac5e38f5399263a8b47990c538
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 20 23:46:01 2015 +0000
-
- upstream commit
-
- sort options useable under Match case-insensitively; prodded
- jmc@
-
-commit 1a779a0dd6cd8b4a1a40ea33b5415ab8408128ac
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Feb 21 20:51:02 2015 +0000
-
- upstream commit
-
- correct paths to configuration files being written/updated;
- they live in $OBJ not cwd; some by Roumen Petrov
-
-commit 28ba006c1acddff992ae946d0bc0b500b531ba6b
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Feb 21 15:41:07 2015 +1100
-
- More correct checking of HAVE_DECL_AI_NUMERICSERV.
-
-commit e50e8c97a9cecae1f28febccaa6ca5ab3bc10f54
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Feb 21 15:10:33 2015 +1100
-
- Add null declaration of AI_NUMERICINFO.
-
- Some platforms (older FreeBSD and DragonFly versions) do have
- getaddrinfo() but do not have AI_NUMERICINFO. so define it to zero
- in those cases.
-
-commit 18a208d6a460d707a45916db63a571e805f5db46
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 20 22:40:32 2015 +0000
-
- upstream commit
-
- more options that are available under Match; bz#2353 reported
- by calestyo AT scientia.net
-
-commit 44732de06884238049f285f1455b2181baa7dc82
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 20 22:17:21 2015 +0000
-
- upstream commit
-
- UpdateHostKeys fixes:
-
- I accidentally changed the format of the hostkeys@openssh.com messages
- last week without changing the extension name, and this has been causing
- connection failures for people who are running -current. First reported
- by sthen@
-
- s/hostkeys@openssh.com/hostkeys-00@openssh.com/
- Change the name of the proof message too, and reorder it a little.
-
- Also, UpdateHostKeys=ask is incompatible with ControlPersist (no TTY
- available to read the response) so disable UpdateHostKeys if it is in
- ask mode and ControlPersist is active (and document this)
-
-commit 13a39414d25646f93e6d355521d832a03aaaffe2
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Feb 17 00:14:05 2015 +0000
-
- upstream commit
-
- Regression: I broke logging of public key fingerprints in
- 1.46. Pointed out by Pontus Lundkvist
-
-commit 773dda25e828c4c9a52f7bdce6e1e5924157beab
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jan 30 23:10:17 2015 +1100
-
- repair --without-openssl; broken in refactor
-
-commit e89c780886b23600de1e1c8d74aabd1ff61f43f0
-Author: Damien Miller <djm@google.com>
-Date: Tue Feb 17 10:04:55 2015 +1100
-
- hook up hostkeys unittest to portable Makefiles
-
-commit 0abf41f99aa16ff09b263bead242d6cb2dbbcf99
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 16 22:21:03 2015 +0000
-
- upstream commit
-
- enable hostkeys unit tests
-
-commit 68a5d647ccf0fb6782b2f749433a1eee5bc9044b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 16 22:20:50 2015 +0000
-
- upstream commit
-
- check string/memory compare arguments aren't NULL
-
-commit ef575ef20d09f20722e26b45dab80b3620469687
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 16 22:18:34 2015 +0000
-
- upstream commit
-
- unit tests for hostfile.c code, just hostkeys_foreach so
- far
-
-commit 8ea3365e6aa2759ccf5c76eaea62cbc8a280b0e7
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Sat Feb 14 12:43:16 2015 +0000
-
- upstream commit
-
- test server rekey limit
-
-commit ce63c4b063c39b2b22d4ada449c9e3fbde788cb3
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 16 22:30:03 2015 +0000
-
- upstream commit
-
- partial backout of:
-
- revision 1.441
- date: 2015/01/31 20:30:05; author: djm; state: Exp; lines: +17 -10; commitid
- : x8klYPZMJSrVlt3O;
- Let sshd load public host keys even when private keys are missing.
- Allows sshd to advertise additional keys for future key rotation.
- Also log fingerprint of hostkeys loaded; ok markus@
-
- hostkey updates now require access to the private key, so we can't
- load public keys only. The improved log messages (fingerprints of keys
- loaded) are kept.
-
-commit 523463a3a2a9bfc6cfc5afa01bae9147f76a37cc
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 16 22:13:32 2015 +0000
-
- upstream commit
-
- Revise hostkeys@openssh.com hostkey learning extension.
-
- The client will not ask the server to prove ownership of the private
- halves of any hitherto-unseen hostkeys it offers to the client.
-
- Allow UpdateHostKeys option to take an 'ask' argument to let the
- user manually review keys offered.
-
- ok markus@
-
-commit 6c5c949782d86a6e7d58006599c7685bfcd01685
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 16 22:08:57 2015 +0000
-
- upstream commit
-
- Refactor hostkeys_foreach() and dependent code Deal with
- IP addresses (i.e. CheckHostIP) Don't clobber known_hosts when nothing
- changed ok markus@ as part of larger commit
-
-commit 51b082ccbe633dc970df1d1f4c9c0497115fe721
-Author: miod@openbsd.org <miod@openbsd.org>
-Date: Mon Feb 16 18:26:26 2015 +0000
-
- upstream commit
-
- Declare ge25519_base as extern, to prevent it from
- becoming a common. Gets us rid of ``lignment 4 of symbol
- `crypto_sign_ed25519_ref_ge25519_base' in mod_ge25519.o is smaller than 16 in
- mod_ed25519.o'' warnings at link time.
-
-commit 02db468bf7e3281a8e3c058ced571b38b6407c34
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Fri Feb 13 18:57:00 2015 +0000
-
- upstream commit
-
- make rekey_limit for sshd w/privsep work; ok djm@
- dtucker@
-
-commit 8ec67d505bd23c8bf9e17b7a364b563a07a58ec8
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Thu Feb 12 20:34:19 2015 +0000
-
- upstream commit
-
- Prevent sshd spamming syslog with
- "ssh_dispatch_run_fatal: disconnected". ok markus@
-
-commit d4c0295d1afc342057ba358237acad6be8af480b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Feb 11 01:20:38 2015 +0000
-
- upstream commit
-
- Some packet error messages show the address of the peer,
- but might be generated after the socket to the peer has suffered a TCP reset.
- In these cases, getpeername() won't work so cache the address earlier.
-
- spotted in the wild via deraadt@ and tedu@
-
-commit 4af1709cf774475ce5d1bc3ddcc165f6c222897d
-Author: jsg@openbsd.org <jsg@openbsd.org>
-Date: Mon Feb 9 23:22:37 2015 +0000
-
- upstream commit
-
- fix some leaks in error paths ok markus@
-
-commit fd36834871d06a03e1ff8d69e41992efa1bbf85f
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Fri Feb 6 23:21:59 2015 +0000
-
- upstream commit
-
- SIZE_MAX is standard, we should be using it in preference to
- the obsolete SIZE_T_MAX. OK miod@ beck@
-
-commit 1910a286d7771eab84c0b047f31c0a17505236fa
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Thu Feb 5 12:59:57 2015 +0000
-
- upstream commit
-
- Include stdint.h, not limits.h to get SIZE_MAX. OK guenther@
-
-commit ce4f59b2405845584f45e0b3214760eb0008c06c
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Tue Feb 3 08:07:20 2015 +0000
-
- upstream commit
-
- missing ; djm and mlarkin really having great
- interactions recently
-
-commit 5d34aa94938abb12b877a25be51862757f25d54b
-Author: halex@openbsd.org <halex@openbsd.org>
-Date: Tue Feb 3 00:34:14 2015 +0000
-
- upstream commit
-
- slightly extend the passphrase prompt if running with -c
- in order to give the user a chance to notice if unintentionally running
- without it
-
- wording tweak and ok djm@
-
-commit cb3bde373e80902c7d5d0db429f85068d19b2918
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 2 22:48:53 2015 +0000
-
- upstream commit
-
- handle PKCS#11 C_Login returning
- CKR_USER_ALREADY_LOGGED_IN; based on patch from Yuri Samoilenko; ok markus@
-
-commit 15ad750e5ec3cc69765b7eba1ce90060e7083399
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 2 07:41:40 2015 +0000
-
- upstream commit
-
- turn UpdateHostkeys off by default until I figure out
- mlarkin@'s warning message; requested by deraadt@
-
-commit 3cd5103c1e1aaa59bd66f7f52f6ebbcd5deb12f9
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Mon Feb 2 01:57:44 2015 +0000
-
- upstream commit
-
- increasing encounters with difficult DNS setups in
- darknets has convinced me UseDNS off by default is better ok djm
-
-commit 6049a548a8a68ff0bbe581ab1748ea6a59ecdc38
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jan 31 20:30:05 2015 +0000
-
- upstream commit
-
- Let sshd load public host keys even when private keys are
- missing. Allows sshd to advertise additional keys for future key rotation.
- Also log fingerprint of hostkeys loaded; ok markus@
-
-commit 46347ed5968f582661e8a70a45f448e0179ca0ab
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 30 11:43:14 2015 +0000
-
- upstream commit
-
- Add a ssh_config HostbasedKeyType option to control which
- host public key types are tried during hostbased authentication.
-
- This may be used to prevent too many keys being sent to the server,
- and blowing past its MaxAuthTries limit.
-
- bz#2211 based on patch by Iain Morgan; ok markus@
-
-commit 802660cb70453fa4d230cb0233bc1bbdf8328de1
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 30 10:44:49 2015 +0000
-
- upstream commit
-
- set a timeout to prevent hangs when talking to busted
- servers; ok markus@
-
-commit 86936ec245a15c7abe71a0722610998b0a28b194
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 30 01:11:39 2015 +0000
-
- upstream commit
-
- regression test for 'wildcard CA' serial/key ID revocations
-
-commit 4509b5d4a4fa645a022635bfa7e86d09b285001f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 30 01:13:33 2015 +0000
-
- upstream commit
-
- avoid more fatal/exit in the packet.c paths that
- ssh-keyscan uses; feedback and "looks good" markus@
-
-commit 669aee994348468af8b4b2ebd29b602cf2860b22
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 30 01:10:33 2015 +0000
-
- upstream commit
-
- permit KRLs that revoke certificates by serial number or
- key ID without scoping to a particular CA; ok markus@
-
-commit 7a2c368477e26575d0866247d3313da4256cb2b5
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 30 00:59:19 2015 +0000
-
- upstream commit
-
- missing parentheses after if in do_convert_from() broke
- private key conversion from other formats some time in 2010; bz#2345 reported
- by jjelen AT redhat.com
-
-commit 25f5f78d8bf5c22d9cea8b49de24ebeee648a355
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 30 00:22:25 2015 +0000
-
- upstream commit
-
- fix ssh protocol 1, spotted by miod@
-
-commit 9ce86c926dfa6e0635161b035e3944e611cbccf0
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 28 22:36:00 2015 +0000
-
- upstream commit
-
- update to new API (key_fingerprint => sshkey_fingerprint)
- check sshkey_fingerprint return values; ok markus
-
-commit 9125525c37bf73ad3ee4025520889d2ce9d10f29
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 28 22:05:31 2015 +0000
-
- upstream commit
-
- avoid fatal() calls in packet code makes ssh-keyscan more
- reliable against server failures ok dtucker@ markus@
-
-commit fae7bbe544cba7a9e5e4ab47ff6faa3d978646eb
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 28 21:15:47 2015 +0000
-
- upstream commit
-
- avoid fatal() calls in packet code makes ssh-keyscan more
- reliable against server failures ok dtucker@ markus@
-
-commit 1a3d14f6b44a494037c7deab485abe6496bf2c60
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 28 11:07:25 2015 +0000
-
- upstream commit
-
- remove obsolete comment
-
-commit 80c25b7bc0a71d75c43a4575d9a1336f589eb639
-Author: okan@openbsd.org <okan@openbsd.org>
-Date: Tue Jan 27 12:54:06 2015 +0000
-
- upstream commit
-
- Since r1.2 removed the use of PRI* macros, inttypes.h is
- no longer required.
-
- ok djm@
-
-commit 69ff64f69615c2a21c97cb5878a0996c21423257
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jan 27 23:07:43 2015 +1100
-
- compile on systems without TCP_MD5SIG (e.g. OSX)
-
-commit 358964f3082fb90b2ae15bcab07b6105cfad5a43
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jan 27 23:07:25 2015 +1100
-
- use ssh-keygen under test rather than system's
-
-commit a2c95c1bf33ea53038324d1fdd774bc953f98236
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jan 27 23:06:59 2015 +1100
-
- OSX lacks HOST_NAME_MAX, has _POSIX_HOST_NAME_MAX
-
-commit ade31d7b6f608a19b85bee29a7a00b1e636a2919
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jan 27 23:06:23 2015 +1100
-
- these need active_state defined to link on OSX
-
- temporary measure until active_state goes away entirely
-
-commit e56aa87502f22c5844918c10190e8b4f785f067b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 27 12:01:36 2015 +0000
-
- upstream commit
-
- use printf instead of echo -n to reduce diff against
- -portable
-
-commit 9f7637f56eddfaf62ce3c0af89c25480f2cf1068
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Mon Jan 26 13:55:29 2015 +0000
-
- upstream commit
-
- sort previous;
-
-commit 3076ee7d530d5b16842fac7a6229706c7e5acd26
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 26 13:36:53 2015 +0000
-
- upstream commit
-
- properly restore umask
-
-commit d411d395556b73ba1b9e451516a0bd6697c4b03d
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 26 06:12:18 2015 +0000
-
- upstream commit
-
- regression test for host key rotation
-
-commit fe8a3a51699afbc6407a8fae59b73349d01e49f8
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 26 06:11:28 2015 +0000
-
- upstream commit
-
- adapt to sshkey API tweaks
-
-commit 7dd355fb1f0038a3d5cdca57ebab4356c7a5b434
-Author: miod@openbsd.org <miod@openbsd.org>
-Date: Sat Jan 24 10:39:21 2015 +0000
-
- upstream commit
-
- Move -lz late in the linker commandline for things to
- build on static arches.
-
-commit 0dad3b806fddb93c475b30853b9be1a25d673a33
-Author: miod@openbsd.org <miod@openbsd.org>
-Date: Fri Jan 23 21:21:23 2015 +0000
-
- upstream commit
-
- -Wpointer-sign is supported by gcc 4 only.
-
-commit 2b3b1c1e4bd9577b6e780c255c278542ea66c098
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 20 22:58:57 2015 +0000
-
- upstream commit
-
- use SUBDIR to recuse into unit tests; makes "make obj"
- actually work
-
-commit 1d1092bff8db27080155541212b420703f8b9c92
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 26 12:16:36 2015 +0000
-
- upstream commit
-
- correct description of UpdateHostKeys in ssh_config.5 and
- add it to -o lists for ssh, scp and sftp; pointed out by jmc@
-
-commit 5104db7cbd6cdd9c5971f4358e74414862fc1022
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 26 06:10:03 2015 +0000
-
- upstream commit
-
- correctly match ECDSA subtype (== curve) for
- offered/recevied host keys. Fixes connection-killing host key mismatches when
- a server offers multiple ECDSA keys with different curve type (an extremely
- unlikely configuration).
-
- ok markus, "looks mechanical" deraadt@
-
-commit 8d4f87258f31cb6def9b3b55b6a7321d84728ff2
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 26 03:04:45 2015 +0000
-
- upstream commit
-
- Host key rotation support.
-
- Add a hostkeys@openssh.com protocol extension (global request) for
- a server to inform a client of all its available host key after
- authentication has completed. The client may record the keys in
- known_hosts, allowing it to upgrade to better host key algorithms
- and a server to gracefully rotate its keys.
-
- The client side of this is controlled by a UpdateHostkeys config
- option (default on).
-
- ok markus@
-
-commit 60b1825262b1f1e24fc72050b907189c92daf18e
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 26 02:59:11 2015 +0000
-
- upstream commit
-
- small refactor and add some convenience functions; ok
- markus
-
-commit a5a3e3328ddce91e76f71ff479022d53e35c60c9
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Thu Jan 22 21:00:42 2015 +0000
-
- upstream commit
-
- heirarchy -> hierarchy;
-
-commit dcff5810a11195c57e1b3343c0d6b6f2b9974c11
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Thu Jan 22 20:24:41 2015 +0000
-
- upstream commit
-
- Provide a warning about chroot misuses (which sadly, seem
- to have become quite popular because shiny). sshd cannot detect/manage/do
- anything about these cases, best we can do is warn in the right spot in the
- man page. ok markus
-
-commit 087266ec33c76fc8d54ac5a19efacf2f4a4ca076
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Tue Jan 20 23:14:00 2015 +0000
-
- upstream commit
-
- Reduce use of <sys/param.h> and transition to <limits.h>
- throughout. ok djm markus
-
-commit 57e783c8ba2c0797f93977e83b2a8644a03065d8
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue Jan 20 20:16:21 2015 +0000
-
- upstream commit
-
- kex_setup errors are fatal()
-
-commit 1d6424a6ff94633c221297ae8f42d54e12a20912
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 20 08:02:33 2015 +0000
-
- upstream commit
-
- this test would accidentally delete agent.sh if run without
- obj/
-
-commit 12b5f50777203e12575f1b08568281e447249ed3
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 20 07:56:44 2015 +0000
-
- upstream commit
-
- make this compile with KERBEROS5 enabled
-
-commit e2cc6bef08941256817d44d146115b3478586ad4
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 20 07:55:33 2015 +0000
-
- upstream commit
-
- fix hostkeys in agent; ok markus@
-
-commit 1ca3e2155aa5d3801a7ae050f85c71f41fcb95b1
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jan 20 10:11:31 2015 +1100
-
- fix kex test
-
-commit c78a578107c7e6dcf5d30a2f34cb6581bef14029
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 19 20:45:25 2015 +0000
-
- upstream commit
-
- finally enable the KEX tests I wrote some years ago...
-
-commit 31821d7217e686667d04935aeec99e1fc4a46e7e
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 19 20:42:31 2015 +0000
-
- upstream commit
-
- adapt to new error message (SSH_ERR_MAC_INVALID)
-
-commit d3716ca19e510e95d956ae14d5b367e364bff7f1
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 19 17:31:13 2015 +0000
-
- upstream commit
-
- this test was broken in at least two ways, such that it
- wasn't checking that a KRL was not excluding valid keys
-
-commit 3f797653748e7c2b037dacb57574c01d9ef3b4d3
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 19 20:32:39 2015 +0000
-
- upstream commit
-
- switch ssh-keyscan from setjmp to multiple ssh transport
- layer instances ok djm@
-
-commit f582f0e917bb0017b00944783cd5f408bf4b0b5e
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 19 20:30:23 2015 +0000
-
- upstream commit
-
- add experimental api for packet layer; ok djm@
-
-commit 48b3b2ba75181f11fca7f327058a591f4426cade
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 19 20:20:20 2015 +0000
-
- upstream commit
-
- store compat flags in struct ssh; ok djm@
-
-commit 57d10cbe861a235dd269c74fb2fe248469ecee9d
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 19 20:16:15 2015 +0000
-
- upstream commit
-
- adapt kex to sshbuf and struct ssh; ok djm@
-
-commit 3fdc88a0def4f86aa88a5846ac079dc964c0546a
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 19 20:07:45 2015 +0000
-
- upstream commit
-
- move dispatch to struct ssh; ok djm@
-
-commit 091c302829210c41e7f57c3f094c7b9c054306f0
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 19 19:52:16 2015 +0000
-
- upstream commit
-
- update packet.c & isolate, introduce struct ssh a) switch
- packet.c to buffer api and isolate per-connection info into struct ssh b)
- (de)serialization of the state is moved from monitor to packet.c c) the old
- packet.c API is implemented in opacket.[ch] d) compress.c/h is removed and
- integrated into packet.c with and ok djm@
-
-commit 4e62cc68ce4ba20245d208b252e74e91d3785b74
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 19 17:35:48 2015 +0000
-
- upstream commit
-
- fix format strings in (disabled) debugging
-
-commit d85e06245907d49a2cd0cfa0abf59150ad616f42
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 19 06:01:32 2015 +0000
-
- upstream commit
-
- be a bit more careful in these tests to ensure that
- known_hosts is clean
-
-commit 7947810eab5fe0ad311f32a48f4d4eb1f71be6cf
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jan 18 22:00:18 2015 +0000
-
- upstream commit
-
- regression test for known_host file editing using
- ssh-keygen (-H / -R / -F) after hostkeys_foreach() change; feedback and ok
- markus@
-
-commit 3a2b09d147a565d8a47edf37491e149a02c0d3a3
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jan 18 19:54:46 2015 +0000
-
- upstream commit
-
- more and better key tests
-
- test signatures and verification
- test certificate generation
- flesh out nested cert test
-
- removes most of the XXX todo markers
-
-commit 589e69fd82724cfc9738f128e4771da2e6405d0d
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jan 18 19:53:58 2015 +0000
-
- upstream commit
-
- make the signature fuzzing test much more rigorous:
- ensure that the fuzzed input cases do not match the original (using new
- fuzz_matches_original() function) and check that the verification fails in
- each case
-
-commit 80603c0daa2538c349c1c152405580b164d5475f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jan 18 19:52:44 2015 +0000
-
- upstream commit
-
- add a fuzz_matches_original() function to the fuzzer to
- detect fuzz cases that are identical to the original data. Hacky
- implementation, but very useful when you need the fuzz to be different, e.g.
- when verifying signature
-
-commit 87d5495bd337e358ad69c524fcb9495208c0750b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jan 18 19:50:55 2015 +0000
-
- upstream commit
-
- better dumps from the fuzzer (shown on errors) -
- include the original data as well as the fuzzed copy.
-
-commit d59ec478c453a3fff05badbbfd96aa856364f2c2
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jan 18 19:47:55 2015 +0000
-
- upstream commit
-
- enable hostkey-agent.sh test
-
-commit 26b3425170bf840e4b095e1c10bf25a0a3e3a105
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jan 17 18:54:30 2015 +0000
-
- upstream commit
-
- unit test for hostkeys in ssh-agent
-
-commit 9e06a0fb23ec55d9223b26a45bb63c7649e2f2f2
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Thu Jan 15 23:41:29 2015 +0000
-
- upstream commit
-
- add kex unit tests
-
-commit d2099dec6da21ae627f6289aedae6bc1d41a22ce
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Mon Jan 19 00:32:54 2015 +0000
-
- upstream commit
-
- djm, your /usr/include tree is old
-
-commit 2b3c3c76c30dc5076fe09d590f5b26880f148a54
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jan 18 21:51:19 2015 +0000
-
- upstream commit
-
- some feedback from markus@: comment hostkeys_foreach()
- context and avoid a member in it.
-
-commit cecb30bc2ba6d594366e657d664d5c494b6c8a7f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jan 18 21:49:42 2015 +0000
-
- upstream commit
-
- make ssh-keygen use hostkeys_foreach(). Removes some
- horrendous code; ok markus@
-
-commit ec3d065df3a9557ea96b02d061fd821a18c1a0b9
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jan 18 21:48:09 2015 +0000
-
- upstream commit
-
- convert load_hostkeys() (hostkey ordering and
- known_host matching) to use the new hostkey_foreach() iterator; ok markus
-
-commit c29811cc480a260e42fd88849fc86a80c1e91038
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jan 18 21:40:23 2015 +0000
-
- upstream commit
-
- introduce hostkeys_foreach() to allow iteration over a
- known_hosts file or controlled subset thereof. This will allow us to pull out
- some ugly and duplicated code, and will be used to implement hostkey rotation
- later.
-
- feedback and ok markus
-
-commit f101d8291da01bbbfd6fb8c569cfd0cc61c0d346
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Sun Jan 18 14:01:00 2015 +0000
-
- upstream commit
-
- string truncation due to sizeof(size) ok djm markus
-
-commit 35d6022b55b7969fc10c261cb6aa78cc4a5fcc41
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jan 18 13:33:34 2015 +0000
-
- upstream commit
-
- avoid trailing ',' in host key algorithms
-
-commit 7efb455789a0cb76bdcdee91c6060a3dc8f5c007
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jan 18 13:22:28 2015 +0000
-
- upstream commit
-
- infer key length correctly when user specified a fully-
- qualified key name instead of using the -b bits option; ok markus@
-
-commit 83f8ffa6a55ccd0ce9d8a205e3e7439ec18fedf5
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jan 17 18:53:34 2015 +0000
-
- upstream commit
-
- fix hostkeys on ssh agent; found by unit test I'm about
- to commit
-
-commit 369d61f17657b814124268f99c033e4dc6e436c1
-Author: schwarze@openbsd.org <schwarze@openbsd.org>
-Date: Fri Jan 16 16:20:23 2015 +0000
-
- upstream commit
-
- garbage collect empty .No macros mandoc warns about
-
-commit bb8b442d32dbdb8521d610e10d8b248d938bd747
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 16 15:55:07 2015 +0000
-
- upstream commit
-
- regression: incorrect error message on
- otherwise-successful ssh-keygen -A. Reported by Dmitry Orlov, via deraadt@
-
-commit 9010902954a40b59d0bf3df3ccbc3140a653e2bc
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 16 07:19:48 2015 +0000
-
- upstream commit
-
- when hostname canonicalisation is enabled, try to parse
- hostnames as addresses before looking them up for canonicalisation. fixes
- bz#2074 and avoids needless DNS lookups in some cases; ok markus
-
-commit 2ae4f337b2a5fb2841b6b0053b49496fef844d1c
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Fri Jan 16 06:40:12 2015 +0000
-
- upstream commit
-
- Replace <sys/param.h> with <limits.h> and other less
- dirty headers where possible. Annotate <sys/param.h> lines with their
- current reasons. Switch to PATH_MAX, NGROUPS_MAX, HOST_NAME_MAX+1,
- LOGIN_NAME_MAX, etc. Change MIN() and MAX() to local definitions of
- MINIMUM() and MAXIMUM() where sensible to avoid pulling in the pollution.
- These are the files confirmed through binary verification. ok guenther,
- millert, doug (helped with the verification protocol)
-
-commit 3c4726f4c24118e8f1bb80bf75f1456c76df072c
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Thu Jan 15 21:38:50 2015 +0000
-
- upstream commit
-
- remove xmalloc, switch to sshbuf
-
-commit e17ac01f8b763e4b83976b9e521e90a280acc097
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Thu Jan 15 21:37:14 2015 +0000
-
- upstream commit
-
- switch to sshbuf
-
-commit ddef9995a1fa6c7a8ff3b38bfe6cf724bebf13d0
-Author: naddy@openbsd.org <naddy@openbsd.org>
-Date: Thu Jan 15 18:32:54 2015 +0000
-
- upstream commit
-
- handle UMAC128 initialization like UMAC; ok djm@ markus@
-
-commit f14564c1f7792446bca143580aef0e7ac25dcdae
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jan 15 11:04:36 2015 +0000
-
- upstream commit
-
- fix regression reported by brad@ for passworded keys without
- agent present
-
-commit 45c0fd70bb2a88061319dfff20cb12ef7b1bc47e
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 15 22:08:23 2015 +1100
-
- make bitmap test compile
-
-commit d333f89abf7179021e5c3f28673f469abe032062
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jan 15 07:36:28 2015 +0000
-
- upstream commit
-
- unit tests for KRL bitmap
-
-commit 7613f828f49c55ff356007ae9645038ab6682556
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed Jan 14 09:58:21 2015 +0000
-
- upstream commit
-
- re-add comment about full path
-
-commit 6c43b48b307c41cd656b415621a644074579a578
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed Jan 14 09:54:38 2015 +0000
-
- upstream commit
-
- don't reset to the installed sshd; connect before
- reconfigure, too
-
-commit 771bb47a1df8b69061f09462e78aa0b66cd594bf
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 13 14:51:51 2015 +0000
-
- upstream commit
-
- implement a SIGINFO handler so we can discern a stuck
- fuzz test from a merely glacial one; prompted by and ok markus
-
-commit cfaa57962f8536f3cf0fd7daf4d6a55d6f6de45f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 13 08:23:26 2015 +0000
-
- upstream commit
-
- use $SSH instead of installed ssh to allow override;
- spotted by markus@
-
-commit 0920553d0aee117a596b03ed5b49b280d34a32c5
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 13 07:49:49 2015 +0000
-
- upstream commit
-
- regress test for PubkeyAcceptedKeyTypes; ok markus@
-
-commit 27ca1a5c0095eda151934bca39a77e391f875d17
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 12 20:13:27 2015 +0000
-
- upstream commit
-
- unbreak parsing of pubkey comments; with gerhard; ok
- djm/deraadt
-
-commit 55358f0b4e0b83bc0df81c5f854c91b11e0bb4dc
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 12 11:46:32 2015 +0000
-
- upstream commit
-
- fatal if soft-PKCS11 library is missing rather (rather
- than continue and fail with a more cryptic error)
-
-commit c3554cdd2a1a62434b8161017aa76fa09718a003
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 12 11:12:38 2015 +0000
-
- upstream commit
-
- let this test all supporte key types; pointed out/ok
- markus@
-
-commit 1129dcfc5a3e508635004bcc05a3574cb7687167
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jan 15 09:40:00 2015 +0000
-
- upstream commit
-
- sync ssh-keysign, ssh-keygen and some dependencies to the
- new buffer/key API; mostly mechanical, ok markus@
-
-commit e4ebf5586452bf512da662ac277aaf6ecf0efe7c
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jan 15 07:57:08 2015 +0000
-
- upstream commit
-
- remove commented-out test code now that it has moved to a
- proper unit test
-
-commit e81cba066c1e9eb70aba0f6e7c0ff220611b370f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 14 20:54:29 2015 +0000
-
- upstream commit
-
- whitespace
-
-commit 141efe49542f7156cdbc2e4cd0a041d8b1aab622
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 14 20:05:27 2015 +0000
-
- upstream commit
-
- move authfd.c and its tentacles to the new buffer/key
- API; ok markus@
-
-commit 0088c57af302cda278bd26d8c3ae81d5b6f7c289
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 14 19:33:41 2015 +0000
-
- upstream commit
-
- fix small regression: ssh-agent would return a success
- message but an empty signature if asked to sign using an unknown key; ok
- markus@
-
-commit b03ebe2c22b8166e4f64c37737f4278676e3488d
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 15 03:08:58 2015 +1100
-
- more --without-openssl
-
- fix some regressions caused by upstream merges
-
- enable KRLs now that they no longer require BIGNUMs
-
-commit bc42cc6fe784f36df225c44c93b74830027cb5a2
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 15 03:08:29 2015 +1100
-
- kludge around tun API mismatch betterer
-
-commit c332110291089b624fa0951fbf2d1ee6de525b9f
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 15 02:59:51 2015 +1100
-
- some systems lack SO_REUSEPORT
-
-commit 83b9678a62cbdc74eb2031cf1e1e4ffd58e233ae
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 15 02:35:50 2015 +1100
-
- fix merge botch
-
-commit 0cdc5a3eb6fb383569a4da2a30705d9b90428d6b
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 15 02:35:33 2015 +1100
-
- unbreak across API change
-
-commit 6e2549ac2b5e7f96cbc2d83a6e0784b120444b47
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 15 02:30:18 2015 +1100
-
- need includes.h for portable OpenSSH
-
-commit 72ef7c148c42db7d5632a29f137f8b87b579f2d9
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 15 02:21:31 2015 +1100
-
- support --without-openssl at configure time
-
- Disables and removes dependency on OpenSSL. Many features don't
- work and the set of crypto options is greatly restricted. This
- will only work on system with native arc4random or /dev/urandom.
-
- Considered highly experimental for now.
-
-commit 4f38c61c68ae7e3f9ee4b3c38bc86cd39f65ece9
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 15 02:28:00 2015 +1100
-
- add files missed in last commit
-
-commit a165bab605f7be55940bb8fae977398e8c96a46d
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 14 15:02:39 2015 +0000
-
- upstream commit
-
- avoid BIGNUM in KRL code by using a simple bitmap;
- feedback and ok markus
-
-commit 7d845f4a0b7ec97887be204c3760e44de8bf1f32
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 14 13:54:13 2015 +0000
-
- upstream commit
-
- update sftp client and server to new buffer API. pretty
- much just mechanical changes; with & ok markus
-
-commit 139ca81866ec1b219c717d17061e5e7ad1059e2a
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed Jan 14 13:09:09 2015 +0000
-
- upstream commit
-
- switch to sshbuf/sshkey; with & ok djm@
-
-commit 81bfbd0bd35683de5d7f2238b985e5f8150a9180
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jan 14 21:48:18 2015 +1100
-
- support --without-openssl at configure time
-
- Disables and removes dependency on OpenSSL. Many features don't
- work and the set of crypto options is greatly restricted. This
- will only work on system with native arc4random or /dev/urandom.
-
- Considered highly experimental for now.
-
-commit 54924b53af15ccdcbb9f89984512b5efef641a31
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 14 10:46:28 2015 +0000
-
- upstream commit
-
- avoid an warning for the !OPENSSL case
-
-commit ae8b463217f7c9b66655bfc3945c050ffdaeb861
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed Jan 14 10:30:34 2015 +0000
-
- upstream commit
-
- swith auth-options to new sshbuf/sshkey; ok djm@
-
-commit 540e891191b98b89ee90aacf5b14a4a68635e763
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 14 10:29:45 2015 +0000
-
- upstream commit
-
- make non-OpenSSL aes-ctr work on sshd w/ privsep; ok
- markus@
-
-commit 60c2c4ea5e1ad0ddfe8b2877b78ed5143be79c53
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed Jan 14 10:24:42 2015 +0000
-
- upstream commit
-
- remove unneeded includes, sync my copyright across files
- & whitespace; ok djm@
-
-commit 128343bcdb0b60fc826f2733df8cf979ec1627b4
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue Jan 13 19:31:40 2015 +0000
-
- upstream commit
-
- adapt mac.c to ssherr.h return codes (de-fatal) and
- simplify dependencies ok djm@
-
-commit e7fd952f4ea01f09ceb068721a5431ac2fd416ed
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 13 19:04:35 2015 +0000
-
- upstream commit
-
- sync changes from libopenssh; prepared by markus@ mostly
- debug output tweaks, a couple of error return value changes and some other
- minor stuff
-
-commit 76c0480a85675f03a1376167cb686abed01a3583
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jan 13 19:38:18 2015 +1100
-
- add --without-ssh1 option to configure
-
- Allows disabling support for SSH protocol 1.
-
-commit 1f729f0614d1376c3332fa1edb6a5e5cec7e9e03
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 13 07:39:19 2015 +0000
-
- upstream commit
-
- add sshd_config HostbasedAcceptedKeyTypes and
- PubkeyAcceptedKeyTypes options to allow sshd to control what public key types
- will be accepted. Currently defaults to all. Feedback & ok markus@
-
-commit 816d1538c24209a93ba0560b27c4fda57c3fff65
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 12 20:13:27 2015 +0000
-
- upstream commit
-
- unbreak parsing of pubkey comments; with gerhard; ok
- djm/deraadt
-
-commit 0097565f849851812df610b7b6b3c4bd414f6c62
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 12 19:22:46 2015 +0000
-
- upstream commit
-
- missing error assigment on sshbuf_put_string()
-
-commit a7f49dcb527dd17877fcb8d5c3a9a6f550e0bba5
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 12 15:18:07 2015 +0000
-
- upstream commit
-
- apparently memcpy(x, NULL, 0) is undefined behaviour
- according to C99 (cf. sections 7.21.1 and 7.1.4), so check skip memcpy calls
- when length==0; ok markus@
-
-commit 905fe30fca82f38213763616d0d26eb6790bde33
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 12 14:05:19 2015 +0000
-
- upstream commit
-
- free->sshkey_free; ok djm@
-
-commit f067cca2bc20c86b110174c3fef04086a7f57b13
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 12 13:29:27 2015 +0000
-
- upstream commit
-
- allow WITH_OPENSSL w/o WITH_SSH1; ok djm@
-
-commit c4bfafcc2a9300d9cfb3c15e75572d3a7d74670d
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jan 8 13:10:58 2015 +0000
-
- upstream commit
-
- adjust for sshkey_load_file() API change
-
-commit e752c6d547036c602b89e9e704851463bd160e32
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jan 8 13:44:36 2015 +0000
-
- upstream commit
-
- fix ssh_config FingerprintHash evaluation order; from Petr
- Lautrbach
-
-commit ab24ab847b0fc94c8d5e419feecff0bcb6d6d1bf
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jan 8 10:15:45 2015 +0000
-
- upstream commit
-
- reorder hostbased key attempts to better match the
- default hostkey algorithms order in myproposal.h; ok markus@
-
-commit 1195f4cb07ef4b0405c839293c38600b3e9bdb46
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jan 8 10:14:08 2015 +0000
-
- upstream commit
-
- deprecate key_load_private_pem() and
- sshkey_load_private_pem() interfaces. Refactor the generic key loading API to
- not require pathnames to be specified (they weren't really used).
-
- Fixes a few other things en passant:
-
- Makes ed25519 keys work for hostbased authentication (ssh-keysign
- previously used the PEM-only routines).
-
- Fixes key comment regression bz#2306: key pathnames were being lost as
- comment fields.
-
- ok markus@
-
-commit febbe09e4e9aff579b0c5cc1623f756862e4757d
-Author: tedu@openbsd.org <tedu@openbsd.org>
-Date: Wed Jan 7 18:15:07 2015 +0000
-
- upstream commit
-
- workaround for the Meyer, et al, Bleichenbacher Side
- Channel Attack. fake up a bignum key before RSA decryption. discussed/ok djm
- markus
-
-commit 5191df927db282d3123ca2f34a04d8d96153911a
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Dec 23 22:42:48 2014 +0000
-
- upstream commit
-
- KNF and add a little more debug()
-
-commit 8abd80315d3419b20e6938f74d37e2e2b547f0b7
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Mon Dec 22 09:26:31 2014 +0000
-
- upstream commit
-
- add fingerprinthash to the options list;
-
-commit 296ef0560f60980da01d83b9f0e1a5257826536f
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Mon Dec 22 09:24:59 2014 +0000
-
- upstream commit
-
- tweak previous;
-
-commit 462082eacbd37778a173afb6b84c6f4d898a18b5
-Author: Damien Miller <djm@google.com>
-Date: Tue Dec 30 08:16:11 2014 +1100
-
- avoid uninitialised free of ldns_res
-
- If an invalid rdclass was passed to getrrsetbyname() then
- this would execute a free on an uninitialised pointer.
- OpenSSH only ever calls this with a fixed and valid rdclass.
-
- Reported by Joshua Rogers
-
-commit 01b63498801053f131a0740eb9d13faf35d636c8
-Author: Damien Miller <djm@google.com>
-Date: Mon Dec 29 18:10:18 2014 +1100
-
- pull updated OpenBSD BCrypt PBKDF implementation
-
- Includes fix for 1 byte output overflow for large key length
- requests (not reachable in OpenSSH).
-
- Pointed out by Joshua Rogers
-
-commit c528c1b4af2f06712177b3de9b30705752f7cbcb
-Author: Damien Miller <djm@google.com>
-Date: Tue Dec 23 15:26:13 2014 +1100
-
- fix variable name for IPv6 case in construct_utmpx
-
- patch from writeonce AT midipix.org via bz#2296
-
-commit 293cac52dcda123244b2e594d15592e5e481c55e
-Author: Damien Miller <djm@google.com>
-Date: Mon Dec 22 16:30:42 2014 +1100
-
- include and use OpenBSD netcat in regress/
-
-commit 8f6784f0cb56dc4fd00af3e81a10050a5785228d
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 22 09:05:17 2014 +0000
-
- upstream commit
-
- mention ssh -Q feature to list supported { MAC, cipher,
- KEX, key } algorithms in more places and include the query string used to
- list the relevant information; bz#2288
-
-commit 449e11b4d7847079bd0a2daa6e3e7ea03d8ef700
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Mon Dec 22 08:24:17 2014 +0000
-
- upstream commit
-
- tweak previous;
-
-commit 4bea0ab3290c0b9dd2aa199e932de8e7e18062d6
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 22 08:06:03 2014 +0000
-
- upstream commit
-
- regression test for multiple required pubkey authentication;
- ok markus@
-
-commit f1c4d8ec52158b6f57834b8cd839605b0a33e7f2
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 22 08:04:23 2014 +0000
-
- upstream commit
-
- correct description of what will happen when a
- AuthorizedKeysCommand is specified but AuthorizedKeysCommandUser is not (sshd
- will refuse to start)
-
-commit 161cf419f412446635013ac49e8c660cadc36080
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 22 07:55:51 2014 +0000
-
- upstream commit
-
- make internal handling of filename arguments of "none"
- more consistent with ssh. "none" arguments are now replaced with NULL when
- the configuration is finalised.
-
- Simplifies checking later on (just need to test not-NULL rather than
- that + strcmp) and cleans up some inconsistencies. ok markus@
-
-commit f69b69b8625be447b8826b21d87713874dac25a6
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 22 07:51:30 2014 +0000
-
- upstream commit
-
- remember which public keys have been used for
- authentication and refuse to accept previously-used keys.
-
- This allows AuthenticationMethods=publickey,publickey to require
- that users authenticate using two _different_ pubkeys.
-
- ok markus@
-
-commit 46ac2ed4677968224c4ca825bc98fc68dae183f0
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 22 07:24:11 2014 +0000
-
- upstream commit
-
- fix passing of wildcard forward bind addresses when
- connection multiplexing is in use; patch from Sami Hartikainen via bz#2324;
- ok dtucker@
-
-commit 0d1b241a262e4d0a6bbfdd595489ab1b853c43a1
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 22 06:14:29 2014 +0000
-
- upstream commit
-
- make this slightly easier to diff against portable
-
-commit 0715bcdddbf68953964058f17255bf54734b8737
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Dec 22 13:47:07 2014 +1100
-
- add missing regress output file
-
-commit 1e30483c8ad2c2f39445d4a4b6ab20c241e40593
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 22 02:15:52 2014 +0000
-
- upstream commit
-
- adjust for new SHA256 key fingerprints and
- slightly-different MD5 hex fingerprint format
-
-commit 6b40567ed722df98593ad8e6a2d2448fc2b4b151
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 22 01:14:49 2014 +0000
-
- upstream commit
-
- poll changes to netcat (usr.bin/netcat.c r1.125) broke
- this test; fix it by ensuring more stdio fds are sent to devnull
-
-commit a5375ccb970f49dddf7d0ef63c9b713ede9e7260
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Sun Dec 21 23:35:14 2014 +0000
-
- upstream commit
-
- tweak previous;
-
-commit b79efde5c3badf5ce4312fe608d8307eade533c5
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Dec 21 23:12:42 2014 +0000
-
- upstream commit
-
- document FingerprintHash here too
-
-commit d16bdd8027dd116afa01324bb071a4016cdc1a75
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Dec 22 10:18:09 2014 +1100
-
- missing include for base64 encoding
-
-commit 56d1c83cdd1ac76f1c6bd41e01e80dad834f3994
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Dec 21 22:27:55 2014 +0000
-
- upstream commit
-
- Add FingerprintHash option to control algorithm used for
- key fingerprints. Default changes from MD5 to SHA256 and format from hex to
- base64.
-
- Feedback and ok naddy@ markus@
-
-commit 058f839fe15c51be8b3a844a76ab9a8db550be4f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 18 23:58:04 2014 +0000
-
- upstream commit
-
- don't count partial authentication success as a failure
- against MaxAuthTries; ok deraadt@
-
-commit c7219f4f54d64d6dde66dbcf7a2699daa782d2a1
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Dec 12 00:02:17 2014 +0000
-
- upstream commit
-
- revert chunk I didn't mean to commit yet; via jmc@
-
-commit 7de5991aa3997e2981440f39c1ea01273a0a2c7b
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 18 11:44:06 2014 +1100
-
- upstream libc change
-
- revision 1.2
- date: 2014/12/08 03:45:00; author: bcook; state: Exp; lines: +2 -2; commitid: 7zWEBgJJOCZ2hvTV;
- avoid left shift overflow in reallocarray.
-
- Some 64-bit platforms (e.g. Windows 64) have a 32-bit long. So, shifting
- 1UL 32-bits to the left causes an overflow. This replaces the constant 1UL with
- (size_t)1 so that we get the correct constant size for the platform.
-
- discussed with tedu@ & deraadt@
-
-commit 2048f85a5e6da8bc6e0532efe02ecfd4e63c978c
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 18 10:15:49 2014 +1100
-
- include CFLAGS in gnome askpass targets
-
- from Fedora
-
-commit 48b68ce19ca42fa488960028048dec023f7899bb
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 11 08:20:09 2014 +0000
-
- upstream commit
-
- explicitly include sys/param.h in files that use the
- howmany() macro; from portable
-
-commit d663bea30a294d440fef4398e5cd816317bd4518
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 11 05:25:06 2014 +0000
-
- upstream commit
-
- mention AuthorizedKeysCommandUser must be set for
- AuthorizedKeysCommand to be run; bz#2287
-
-commit 17bf3d81e00f2abb414a4fd271118cf4913f049f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 11 05:13:28 2014 +0000
-
- upstream commit
-
- show in debug output which hostkeys are being tried when
- attempting hostbased auth; patch from Iain Morgan
-
-commit da0277e3717eadf5b15e03379fc29db133487e94
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 11 04:16:14 2014 +0000
-
- upstream commit
-
- Make manual reflect reality: sftp-server's -d option
- accepts a "%d" option, not a "%h" one.
-
- bz#2316; reported by Kirk Wolf
-
-commit 4cf87f4b81fa9380bce5fcff7b0f8382ae3ad996
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Dec 10 01:24:09 2014 +0000
-
- upstream commit
-
- better error value for invalid signature length
-
-commit 4bfad14ca56f8ae04f418997816b4ba84e2cfc3c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Dec 10 02:12:51 2014 +1100
-
- Resync more with OpenBSD's rijndael.c, in particular "#if 0"-ing out some
- unused code. Should fix compile error reported by plautrba at redhat.
-
-commit 642652d280499691c8212ec6b79724b50008ce09
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Dec 10 01:32:23 2014 +1100
-
- Add reallocarray to compat library
-
-commit 3dfd8d93dfcc69261f5af99df56f3ff598581979
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 4 22:31:50 2014 +0000
-
- upstream commit
-
- add tests for new client RevokedHostKeys option; refactor
- to make it a bit more readable
-
-commit a31046cad1aed16a0b55171192faa6d02665ccec
-Author: krw@openbsd.org <krw@openbsd.org>
-Date: Wed Nov 19 13:35:37 2014 +0000
-
- upstream commit
-
- Nuke yet more obvious #include duplications.
-
- ok deraadt@
-
-commit a7c762e5b2c1093542c0bc1df25ccec0b4cf479f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 4 20:47:36 2014 +0000
-
- upstream commit
-
- key_in_file() wrapper is no longer used
-
-commit 5e39a49930d885aac9c76af3129332b6e772cd75
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 4 02:24:32 2014 +0000
-
- upstream commit
-
- add RevokedHostKeys option for the client
-
- Allow textfile or KRL-based revocation of hostkeys.
-
-commit 74de254bb92c684cf53461da97f52d5ba34ded80
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 4 01:49:59 2014 +0000
-
- upstream commit
-
- convert KRL code to new buffer API
-
- ok markus@
-
-commit db995f2eed5fc432598626fa3e30654503bf7151
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Wed Nov 26 18:34:51 2014 +0000
-
- upstream commit
-
- Prefer setvbuf() to setlinebuf() for portability; ok
- deraadt@
-
-commit 72bba3d179ced8b425272efe6956a309202a91f3
-Author: jsg@openbsd.org <jsg@openbsd.org>
-Date: Mon Nov 24 03:39:22 2014 +0000
-
- upstream commit
-
- Fix crashes in the handling of the sshd config file found
- with the afl fuzzer.
-
- ok deraadt@ djm@
-
-commit 867f49c666adcfe92bf539d9c37c1accdea08bf6
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Nov 26 13:22:41 2014 +1100
-
- Avoid Cygwin ssh-host-config reading /etc/group
-
- Patch from Corinna Vinschen
-
-commit 8b66f36291a721b1ba7c44f24a07fdf39235593e
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Nov 26 13:20:35 2014 +1100
-
- allow custom service name for sshd on Cygwin
-
- Permits the use of multiple sshd running with different service names.
-
- Patch by Florian Friesdorf via Corinna Vinschen
-
-commit 08c0eebf55d70a9ae1964399e609288ae3186a0c
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Sat Nov 22 19:21:03 2014 +0000
-
- upstream commit
-
- restore word zapped in previous, and remove some useless
- "No" macros;
-
-commit a1418a0033fba43f061513e992e1cbcc3343e563
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Sat Nov 22 18:15:41 2014 +0000
-
- upstream commit
-
- /dev/random has created the same effect as /dev/arandom
- (and /dev/urandom) for quite some time. Mop up the last few, by using
- /dev/random where we actually want it, or not even mentioning arandom where
- it is irrelevant.
-
-commit b6de5ac9ed421362f479d1ad4fa433d2e25dad5b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Nov 21 01:00:38 2014 +0000
-
- upstream commit
-
- fix NULL pointer dereference crash on invalid timestamp
-
- found using Michal Zalewski's afl fuzzer
-
-commit a1f8110cd5ed818d59b3a2964fab7de76e92c18e
-Author: mikeb@openbsd.org <mikeb@openbsd.org>
-Date: Tue Nov 18 22:38:48 2014 +0000
-
- upstream commit
-
- Sync AES code to the one shipped in OpenSSL/LibreSSL.
-
- This includes a commit made by Andy Polyakov <appro at openssl ! org>
- to the OpenSSL source tree on Wed, 28 Jun 2006 with the following
- message: "Mitigate cache-collision timing attack on last round."
-
- OK naddy, miod, djm
-
-commit 335c83d5f35d8620e16b8aa26592d4f836e09ad2
-Author: krw@openbsd.org <krw@openbsd.org>
-Date: Tue Nov 18 20:54:28 2014 +0000
-
- upstream commit
-
- Nuke more obvious #include duplications.
-
- ok deraadt@ millert@ tedu@
-
-commit 51b64e44121194ae4bf153dee391228dada2abcb
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Nov 17 00:21:40 2014 +0000
-
- upstream commit
-
- fix KRL generation when multiple CAs are in use
-
- We would generate an invalid KRL when revoking certs by serial
- number for multiple CA keys due to a section being written out
- twice.
-
- Also extend the regress test to catch this case by having it
- produce a multi-CA KRL.
-
- Reported by peter AT pean.org
-
-commit d2d51003a623e21fb2b25567c4878d915e90aa2a
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Nov 18 01:02:25 2014 +0000
-
- upstream commit
-
- fix NULL pointer dereference crash in key loading
-
- found by Michal Zalewski's AFL fuzzer
-
-commit 9f9fad0191028edc43d100d0ded39419b6895fdf
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Nov 17 00:21:40 2014 +0000
-
- upstream commit
-
- fix KRL generation when multiple CAs are in use
-
- We would generate an invalid KRL when revoking certs by serial
- number for multiple CA keys due to a section being written out
- twice.
-
- Also extend the regress test to catch this case by having it
- produce a multi-CA KRL.
-
- Reported by peter AT pean.org
-
-commit da8af83d3f7ec00099963e455010e0ed1d7d0140
-Author: bentley@openbsd.org <bentley@openbsd.org>
-Date: Sat Nov 15 14:41:03 2014 +0000
-
- upstream commit
-
- Reduce instances of `` '' in manuals.
-
- troff displays these as typographic quotes, but nroff implementations
- almost always print them literally, which rarely has the intended effect
- with modern fonts, even in stock xterm.
-
- These uses of `` '' can be replaced either with more semantic alternatives
- or with Dq, which prints typographic quotes in a UTF-8 locale (but will
- automatically fall back to `` '' in an ASCII locale).
-
- improvements and ok schwarze@
-
-commit fc302561369483bb755b17f671f70fb894aec01d
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Nov 10 22:25:49 2014 +0000
-
- upstream commit
-
- mux-related manual tweaks
-
- mention ControlPersist=0 is the same as ControlPersist=yes
-
- recommend that ControlPath sockets be placed in a og-w directory
-
-commit 0e4cff5f35ed11102fe3783779960ef07e0cd381
-Author: Damien Miller <djm@google.com>
-Date: Wed Nov 5 11:01:31 2014 +1100
-
- Prepare scripts for next Cygwin release
-
- Makes the Cygwin-specific ssh-user-config script independent of the
- existence of /etc/passwd. The next Cygwin release will allow to
- generate passwd and group entries from the Windows account DBs, so the
- scripts have to adapt.
-
- from Corinna Vinschen
-
-commit 7d0ba5336651731949762eb8877ce9e3b52df436
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 30 10:45:41 2014 +1100
-
- include version number in OpenSSL-too-old error
-
-commit 3bcb92e04d9207e9f78d82f7918c6d3422054ce9
-Author: lteo@openbsd.org <lteo@openbsd.org>
-Date: Fri Oct 24 02:01:20 2014 +0000
-
- upstream commit
-
- Remove unnecessary include: netinet/in_systm.h is not needed
- by these programs.
-
- NB. skipped for portable
-
- ok deraadt@ millert@
-
-commit 6fdcaeb99532e28a69f1a1599fbd540bb15b70a0
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Oct 20 03:43:01 2014 +0000
-
- upstream commit
-
- whitespace
-
-commit 165bc8786299e261706ed60342985f9de93a7461
-Author: daniel@openbsd.org <daniel@openbsd.org>
-Date: Tue Oct 14 03:09:59 2014 +0000
-
- upstream commit
-
- plug a memory leak; from Maxime Villard.
-
- ok djm@
-
-commit b1ba15f3885947c245c2dbfaad0a04ba050abea0
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Thu Oct 9 06:21:31 2014 +0000
-
- upstream commit
-
- tweak previous;
-
-commit 259a02ebdf74ad90b41d116ecf70aa823fa4c6e7
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Oct 13 00:38:35 2014 +0000
-
- upstream commit
-
- whitespace
-
-commit 957fbceb0f3166e41b76fdb54075ab3b9cc84cba
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 8 22:20:25 2014 +0000
-
- upstream commit
-
- Tweak config reparsing with host canonicalisation
-
- Make the second pass through the config files always run when
- hostname canonicalisation is enabled.
-
- Add a "Match canonical" criteria that allows ssh_config Match
- blocks to trigger only in the second config pass.
-
- Add a -G option to ssh that causes it to parse its configuration
- and dump the result to stdout, similar to "sshd -T"
-
- Allow ssh_config Port options set in the second config parse
- phase to be applied (they were being ignored).
-
- bz#2267 bz#2286; ok markus
-
-commit 5c0dafd38bf66feeeb45fa0741a5baf5ad8039ba
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 8 22:15:27 2014 +0000
-
- upstream commit
-
- another -Wpointer-sign from clang
-
-commit bb005dc815ebda9af3ae4b39ca101c4da918f835
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 8 22:15:06 2014 +0000
-
- upstream commit
-
- fix a few -Wpointer-sign warnings from clang
-
-commit 3cc1fbb4fb0e804bfb873fd363cea91b27fc8188
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 8 21:45:48 2014 +0000
-
- upstream commit
-
- parse cert sections using nested buffers to reduce
- copies; ok markus
-
-commit 4a45922aebf99164e2fc83d34fe55b11ae1866ef
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Oct 6 00:47:15 2014 +0000
-
- upstream commit
-
- correct options in usage(); from mancha1 AT zoho.com
-
-commit 48dffd5bebae6fed0556dc5c36cece0370690618
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Sep 9 09:45:36 2014 +0000
-
- upstream commit
-
- mention permissions on tun(4) devices in PermitTunnel
- documentation; bz#2273
-
-commit a5883d4eccb94b16c355987f58f86a7dee17a0c2
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 3 18:55:07 2014 +0000
-
- upstream commit
-
- tighten permissions on pty when the "tty" group does
- not exist; pointed out by Corinna Vinschen; ok markus
-
-commit 180bcb406b58bf30723c01a6b010e48ee626dda8
-Author: sobrado@openbsd.org <sobrado@openbsd.org>
-Date: Sat Aug 30 16:32:25 2014 +0000
-
- upstream commit
-
- typo.
-
-commit f70b22bcdd52f6bf127047b3584371e6e5d45627
-Author: sobrado@openbsd.org <sobrado@openbsd.org>
-Date: Sat Aug 30 15:33:50 2014 +0000
-
- upstream commit
-
- improve capitalization for the Ed25519 public-key
- signature system.
-
- ok djm@
-
-commit 7df8818409c752cf3f0c3f8044fe9aebed8647bd
-Author: doug@openbsd.org <doug@openbsd.org>
-Date: Thu Aug 21 01:08:52 2014 +0000
-
- upstream commit
-
- Free resources on error in mkstemp and fdopen
-
- ok djm@
-
-commit 40ba4c9733aaed08304714faeb61529f18da144b
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Wed Aug 20 01:28:55 2014 +0000
-
- upstream commit
-
- djm how did you make a typo like that...
-
-commit 57d378ec9278ba417a726f615daad67d157de666
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Aug 19 23:58:28 2014 +0000
-
- upstream commit
-
- When dumping the server configuration (sshd -T), print
- correct KEX, MAC and cipher defaults. Spotted by Iain Morgan
-
-commit 7ff880ede5195d0b17e7f1e3b6cfbc4cb6f85240
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Aug 19 23:57:18 2014 +0000
-
- upstream commit
-
- ~-expand lcd paths
-
-commit 4460a7ad0c78d4cd67c467f6e9f4254d0404ed59
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Oct 12 12:35:48 2014 +1100
-
- remove duplicated KEX_DH1 entry
-
-commit c9b8426a616138d0d762176c94f51aff3faad5ff
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 9 10:34:06 2014 +1100
-
- remove ChangeLog file
-
- Commit logs will be generated from git at release time.
-
-commit 81d18ff7c93a04affbf3903e0963859763219aed
-Author: Damien Miller <djm@google.com>
-Date: Tue Oct 7 21:24:25 2014 +1100
-
- delete contrib/caldera directory
-
-commit 0ec9e87d3638206456968202f05bb5123670607a
-Author: Damien Miller <djm@google.com>
-Date: Tue Oct 7 19:57:27 2014 +1100
-
- test commit
-
-commit 8fb65a44568701b779f3d77326bceae63412d28d
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 7 09:21:49 2014 +1100
-
- - (djm) Release OpenSSH-6.7
-
-commit e8c9f2602c46f6781df5e52e6cd8413dab4602a3
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Oct 3 09:24:56 2014 +1000
-
- - (djm) [sshd_config.5] typo; from Iain Morgan
-
-commit 703b98a26706f5083801d11059486d77491342ae
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 1 09:43:07 2014 +1000
-
- - (djm) [openbsd-compat/Makefile.in openbsd-compat/kludge-fd_set.c]
- [openbsd-compat/openbsd-compat.h] Kludge around bad glibc
- _FORTIFY_SOURCE check that doesn't grok heap-allocated fd_sets;
- ok dtucker@
-
-commit 0fa0ed061bbfedb0daa705e220748154a84c3413
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Sep 10 08:15:34 2014 +1000
-
- - (djm) [sandbox-seccomp-filter.c] Allow mremap and exit for DietLibc;
- patch from Felix von Leitner; ok dtucker
-
-commit ad7d23d461c3b7e1dcb15db13aee5f4b94dc1a95
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Sep 9 12:23:10 2014 +1000
-
- 20140908
- - (dtucker) [INSTALL] Update info about egd. ok djm@
-
-commit 2a8699f37cc2515e3bc60e0c677ba060f4d48191
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Sep 4 03:46:05 2014 +1000
-
- - (djm) [openbsd-compat/arc4random.c] Zero seed after keying PRNG
-
-commit 44988defb1f5e3afe576d86000365e1f07a1b494
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Sep 3 05:35:32 2014 +1000
-
- - (djm) [contrib/cygwin/ssh-host-config] Fix old code leading to
- permissions/ACLs; from Corinna Vinschen
-
-commit 23f269562b7537b2f6f5014e50a25e5dcc55a837
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Sep 3 05:33:25 2014 +1000
-
- - (djm) [defines.h sshbuf.c] Move __predict_true|false to defines.h and
- conditionalise to avoid duplicate definition.
-
-commit 41c8de2c0031cf59e7cf0c06b5bcfbf4852c1fda
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Aug 30 16:23:06 2014 +1000
-
- - (djm) [Makefile.in] Make TEST_SHELL a variable; "good idea" tim@
-
-commit d7c81e216a7bd9eed6e239c970d9261bb1651947
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Aug 30 04:18:28 2014 +1000
-
- - (djm) [openbsd-compat/openssl-compat.h] add include guard
-
-commit 4687802dda57365b984b897fc3c8e2867ea09b22
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Aug 30 03:29:19 2014 +1000
-
- - (djm) [misc.c] Missing newline between functions
-
-commit 51c77e29220dee87c53be2dc47092934acab26fe
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Aug 30 02:30:30 2014 +1000
-
- - (djm) [openbsd-compat/openssl-compat.h] add
- OPENSSL_[RD]SA_MAX_MODULUS_BITS defines for OpenSSL that lacks them
-
-commit 3d673d103bad35afaec6e7ef73e5277216ce33a3
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 27 06:32:01 2014 +1000
-
- - (djm) [openbsd-compat/explicit_bzero.c] implement explicit_bzero()
- using memset_s() where possible; improve fallback to indirect bzero
- via a volatile pointer to give it more of a chance to avoid being
- optimised away.
-
-commit 146218ac11a1eb0dcade6f793d7acdef163b5ddc
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 27 04:11:55 2014 +1000
-
- - (djm) [monitor.c sshd.c] SIGXFSZ needs to be ignored in postauth
- monitor, not preauth; bz#2263
-
-commit 1b215c098b3b37e38aa4e4c91bb908eee41183b1
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 27 04:04:40 2014 +1000
-
- - (djm) [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c]
- [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c]
- [regress/unittests/sshkey/common.c]
- [regress/unittests/sshkey/test_file.c]
- [regress/unittests/sshkey/test_fuzz.c]
- [regress/unittests/sshkey/test_sshkey.c] Don't include openssl/ec.h
- on !ECC OpenSSL systems
-
-commit ad013944af0a19e3f612089d0099bb397cf6502d
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Aug 26 09:27:28 2014 +1000
-
- - (djm) [INSTALL] Recommend libcrypto be built -fPIC, mention LibreSSL,
- update OpenSSL version requirement.
-
-commit ed126de8ee04c66640a0ea2697c4aaf36801f100
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Aug 26 08:37:47 2014 +1000
-
- - (djm) [bufec.c] Skip this file on !ECC OpenSSL
-
-commit 9c1dede005746864a4fdb36a7cdf6c51296ca909
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Aug 24 03:01:06 2014 +1000
-
- - (djm) [sftp-server.c] Some systems (e.g. Irix) have prctl() but not
- PR_SET_DUMPABLE, so adjust ifdef; reported by Tom Christensen
-
-commit d244a5816fd1312a33404b436e4dd83594f1119e
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Aug 23 17:06:49 2014 +1000
-
- - (djm) [configure.ac] We now require a working vsnprintf everywhere (not
- just for systems that lack asprintf); check for it always and extend
- test to catch more brokenness. Fixes builds on Solaris <= 9
-
-commit 4cec036362a358e398e6a2e6d19d8e5780558634
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Aug 23 03:11:09 2014 +1000
-
- - (djm) [sshd.c] Ignore SIGXFSZ in preauth monitor child; can explode on
- lastlog writing on platforms with high UIDs; bz#2263
-
-commit 394a60f2598d28b670d934b93942a3370b779b39
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Aug 22 18:06:20 2014 +1000
-
- - (djm) [configure.ac] double braces to appease autoconf
-
-commit 4d69aeabd6e60afcdc7cca177ca751708ab79a9d
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Aug 22 17:48:27 2014 +1000
-
- - (djm) [openbsd-compat/bsd-snprintf.c] Fix compilation failure (prototype/
- definition mismatch) and warning for broken/missing snprintf case.
-
-commit 0c11f1ac369d2c0aeb0ab0458a7cd04c72fe5e9e
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Aug 22 17:36:56 2014 +1000
-
- - (djm) [sshbuf-getput-crypto.c] Fix compilation when OpenSSL lacks ECC
-
-commit 6d62784b8973340b251fea6b04890f471adf28db
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Aug 22 17:36:19 2014 +1000
-
- - (djm) [configure.ac] include leading zero characters in OpenSSL version
- number; fixes test for unsupported versions
-
-commit 4f1ff1ed782117f5d5204d4e91156ed5da07cbb7
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Aug 21 15:54:50 2014 +1000
-
- - (djm) [regress/unittests/test_helper/test_helper.c] Fix for systems that
- don't set __progname. Diagnosed by Tom Christensen.
-
-commit 005a64da0f457410045ef0bfa93c863c2450447d
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Aug 21 10:48:41 2014 +1000
-
- - (djm) [key.h] Fix ifdefs for no-ECC OpenSSL
-
-commit aa6598ebb3343c7380e918388e10e8ca5852b613
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Aug 21 10:47:54 2014 +1000
-
- - (djm) [Makefile.in] fix reference to libtest_helper.a in sshkey test too.
-
-commit 54703e3cf63f0c80d4157e5ad7dbc2b363ee2c56
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 20 11:10:51 2014 +1000
-
- - (djm) [contrib/cygwin/README] Correct build instructions; from Corinna
-
-commit f0935698f0461f24d8d1f1107b476ee5fd4db1cb
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 20 11:06:50 2014 +1000
-
- - (djm) [sshkey.h] Fix compilation when OpenSSL lacks ECC
-
-commit c5089ecaec3b2c02f014f4e67518390702a4ba14
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 20 11:06:20 2014 +1000
-
- - (djm) [Makefile.in] refer to libtest_helper.a by explicit path rather than
- -L/-l; fixes linking problems on some platforms
-
-commit 2195847e503a382f83ee969b0a8bd3dfe0e55c18
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 20 11:05:03 2014 +1000
-
- - (djm) [configure.ac] Check OpenSSL version is supported at configure time;
- suggested by Kevin Brott
-
-commit a75aca1bbc989aa9f8b1b08489d37855f3d24d1a
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Aug 19 11:36:07 2014 +1000
-
- - (djm) [INSTALL contrib/caldera/openssh.spec contrib/cygwin/README]
- [contrib/redhat/openssh.spec contrib/suse/openssh.spec] Remove mentions
- of TCP wrappers.
-
-commit 3f022b5a9477abceeb1bbeab04b055f3cc7ca8f6
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Aug 19 11:32:34 2014 +1000
-
- - (djm) [ssh-dss.c] Include openssl/dsa.h for DSA_SIG
-
-commit 88137902632aceb923990e98cf5dc923bb3ef2f5
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Aug 19 11:28:11 2014 +1000
-
- - (djm) [sshbuf.h] Fix compilation on systems without OPENSSL_HAS_ECC.
-
-commit 2f3d1e7fb2eabd3cfbfd8d0f7bdd2f9a1888690b
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Aug 19 11:14:36 2014 +1000
-
- - (djm) [myproposal.h] Make curve25519 KEX dependent on
- HAVE_EVP_SHA256 instead of OPENSSL_HAS_ECC.
-
-commit d4e7d59d01a6c7f59e8c1f94a83c086e9a33d8aa
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Aug 19 11:14:17 2014 +1000
-
- - (djm) [serverloop.c] Fix syntax error on Cygwin; from Corinna Vinschen
-
-commit 9eaeea2cf2b6af5f166cfa9ad3c7a90711a147a9
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Aug 10 11:35:05 2014 +1000
-
- - (djm) [README contrib/caldera/openssh.spec]
- [contrib/redhat/openssh.spec contrib/suse/openssh.spec] Update versions
-
-commit f8988fbef0c9801d19fa2f8f4f041690412bec37
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Aug 1 13:31:52 2014 +1000
-
- - (djm) [regress/multiplex.sh] Use -d (detach stdin) flag to disassociate
- nc from stdin, it's more portable
-
-commit 5b3879fd4b7a4e3d43bab8f40addda39bc1169d0
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Aug 1 12:28:31 2014 +1000
-
- - (djm) [regress/multiplex.sh] Instruct nc not to quit as soon as stdin
- is closed; avoid regress failures when stdin is /dev/null
-
-commit a9c46746d266f8a1b092a72b2150682d1af8ebfc
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Aug 1 12:26:49 2014 +1000
-
- - (djm) [regress/multiplex.sh] Skip test for non-OpenBSD netcat. We need
- a better solution, but this will have to do for now.
-
-commit 426117b2e965e43f47015942b5be8dd88fe74b88
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 30 12:33:20 2014 +1000
-
- - schwarze@cvs.openbsd.org 2014/07/28 15:40:08
- [sftp-server.8 sshd_config.5]
- some systems no longer need /dev/log;
- issue noticed by jirib;
- ok deraadt
-
-commit f497794b6962eaf802ab4ac2a7b22ae591cca1d5
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 30 12:32:46 2014 +1000
-
- - dtucker@cvs.openbsd.org 2014/07/25 21:22:03
- [ssh-agent.c]
- Clear buffer used for handling messages. This prevents keys being
- left in memory after they have been expired or deleted in some cases
- (but note that ssh-agent is setgid so you would still need root to
- access them). Pointed out by Kevin Burns, ok deraadt
-
-commit a8a0f65c57c8ecba94d65948e9090da54014dfef
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 30 12:32:28 2014 +1000
-
- - OpenBSD CVS Sync
- - millert@cvs.openbsd.org 2014/07/24 22:57:10
- [ssh.1]
- Mention UNIX-domain socket forwarding too. OK jmc@ deraadt@
-
-commit 56b840f2b81e14a2f95c203403633a72566736f8
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 25 08:11:30 2014 +1000
-
- - (djm) [regress/multiplex.sh] restore incorrectly deleted line;
- pointed out by Christian Hesse
-
-commit dd417b60d5ca220565d1014e92b7f8f43dc081eb
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jul 23 10:41:21 2014 +1000
-
- - dtucker@cvs.openbsd.org 2014/07/22 23:35:38
- [regress/unittests/sshkey/testdata/*]
- Regenerate test keys with certs signed with ed25519 instead of ecdsa.
- These can be used in -portable on platforms that don't support ECDSA.
-
-commit 40e50211896369dba8f64f3b5e5fd58b76f5ac3f
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jul 23 10:35:45 2014 +1000
-
- - dtucker@cvs.openbsd.org 2014/07/22 23:57:40
- [regress/unittests/sshkey/mktestdata.sh]
- Add $OpenBSD tag to make syncs easier
-
-commit 07e644251e809b1d4c062cf85bd1146a7e3f5a8a
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jul 23 10:34:26 2014 +1000
-
- - dtucker@cvs.openbsd.org 2014/07/22 23:23:22
- [regress/unittests/sshkey/mktestdata.sh]
- Sign test certs with ed25519 instead of ecdsa so that they'll work in
- -portable on platforms that don't have ECDSA in their OpenSSL. ok djm
-
-commit cea099a7c4eaecb01b001e5453bb4e5c25006c22
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jul 23 10:04:02 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/22 01:32:12
- [regress/multiplex.sh]
- change the test for still-open Unix domain sockets to be robust against
- nc implementations that produce error messages. from -portable
- (Id sync only)
-
-commit 31eb78078d349b32ea41952ecc944b3ad6cb0d45
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jul 23 09:43:42 2014 +1000
-
- - guenther@cvs.openbsd.org 2014/07/22 07:13:42
- [umac.c]
- Convert from <sys/endian.h> to the shiney new <endian.h>
- ok dtucker@, who also confirmed that -portable handles this already
- (ID sync only, includes.h pulls in endian.h if available.)
-
-commit 820763efef2d19d965602533036c2b4badc9d465
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jul 23 09:40:46 2014 +1000
-
- - dtucker@cvs.openbsd.org 2014/07/22 01:18:50
- [key.c]
- Prevent spam from key_load_private_pem during hostbased auth. ok djm@
-
-commit c4ee219a66f3190fa96cbd45b4d11015685c6306
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jul 23 04:27:50 2014 +1000
-
- - (dtucker) [regress/unittests/sshkey/test_{file,fuzz,sshkey}.c] Wrap ecdsa-
- specific tests inside OPENSSL_HAS_ECC.
-
-commit 04f4824940ea3edd60835416ececbae16438968a
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jul 22 11:31:47 2014 +1000
-
- - (djm) [regress/multiplex.sh] change the test for still-open Unix
- domain sockets to be robust against nc implementations that produce
- error messages.
-
-commit 5ea4fe00d55453aaa44007330bb4c3181bd9b796
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jul 22 09:39:19 2014 +1000
-
- - (djm) [regress/multiplex.sh] ssh mux master lost -N somehow;
- put it back
-
-commit 948a1774a79a85f9deba6d74db95f402dee32c69
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Jul 22 01:07:11 2014 +1000
-
- - (dtucker) [sshkey.c] ifdef out unused variable when compiling without
- OPENSSL_HAS_ECC.
-
-commit c8f610f6cc57ae129758052439d9baf13699097b
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Jul 21 10:23:27 2014 +1000
-
- - (djm) [regress/multiplex.sh] Not all netcat accept the -N option.
-
-commit 0e4e95566cd95c887f69272499b8f3880b3ec0f5
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Jul 21 09:52:54 2014 +1000
-
- - millert@cvs.openbsd.org 2014/07/15 15:54:15
- [forwarding.sh multiplex.sh]
- Add support for Unix domain socket forwarding. A remote TCP port
- may be forwarded to a local Unix domain socket and vice versa or
- both ends may be a Unix domain socket. This is a reimplementation
- of the streamlocal patches by William Ahern from:
- http://www.25thandclement.com/~william/projects/streamlocal.html
- OK djm@ markus@
-
-commit 93a87ab27ecdc709169fb24411133998f81e2761
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Jul 21 06:30:25 2014 +1000
-
- - (dtucker) [regress/unittests/sshkey/
- {common,test_file,test_fuzz,test_sshkey}.c] Wrap stdint.h includes in
- ifdefs.
-
-commit 5573171352ea23df2dc6d2fe0324d023b7ba697c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Jul 21 02:24:59 2014 +1000
-
- - (dtucker) [cipher.c openbsd-compat/openssl-compat.h] Restore the bits
- needed to build AES CTR mode against OpenSSL 0.9.8f and above. ok djm
-
-commit 74e28682711d005026c7c8f15f96aea9d3c8b5a3
-Author: Tim Rice <tim@multitalents.net>
-Date: Fri Jul 18 20:00:11 2014 -0700
-
- - (tim) [openbsd-compat/port-uw.c] Include misc.h for fwd_opts, used
- in servconf.h.
-
-commit d1a0421f8e5e933fee6fb58ee6b9a22c63c8a613
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Jul 19 07:23:55 2014 +1000
-
- - (dtucker) [key.c sshkey.c] Put new ecdsa bits inside ifdef OPENSSL_HAS_ECC.
-
-commit f0fe9ea1be62227c130b317769de3d1e736b6dc1
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Jul 19 06:33:12 2014 +1000
-
- - (dtucker) [Makefile.in] Add a t-exec target to run just the executable
- tests.
-
-commit 450bc1180d4b061434a4b733c5c8814fa30b022b
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Jul 19 06:23:18 2014 +1000
-
- - (dtucker) [auth2-gss.c gss-serv-krb5.c] Include misc.h for fwd_opts, used
- in servconf.h.
-
-commit ab2ec586baad122ed169285c31927ccf58bc7b28
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 18 15:04:47 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/18 02:46:01
- [ssh-agent.c]
- restore umask around listener socket creation (dropped in streamlocal patch
- merge)
-
-commit 357610d15946381ae90c271837dcdd0cdce7145f
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 18 15:04:10 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/17 07:22:19
- [mux.c ssh.c]
- reflect stdio-forward ("ssh -W host:port ...") failures in exit status.
- previously we were always returning 0. bz#2255 reported by Brendan
- Germain; ok dtucker
-
-commit dad9a4a0b7c2b5d78605f8df28718f116524134e
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 18 15:03:49 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/17 00:12:03
- [key.c]
- silence "incorrect passphrase" error spam; reported and ok dtucker@
-
-commit f42f7684ecbeec6ce50e0310f80b3d6da2aaf533
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 18 15:03:27 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/17 00:10:18
- [mux.c]
- preserve errno across syscall
-
-commit 1b83320628cb0733e3688b85bfe4d388a7c51909
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 18 15:03:02 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/17 00:10:56
- [sandbox-systrace.c]
- ifdef SYS_sendsyslog so this will compile without patching on -stable
-
-commit 6d57656331bcd754d912950e4a18ad259d596e61
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 18 15:02:06 2014 +1000
-
- - jmc@cvs.openbsd.org 2014/07/16 14:48:57
- [ssh.1]
- add the streamlocal* options to ssh's -o list; millert says they're
- irrelevant for scp/sftp;
-
- ok markus millert
-
-commit 7acefbbcbeab725420ea07397ae35992f505f702
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 18 14:11:24 2014 +1000
-
- - millert@cvs.openbsd.org 2014/07/15 15:54:14
- [PROTOCOL auth-options.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c]
- [auth-rsa.c auth.c auth1.c auth2-hostbased.c auth2-kbdint.c auth2-none.c]
- [auth2-passwd.c auth2-pubkey.c auth2.c canohost.c channels.c channels.h]
- [clientloop.c misc.c misc.h monitor.c mux.c packet.c readconf.c]
- [readconf.h servconf.c servconf.h serverloop.c session.c ssh-agent.c]
- [ssh.c ssh_config.5 sshconnect.c sshconnect1.c sshconnect2.c sshd.c]
- [sshd_config.5 sshlogin.c]
- Add support for Unix domain socket forwarding. A remote TCP port
- may be forwarded to a local Unix domain socket and vice versa or
- both ends may be a Unix domain socket. This is a reimplementation
- of the streamlocal patches by William Ahern from:
- http://www.25thandclement.com/~william/projects/streamlocal.html
- OK djm@ markus@
-
-commit 6262d760e00714523633bd989d62e273a3dca99a
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 17 09:52:07 2014 +1000
-
- - tedu@cvs.openbsd.org 2014/07/11 13:54:34
- [myproposal.h]
- by popular demand, add back hamc-sha1 to server proposal for better compat
- with many clients still in use. ok deraadt
-
-commit 9d69d937b46ecba17f16d923e538ceda7b705c7a
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 17 09:49:37 2014 +1000
-
- - deraadt@cvs.openbsd.org 2014/07/11 08:09:54
- [sandbox-systrace.c]
- Permit use of SYS_sendsyslog from inside the sandbox. Clock is ticking,
- update your kernels and sshd soon.. libc will start using sendsyslog()
- in about 4 days.
-
-commit f6293a0b4129826fc2e37e4062f96825df43c326
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 17 09:01:25 2014 +1000
-
- - (djm) [digest-openssl.c] Preserve array order when disabling digests.
- Reported by Petr Lautrbach.
-
-commit 00f9cd230709c04399ef5ff80492d70a55230694
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jul 15 10:41:38 2014 +1000
-
- - (djm) [configure.ac] Delay checks for arc4random* until after libcrypto
- has been located; fixes builds agains libressl-portable
-
-commit 1d0df3249c87019556b83306c28d4769375c2edc
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 11 09:19:04 2014 +1000
-
- - OpenBSD CVS Sync
- - benno@cvs.openbsd.org 2014/07/09 14:15:56
- [ssh-add.c]
- fix ssh-add crash while loading more than one key
- ok markus@
-
-commit 7a57eb3d105aa4ced15fb47001092c58811e6d9d
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 9 13:22:31 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/07 08:15:26
- [multiplex.sh]
- remove forced-fatal that I stuck in there to test the new cleanup
- logic and forgot to remove...
-
-commit 612f965239a30fe536b11ece1834d9f470aeb029
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 9 13:22:03 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/06 07:42:03
- [multiplex.sh test-exec.sh]
- add a hook to the cleanup() function to kill $SSH_PID if it is set
-
- use it to kill the mux master started in multiplex.sh (it was being left
- around on fatal failures)
-
-commit d0bb950485ba121e43a77caf434115ed6417b46f
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 9 13:07:28 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/09 03:02:15
- [key.c]
- downgrade more error() to debug() to better match what old authfile.c
- did; suppresses spurious errors with hostbased authentication enabled
-
-commit 0070776a038655c57f57e70cd05e4c38a5de9d84
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 9 13:07:06 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/09 01:45:10
- [sftp.c]
- more useful error message when GLOB_NOSPACE occurs;
- bz#2254, patch from Orion Poplawski
-
-commit 079bac2a43c74ef7cf56850afbab3b1932534c50
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 9 13:06:25 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/07 08:19:12
- [ssh_config.5]
- mention that ProxyCommand is executed using shell "exec" to avoid
- a lingering process; bz#1977
-
-commit 3a48cc090096cf99b9de592deb5f90e444edebfb
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Jul 6 09:32:49 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/05 23:11:48
- [channels.c]
- fix remote-forward cancel regression; ok markus@
-
-commit 48bae3a38cb578713e676708164f6e7151cc64fa
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Jul 6 09:27:06 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 23:18:35
- [authfile.h]
- remove leakmalloc droppings
-
-commit 72e6b5c9ed5e72ca3a6ccc3177941b7c487a0826
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 4 09:00:04 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 22:40:43
- [servconf.c servconf.h session.c sshd.8 sshd_config.5]
- Add a sshd_config PermitUserRC option to control whether ~/.ssh/rc is
- executed, mirroring the no-user-rc authorized_keys option;
- bz#2160; ok markus@
-
-commit 602943d1179a08dfa70af94f62296ea5e3d6ebb8
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 4 08:59:41 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 22:33:41
- [channels.c]
- allow explicit ::1 and 127.0.0.1 forwarding bind addresses when
- GatewayPorts=no; allows client to choose address family;
- bz#2222 ok markus@
-
-commit 6b37fbb7921d156b31e2c8f39d9e1b6746c34983
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 4 08:59:24 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 22:23:46
- [sshconnect.c]
- when rekeying, skip file/DNS lookup if it is the same as the key sent
- during initial key exchange. bz#2154 patch from Iain Morgan; ok markus@
-
-commit d2c3cd5f2e47ee24cf7093ce8e948c2e79dfc3fd
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 4 08:59:01 2014 +1000
-
- - jsing@cvs.openbsd.org 2014/07/03 12:42:16
- [cipher-chachapoly.c]
- Call chacha_ivsetup() immediately before chacha_encrypt_bytes() - this
- makes it easier to verify that chacha_encrypt_bytes() is only called once
- per chacha_ivsetup() call.
- ok djm@
-
-commit 686feb560ec43a06ba04da82b50f3c183c947309
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 21:29:38 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 11:16:55
- [auth.c auth.h auth1.c auth2.c]
- make the "Too many authentication failures" message include the
- user, source address, port and protocol in a format similar to the
- authentication success / failure messages; bz#2199, ok dtucker
-
-commit 0f12341402e18fd9996ec23189b9418d2722453f
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 21:28:09 2014 +1000
-
- - jmc@cvs.openbsd.org 2014/07/03 07:45:27
- [ssh_config.5]
- escape %C since groff thinks it part of an Rs/Re block;
-
-commit 9c38643c5cd47a19db2cc28279dcc28abadc22b3
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 21:27:46 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 06:39:19
- [ssh.c ssh_config.5]
- Add a %C escape sequence for LocalCommand and ControlPath that expands
- to a unique identifer based on a has of the tuple of (local host,
- remote user, hostname, port).
-
- Helps avoid exceeding sockaddr_un's miserly pathname limits for mux
- control paths.
-
- bz#2220, based on patch from mancha1 AT zoho.com; ok markus@
-
-commit 49d9bfe2b2f3e90cc158a215dffa7675e57e7830
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 21:26:42 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 05:38:17
- [ssh.1]
- document that -g will only work in the multiplexed case if applied to
- the mux master
-
-commit ef9f13ba4c58057b2166d1f2e790535da402fbe5
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 21:26:21 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 05:32:36
- [ssh_config.5]
- mention '%%' escape sequence in HostName directives and how it may
- be used to specify IPv6 link-local addresses
-
-commit e6a407789e5432dd2e53336fb73476cc69048c54
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 21:25:03 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 04:36:45
- [digest.h]
- forward-declare struct sshbuf so consumers don't need to include sshbuf.h
-
-commit 4a1d3d50f02d0a8a4ef95ea4749293cbfb89f919
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 21:24:40 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 03:47:27
- [ssh-keygen.c]
- When hashing or removing hosts using ssh-keygen, don't choke on
- @revoked markers and don't remove @cert-authority markers;
- bz#2241, reported by mlindgren AT runelind.net
-
-commit e5c0d52ceb575c3db8c313e0b1aa3845943d7ba8
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 21:24:19 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 03:34:09
- [gss-serv.c session.c ssh-keygen.c]
- standardise on NI_MAXHOST for gethostname() string lengths; about
- 1/2 the cases were using it already. Fixes bz#2239 en passant
-
-commit c174a3b7c14e0d178c61219de2aa1110e209950c
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 21:23:24 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 03:26:43
- [digest-openssl.c]
- use EVP_Digest() for one-shot hash instead of creating, updating,
- finalising and destroying a context.
- bz#2231, based on patch from Timo Teras
-
-commit d7ca2cd31ecc4d63a055e2dcc4bf35c13f2db4c5
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 21:23:01 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 03:15:01
- [ssh-add.c]
- make stdout line-buffered; saves partial output getting lost when
- ssh-add fatal()s part-way through (e.g. when listing keys from an
- agent that supports key types that ssh-add doesn't);
- bz#2234, reported by Phil Pennock
-
-commit b1e967c8d7c7578dd0c172d85b3046cf54ea42ba
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 21:22:40 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 03:11:03
- [ssh-agent.c]
- Only cleanup agent socket in the main agent process and not in any
- subprocesses it may have started (e.g. forked askpass). Fixes
- agent sockets being zapped when askpass processes fatal();
- bz#2236 patch from Dmitry V. Levin
-
-commit 61e28e55c3438d796b02ef878bcd28620d452670
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 21:22:22 2014 +1000
-
- - djm@cvs.openbsd.org 2014/07/03 01:45:38
- [sshkey.c]
- make Ed25519 keys' title fit properly in the randomart border; bz#2247
- based on patch from Christian Hesse
-
-commit 9eb4cd9a32c32d40d36450b68ed93badc6a94c68
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 13:29:50 2014 +1000
-
- - (djm) [monitor_fdpass.c] Use sys/poll.h if poll.h doesn't exist;
- bz#2237
-
-commit 8da0fa24934501909408327298097b1629b89eaa
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 3 11:54:19 2014 +1000
-
- - (djm) [digest-openssl.c configure.ac] Disable RIPEMD160 if libcrypto
- doesn't support it.
-
-commit 81309c857dd0dbc0a1245a16d621c490ad48cfbb
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 17:45:55 2014 +1000
-
- - (djm) [regress/Makefile] fix execution of sshkey unit/fuzz test
-
-commit 82b2482ce68654815ee049b9bf021bb362a35ff2
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 17:43:41 2014 +1000
-
- - (djm) [sshkey.c] Conditionalise inclusion of util.h
-
-commit dd8b1dd7933eb6f5652641b0cdced34a387f2e80
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 17:38:31 2014 +1000
-
- - djm@cvs.openbsd.org 2014/06/24 01:14:17
- [Makefile.in regress/Makefile regress/unittests/Makefile]
- [regress/unittests/sshkey/Makefile]
- [regress/unittests/sshkey/common.c]
- [regress/unittests/sshkey/common.h]
- [regress/unittests/sshkey/mktestdata.sh]
- [regress/unittests/sshkey/test_file.c]
- [regress/unittests/sshkey/test_fuzz.c]
- [regress/unittests/sshkey/test_sshkey.c]
- [regress/unittests/sshkey/tests.c]
- [regress/unittests/sshkey/testdata/dsa_1]
- [regress/unittests/sshkey/testdata/dsa_1-cert.fp]
- [regress/unittests/sshkey/testdata/dsa_1-cert.pub]
- [regress/unittests/sshkey/testdata/dsa_1.fp]
- [regress/unittests/sshkey/testdata/dsa_1.fp.bb]
- [regress/unittests/sshkey/testdata/dsa_1.param.g]
- [regress/unittests/sshkey/testdata/dsa_1.param.priv]
- [regress/unittests/sshkey/testdata/dsa_1.param.pub]
- [regress/unittests/sshkey/testdata/dsa_1.pub]
- [regress/unittests/sshkey/testdata/dsa_1_pw]
- [regress/unittests/sshkey/testdata/dsa_2]
- [regress/unittests/sshkey/testdata/dsa_2.fp]
- [regress/unittests/sshkey/testdata/dsa_2.fp.bb]
- [regress/unittests/sshkey/testdata/dsa_2.pub]
- [regress/unittests/sshkey/testdata/dsa_n]
- [regress/unittests/sshkey/testdata/dsa_n_pw]
- [regress/unittests/sshkey/testdata/ecdsa_1]
- [regress/unittests/sshkey/testdata/ecdsa_1-cert.fp]
- [regress/unittests/sshkey/testdata/ecdsa_1-cert.pub]
- [regress/unittests/sshkey/testdata/ecdsa_1.fp]
- [regress/unittests/sshkey/testdata/ecdsa_1.fp.bb]
- [regress/unittests/sshkey/testdata/ecdsa_1.param.curve]
- [regress/unittests/sshkey/testdata/ecdsa_1.param.priv]
- [regress/unittests/sshkey/testdata/ecdsa_1.param.pub]
- [regress/unittests/sshkey/testdata/ecdsa_1.pub]
- [regress/unittests/sshkey/testdata/ecdsa_1_pw]
- [regress/unittests/sshkey/testdata/ecdsa_2]
- [regress/unittests/sshkey/testdata/ecdsa_2.fp]
- [regress/unittests/sshkey/testdata/ecdsa_2.fp.bb]
- [regress/unittests/sshkey/testdata/ecdsa_2.param.curve]
- [regress/unittests/sshkey/testdata/ecdsa_2.param.priv]
- [regress/unittests/sshkey/testdata/ecdsa_2.param.pub]
- [regress/unittests/sshkey/testdata/ecdsa_2.pub]
- [regress/unittests/sshkey/testdata/ecdsa_n]
- [regress/unittests/sshkey/testdata/ecdsa_n_pw]
- [regress/unittests/sshkey/testdata/ed25519_1]
- [regress/unittests/sshkey/testdata/ed25519_1-cert.fp]
- [regress/unittests/sshkey/testdata/ed25519_1-cert.pub]
- [regress/unittests/sshkey/testdata/ed25519_1.fp]
- [regress/unittests/sshkey/testdata/ed25519_1.fp.bb]
- [regress/unittests/sshkey/testdata/ed25519_1.pub]
- [regress/unittests/sshkey/testdata/ed25519_1_pw]
- [regress/unittests/sshkey/testdata/ed25519_2]
- [regress/unittests/sshkey/testdata/ed25519_2.fp]
- [regress/unittests/sshkey/testdata/ed25519_2.fp.bb]
- [regress/unittests/sshkey/testdata/ed25519_2.pub]
- [regress/unittests/sshkey/testdata/pw]
- [regress/unittests/sshkey/testdata/rsa1_1]
- [regress/unittests/sshkey/testdata/rsa1_1.fp]
- [regress/unittests/sshkey/testdata/rsa1_1.fp.bb]
- [regress/unittests/sshkey/testdata/rsa1_1.param.n]
- [regress/unittests/sshkey/testdata/rsa1_1.pub]
- [regress/unittests/sshkey/testdata/rsa1_1_pw]
- [regress/unittests/sshkey/testdata/rsa1_2]
- [regress/unittests/sshkey/testdata/rsa1_2.fp]
- [regress/unittests/sshkey/testdata/rsa1_2.fp.bb]
- [regress/unittests/sshkey/testdata/rsa1_2.param.n]
- [regress/unittests/sshkey/testdata/rsa1_2.pub]
- [regress/unittests/sshkey/testdata/rsa_1]
- [regress/unittests/sshkey/testdata/rsa_1-cert.fp]
- [regress/unittests/sshkey/testdata/rsa_1-cert.pub]
- [regress/unittests/sshkey/testdata/rsa_1.fp]
- [regress/unittests/sshkey/testdata/rsa_1.fp.bb]
- [regress/unittests/sshkey/testdata/rsa_1.param.n]
- [regress/unittests/sshkey/testdata/rsa_1.param.p]
- [regress/unittests/sshkey/testdata/rsa_1.param.q]
- [regress/unittests/sshkey/testdata/rsa_1.pub]
- [regress/unittests/sshkey/testdata/rsa_1_pw]
- [regress/unittests/sshkey/testdata/rsa_2]
- [regress/unittests/sshkey/testdata/rsa_2.fp]
- [regress/unittests/sshkey/testdata/rsa_2.fp.bb]
- [regress/unittests/sshkey/testdata/rsa_2.param.n]
- [regress/unittests/sshkey/testdata/rsa_2.param.p]
- [regress/unittests/sshkey/testdata/rsa_2.param.q]
- [regress/unittests/sshkey/testdata/rsa_2.pub]
- [regress/unittests/sshkey/testdata/rsa_n]
- [regress/unittests/sshkey/testdata/rsa_n_pw]
- unit and fuzz tests for new key API
-
-commit c1dc24b71f087f385b92652b9673f52af64e0428
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 17:02:03 2014 +1000
-
- - djm@cvs.openbsd.org 2014/06/24 01:04:43
- [regress/krl.sh]
- regress test for broken consecutive revoked serial number ranges
-
-commit 43d3ed2dd3feca6d0326c7dc82588d2faa115e92
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 17:01:08 2014 +1000
-
- - djm@cvs.openbsd.org 2014/05/21 07:04:21
- [regress/integrity.sh]
- when failing because of unexpected output, show the offending output
-
-commit 5a96707ffc8d227c2e7d94fa6b0317f8a152cf4e
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 15:38:05 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/30 05:32:00
- [regress/Makefile]
- unit tests for new buffer API; including basic fuzz testing
- NB. Id sync only.
-
-commit 3ff92ba756aee48e4ae3e0aeff7293517b3dd185
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 15:33:09 2014 +1000
-
- - djm@cvs.openbsd.org 2014/06/30 12:54:39
- [key.c]
- suppress spurious error message when loading key with a passphrase;
- reported by kettenis@ ok markus@
- - djm@cvs.openbsd.org 2014/07/02 04:59:06
- [cipher-3des1.c]
- fix ssh protocol 1 on the server that regressed with the sshkey change
- (sometimes fatal() after auth completed), make file return useful status
- codes.
- NB. Id sync only for these two. They were bundled into the sshkey merge
- above, since it was easier to sync the entire file and then apply
- portable-specific changed atop it.
-
-commit ec3d0e24a1e46873d80507f5cd8ee6d0d03ac5dc
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 15:30:00 2014 +1000
-
- - markus@cvs.openbsd.org 2014/06/27 18:50:39
- [ssh-add.c]
- fix loading of private keys
-
-commit 4b3ed647d5b328cf68e6a8ffbee490d8e0683e82
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 15:29:40 2014 +1000
-
- - markus@cvs.openbsd.org 2014/06/27 16:41:56
- [channels.c channels.h clientloop.c ssh.c]
- fix remote fwding with same listen port but different listen address
- with gerhard@, ok djm@
-
-commit 9e01ff28664921ce9b6500681333e42fb133b4d0
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 15:29:21 2014 +1000
-
- - deraadt@cvs.openbsd.org 2014/06/25 14:16:09
- [sshbuf.c]
- unblock SIGSEGV before raising it
- ok djm
-
-commit 1845fe6bda0729e52f4c645137f4fc3070b5438a
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 15:29:01 2014 +1000
-
- - djm@cvs.openbsd.org 2014/06/24 02:21:01
- [scp.c]
- when copying local->remote fails during read, don't send uninitialised
- heap to the remote end. Reported by Jann Horn
-
-commit 19439e9a2a0ac0b4b3b1210e89695418beb1c883
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 15:28:40 2014 +1000
-
- - djm@cvs.openbsd.org 2014/06/24 02:19:48
- [ssh.c]
- don't fatal() when hostname canonicalisation fails with a
- ProxyCommand in use; continue and allow the ProxyCommand to
- connect anyway (e.g. to a host with a name outside the DNS
- behind a bastion)
-
-commit 8668706d0f52654fe64c0ca41a96113aeab8d2b8
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 15:28:02 2014 +1000
-
- - djm@cvs.openbsd.org 2014/06/24 01:13:21
- [Makefile.in auth-bsdauth.c auth-chall.c auth-options.c auth-rsa.c
- [auth2-none.c auth2-pubkey.c authfile.c authfile.h cipher-3des1.c
- [cipher-chachapoly.c cipher-chachapoly.h cipher.c cipher.h
- [digest-libc.c digest-openssl.c digest.h dns.c entropy.c hmac.h
- [hostfile.c key.c key.h krl.c monitor.c packet.c rsa.c rsa.h
- [ssh-add.c ssh-agent.c ssh-dss.c ssh-ecdsa.c ssh-ed25519.c
- [ssh-keygen.c ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c
- [ssh-rsa.c sshbuf-misc.c sshbuf.h sshconnect.c sshconnect1.c
- [sshconnect2.c sshd.c sshkey.c sshkey.h
- [openbsd-compat/openssl-compat.c openbsd-compat/openssl-compat.h]
- New key API: refactor key-related functions to be more library-like,
- existing API is offered as a set of wrappers.
-
- with and ok markus@
-
- Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew
- Dempsky and Ron Bowes for a detailed review a few months ago.
-
- NB. This commit also removes portable OpenSSH support for OpenSSL
- <0.9.8e.
-
-commit 2cd7929250cf9e9f658d70dcd452f529ba08c942
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 12:48:30 2014 +1000
-
- - djm@cvs.openbsd.org 2014/06/24 00:52:02
- [krl.c]
- fix bug in KRL generation: multiple consecutive revoked certificate
- serial number ranges could be serialised to an invalid format.
-
- Readers of a broken KRL caused by this bug will fail closed, so no
- should-have-been-revoked key will be accepted.
-
-commit 99db840ee8dbbd2b3fbc6c45d0ee2f6a65e96898
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 12:48:04 2014 +1000
-
- - naddy@cvs.openbsd.org 2014/06/18 15:42:09
- [sshbuf-getput-crypto.c]
- The ssh_get_bignum functions must accept the same range of bignums
- the corresponding ssh_put_bignum functions create. This fixes the
- use of 16384-bit RSA keys (bug reported by Eivind Evensen).
- ok djm@
-
-commit 84a89161a9629239b64171ef3e22ef6a3e462d51
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 12:47:48 2014 +1000
-
- - matthew@cvs.openbsd.org 2014/06/18 02:59:13
- [sandbox-systrace.c]
- Now that we have a dedicated getentropy(2) system call for
- arc4random(3), we can disallow __sysctl(2) in OpenSSH's systrace
- sandbox.
-
- ok djm
-
-commit 51504ceec627c0ad57b9f75585c7b3d277f326be
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 2 12:47:25 2014 +1000
-
- - deraadt@cvs.openbsd.org 2014/06/13 08:26:29
- [sandbox-systrace.c]
- permit SYS_getentropy
- from matthew
-
-commit a261b8df59117f7dc52abb3a34b35a40c2c9fa88
-Author: Tim Rice <tim@multitalents.net>
-Date: Wed Jun 18 16:17:28 2014 -0700
-
- - (tim) [openssh/session.c] Work around to get chroot sftp working on UnixWare
-
-commit 316fac6f18f87262a315c79bcf68b9f92c9337e4
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Jun 17 23:06:07 2014 +1000
-
- - (dtucker) [entropy.c openbsd-compat/openssl-compat.{c,h}
- openbsd-compat/regress/{.cvsignore,Makefile.in,opensslvertest.c}]
- Move the OpenSSL header/library version test into its own function and add
- tests for it. Fix it to allow fix version upgrades (but not downgrades).
- Prompted by chl@ via OpenSMTPD (issue #462) and Debian (bug #748150).
- ok djm@ chl@
-
-commit af665bb7b092a59104db1e65577851cf35b86e32
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Jun 16 22:50:55 2014 +1000
-
- - (dtucker) [defines.h] Fix undef of _PATH_MAILDIR. From rak at debian via
- OpenSMTPD and chl@
-
-commit f9696566fb41320820f3b257ab564fa321bb3751
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jun 13 11:06:04 2014 +1000
-
- - (dtucker) [configure.ac] Remove tcpwrappers support, support has already
- been removed from sshd.c.
-
-commit 5e2b8894b0b24af4ad0a2f7aa33ebf255df7a8bc
-Author: Tim Rice <tim@multitalents.net>
-Date: Wed Jun 11 18:31:10 2014 -0700
-
- - (tim) [regress/unittests/test_helper/test_helper.h] Add includes.h for
- u_intXX_t types.
-
-commit 985ee2cbc3e43bc65827c3c0d4df3faa99160c37
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 12 05:32:29 2014 +1000
-
- - (dtucker) [regress/unittests/sshbuf/*.c regress/unittests/test_helper/*]
- Wrap stdlib.h include an ifdef for platforms that don't have it.
-
-commit cf5392c2db2bb1dbef9818511d34056404436109
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 12 05:22:49 2014 +1000
-
- - (dtucker) [defines.h] Add va_copy if we don't already have it, taken from
- openbsd-compat/bsd-asprintf.c.
-
-commit 58538d795e0b662f2f4e5a7193f1204bbe992ddd
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jun 11 13:39:24 2014 +1000
-
- - (dtucker) [bufaux.c bufbn.c bufec.c buffer.c] Pull in includes.h for
- compat stuff, specifically whether or not OpenSSL has ECC.
-
-commit eb012ac581fd0abc16ee86ee3a68cf07c8ce4d08
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jun 11 13:10:00 2014 +1000
-
- - (dtucker) [openbsd-compat/arc4random.c] Use explicit_bzero instead of an
- assigment that might get optimized out. ok djm@
-
-commit b9609fd86c623d6d440e630f5f9a63295f7aea20
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jun 11 08:04:02 2014 +1000
-
- - (dtucker) [sshbuf.h] Only declare ECC functions if building without
- OpenSSL or if OpenSSL has ECC.
-
-commit a54a040f66944c6e8913df8635a01a2327219be9
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jun 11 07:58:35 2014 +1000
-
- - dtucker@cvs.openbsd.org 2014/06/10 21:46:11
- [sshbuf.h]
- Group ECC functions together to make things a little easier in -portable.
- "doesn't bother me" deraadt@
-
-commit 9f92c53bad04a89067756be8198d4ec2d8a08875
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jun 11 07:57:58 2014 +1000
-
- - djm@cvs.openbsd.org 2014/06/05 22:17:50
- [sshconnect2.c]
- fix inverted test that caused PKCS#11 keys that were explicitly listed
- not to be preferred. Reported by Dirk-Willem van Gulik
-
-commit 15c254a25394f96643da2ad0f674acdc51e89856
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jun 11 07:38:49 2014 +1000
-
- - (dtucker) [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] ifdef
- ECC variable too.
-
-commit d7af0cc5bf273eeed0897a99420bc26841d07d8f
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jun 11 07:37:25 2014 +1000
-
- - (dtucker) [myprosal.h] Don't include curve25519-sha256@libssh.org in
- the proposal if the version of OpenSSL we're using doesn't support ECC.
-
-commit 67508ac2563c33d582be181a3e777c65f549d22f
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jun 11 06:27:16 2014 +1000
-
- - (dtucker) [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
- regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] Only do NISTP256
- curve tests if OpenSSL has them.
-
-commit 6482d90a65459a88c18c925368525855832272b3
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue May 27 14:34:42 2014 +1000
-
- - (djm) [configure.ac openbsd-compat/bsd-cygwin_util.c]
- [openbsd-compat/bsd-cygwin_util.h] On Cygwin, determine privilege
- separation user at runtime, since it may need to be a domain account.
- Patch from Corinna Vinschen.
-
-commit f9eb5e0734f7a7f6e975809eb54684d2a06a7ffc
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue May 27 14:31:58 2014 +1000
-
- - (djm) [contrib/cygwin/ssh-host-config] Updated Cygwin ssh-host-config
- from Corinna Vinschen, fixing a number of bugs and preparing for
- Cygwin 1.7.30.
-
-commit eae88744662e6b149f43ef071657727f1a157d95
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue May 27 14:27:02 2014 +1000
-
- - (djm) [cipher.c] Fix merge botch.
-
-commit 564b5e253c1d95c26a00e8288f0089a2571661c3
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 22 08:23:59 2014 +1000
-
- - (djm) [Makefile.in] typo in path
-
-commit e84d10302aeaf7a1acb05c451f8718143656856a
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed May 21 17:13:36 2014 +1000
-
- revert a diff I didn't mean to commit
-
-commit 795b86313f1f1aab9691666c4f2d5dae6e4acd50
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed May 21 17:12:53 2014 +1000
-
- - (djm) [misc.c] Use CLOCK_BOOTTIME in preference to CLOCK_MONOTONIC
- when it is available. It takes into account time spent suspended,
- thereby ensuring timeouts (e.g. for expiring agent keys) fire
- correctly. bz#2228 reported by John Haxby
-
-commit 18912775cb97c0b1e75e838d3c7d4b56648137b5
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed May 21 17:06:46 2014 +1000
-
- - (djm) [commit configure.ac defines.h sshpty.c] don't attempt to use
- vhangup on Linux. It doens't work for non-root users, and for them
- it just messes up the tty settings.
-
-commit 7f1c264d3049cd95234e91970ccb5406e1d15b27
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 18:01:52 2014 +1000
-
- - (djm) [sshbuf.c] need __predict_false
-
-commit e7429f2be8643e1100380a8a7389d85cc286c8fe
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 18:01:01 2014 +1000
-
- - (djm) [regress/Makefile Makefile.in]
- [regress/unittests/sshbuf/test_sshbuf.c
- [regress/unittests/sshbuf/test_sshbuf_fixed.c]
- [regress/unittests/sshbuf/test_sshbuf_fuzz.c]
- [regress/unittests/sshbuf/test_sshbuf_getput_basic.c]
- [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c]
- [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c]
- [regress/unittests/sshbuf/test_sshbuf_misc.c]
- [regress/unittests/sshbuf/tests.c]
- [regress/unittests/test_helper/fuzz.c]
- [regress/unittests/test_helper/test_helper.c]
- Hook new unit tests into the build and "make tests"
-
-commit def1de086707b0e6b046fe7e115c60aca0227a99
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 15:17:15 2014 +1000
-
- - (djm) [regress/unittests/Makefile]
- [regress/unittests/Makefile.inc]
- [regress/unittests/sshbuf/Makefile]
- [regress/unittests/sshbuf/test_sshbuf.c]
- [regress/unittests/sshbuf/test_sshbuf_fixed.c]
- [regress/unittests/sshbuf/test_sshbuf_fuzz.c]
- [regress/unittests/sshbuf/test_sshbuf_getput_basic.c]
- [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c]
- [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c]
- [regress/unittests/sshbuf/test_sshbuf_misc.c]
- [regress/unittests/sshbuf/tests.c]
- [regress/unittests/test_helper/Makefile]
- [regress/unittests/test_helper/fuzz.c]
- [regress/unittests/test_helper/test_helper.c]
- [regress/unittests/test_helper/test_helper.h]
- Import new unit tests from OpenBSD; not yet hooked up to build.
-
-commit 167685756fde8bc213a8df2c8e1848e312db0f46
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 15:08:40 2014 +1000
-
- - logan@cvs.openbsd.org 2014/05/04 10:40:59
- [connect-privsep.sh]
- Remove the Z flag from the list of malloc options as it
- was removed from malloc.c 10 days ago.
-
- OK from miod@
-
-commit d0b69fe90466920d69c96069312e24b581771bd7
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 15:08:19 2014 +1000
-
- - dtucker@cvs.openbsd.org 2014/05/03 18:46:14
- [proxy-connect.sh]
- Add tests for with and without compression, with and without privsep.
-
-commit edb1af50441d19fb2dd9ccb4d75bf14473fca584
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 15:07:53 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/21 22:15:37
- [dhgex.sh integrity.sh kextype.sh rekey.sh try-ciphers.sh]
- repair regress tests broken by server-side default cipher/kex/mac changes
- by ensuring that the option under test is included in the server's
- algorithm list
-
-commit 54343e95c70994695f8842fb22836321350198d3
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 15:07:33 2014 +1000
-
- - djm@cvs.openbsd.org 2014/03/13 20:44:49
- [login-timeout.sh]
- this test is a sorry mess of race conditions; add another sleep
- to avoid a failure on slow machines (at least until I find a
- better way)
-
-commit e5b9f0f2ee6e133894307e44e862b66426990733
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 14:58:07 2014 +1000
-
- - (djm) [Makefile.in configure.ac sshbuf-getput-basic.c]
- [sshbuf-getput-crypto.c sshbuf.c] compilation and portability fixes
-
-commit b9c566788a9ebd6a9d466f47a532124f111f0542
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 14:43:37 2014 +1000
-
- - (djm) [configure.ac] Unconditionally define WITH_OPENSSL until we write
- portability glue to support building without libcrypto
-
-commit 3dc27178b42234b653a32f7a87292d7994045ee3
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 14:37:59 2014 +1000
-
- - logan@cvs.openbsd.org 2014/05/05 07:02:30
- [sftp.c]
- Zap extra whitespace.
-
- OK from djm@ and dtucker@
-
-commit c31a0cd5b31961f01c5b731f62a6cb9d4f767472
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 14:37:39 2014 +1000
-
- - markus@cvs.openbsd.org 2014/05/03 17:20:34
- [monitor.c packet.c packet.h]
- unbreak compression, by re-init-ing the compression code in the
- post-auth child. the new buffer code is more strict, and requires
- buffer_init() while the old code was happy after a bzero();
- originally from djm@
-
-commit 686c7d9ee6f44b2be4128d7860b6b37adaeba733
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 14:37:03 2014 +1000
-
- - djm@cvs.openbsd.org 2014/05/02 03:27:54
- [chacha.h cipher-chachapoly.h digest.h hmac.h kex.h kexc25519.c]
- [misc.h poly1305.h ssh-pkcs11.c defines.h]
- revert __bounded change; it causes way more problems for portable than
- it solves; pointed out by dtucker@
-
-commit 294c58a007cfb2f3bddc4fc3217e255857ffb9bf
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 14:35:03 2014 +1000
-
- - naddy@cvs.openbsd.org 2014/04/30 19:07:48
- [mac.c myproposal.h umac.c]
- UMAC can use our local fallback implementation of AES when OpenSSL isn't
- available. Glue code straight from Ted Krovetz's original umac.c.
- ok markus@
-
-commit 05e82c3b963c33048128baf72a6f6b3a1c10b4c1
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 14:33:43 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/30 05:29:56
- [bufaux.c bufbn.c bufec.c buffer.c buffer.h sshbuf-getput-basic.c]
- [sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c sshbuf.h ssherr.c]
- [ssherr.h]
- New buffer API; the first installment of the conversion/replacement
- of OpenSSH's internals to make them usable as a standalone library.
-
- This includes a set of wrappers to make it compatible with the
- existing buffer API so replacement can occur incrementally.
-
- With and ok markus@
-
- Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew
- Dempsky and Ron Bowes for a detailed review.
-
-commit 380948180f847a26f2d0c85b4dad3dca2ed2fd8b
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 14:25:18 2014 +1000
-
- - dtucker@cvs.openbsd.org 2014/04/29 20:36:51
- [sftp.c]
- Don't attempt to append a nul quote char to the filename. Should prevent
- fatal'ing with "el_insertstr failed" when there's a single quote char
- somewhere in the string. bz#2238, ok markus@
-
-commit d7fd8bedd4619a2ec7fd02aae4c4e1db4431ad9f
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 14:24:59 2014 +1000
-
- - dtucker@cvs.openbsd.org 2014/04/29 19:58:50
- [sftp.c]
- Move nulling of variable next to where it's freed. ok markus@
-
-commit 1f0311c7c7d10c94ff7f823de9c5b2ed79368b14
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 14:24:09 2014 +1000
-
- - markus@cvs.openbsd.org 2014/04/29 18:01:49
- [auth.c authfd.c authfile.c bufaux.c cipher.c cipher.h hostfile.c]
- [kex.c key.c mac.c monitor.c monitor_wrap.c myproposal.h packet.c]
- [roaming_client.c ssh-agent.c ssh-keygen.c ssh-keyscan.c ssh-keysign.c]
- [ssh-pkcs11.h ssh.c sshconnect.c sshconnect2.c sshd.c]
- make compiling against OpenSSL optional (make OPENSSL=no);
- reduces algorithms to curve25519, aes-ctr, chacha, ed25519;
- allows us to explore further options; with and ok djm
-
-commit c5893785564498cea73cb60d2cf199490483e080
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 13:48:49 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/29 13:10:30
- [clientloop.c serverloop.c]
- bz#1818 - don't send channel success/failre replies on channels that
- have sent a close already; analysis and patch from Simon Tatham;
- ok markus@
-
-commit 633de33b192d808d87537834c316dc8b75fe1880
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 13:48:26 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/28 03:09:18
- [authfile.c bufaux.c buffer.h channels.c krl.c mux.c packet.c packet.h]
- [ssh-keygen.c]
- buffer_get_string_ptr's return should be const to remind
- callers that futzing with it will futz with the actual buffer
- contents
-
-commit 15271907843e4ae50dcfc83b3594014cf5e9607b
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 13:47:56 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/23 12:42:34
- [readconf.c]
- don't record duplicate IdentityFiles
-
-commit 798a02568b13a2e46efebd81f08c8f4bb33a6dc7
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 13:47:37 2014 +1000
-
- - jmc@cvs.openbsd.org 2014/04/22 14:16:30
- [sftp.1]
- zap eol whitespace;
-
-commit d875ff78d2b8436807381051de112f0ebf9b9ae1
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 13:47:15 2014 +1000
-
- - logan@cvs.openbsd.org 2014/04/22 12:42:04
- [sftp.1]
- Document sftp upload resume.
- OK from djm@, with feedback from okan@.
-
-commit b15cd7bb097fd80dc99520f45290ef775da1ef19
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 13:46:52 2014 +1000
-
- - logan@cvs.openbsd.org 2014/04/22 10:07:12
- [sftp.c]
- Sort the sftp command list.
- OK from djm@
-
-commit d8accc0aa72656ba63d50937165c5ae49db1dcd6
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 13:46:25 2014 +1000
-
- - logan@cvs.openbsd.org 2014/04/21 14:36:16
- [sftp-client.c sftp-client.h sftp.c]
- Implement sftp upload resume support.
- OK from djm@, with input from guenther@, mlarkin@ and
- okan@
-
-commit 16cd3928a87d20c77b13592a74b60b08621d3ce6
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 13:45:58 2014 +1000
-
- - logan@cvs.openbsd.org 2014/04/20 09:24:26
- [dns.c dns.h ssh-keygen.c]
- Add support for SSHFP DNS records for ED25519 key types.
- OK from djm@
-
-commit ec0b67eb3b4e12f296ced1fafa01860c374f7eea
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 15 13:45:26 2014 +1000
-
- - (djm) [rijndael.c rijndael.h] Sync with newly-ressurected versions ine
- OpenBSD
-
-commit f028460d0b2e5a584355321015cde69bf6fd933e
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 1 02:24:35 2014 +1000
-
- - (dtucker) [defines.h] Define __GNUC_PREREQ__ macro if we don't already
- have it. Only attempt to use __attribute__(__bounded__) for gcc.
-
-commit b628cc4c3e4a842bab5e4584d18c2bc5fa4d0edf
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:33:58 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/20 02:49:32
- [compat.c]
- add a canonical 6.6 + curve25519 bignum fix fake version that I can
- recommend people use ahead of the openssh-6.7 release
-
-commit 888566913933a802f3a329ace123ebcb7154cf78
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:33:19 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/20 02:30:25
- [misc.c misc.h umac.c]
- use get/put_u32 to load values rather than *((UINT32 *)p) that breaks on
- strict-alignment architectures; reported by and ok stsp@
-
-commit 16f85cbc7e5139950e6a38317e7c8b368beafa5d
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:29:28 2014 +1000
-
- - tedu@cvs.openbsd.org 2014/04/19 18:42:19
- [ssh.1]
- delete .xr to hosts.equiv. there's still an unfortunate amount of
- documentation referring to rhosts equivalency in here.
-
-commit 69cb24b7356ec3f0fc5ff04a68f98f2c55c766f4
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:29:06 2014 +1000
-
- - tedu@cvs.openbsd.org 2014/04/19 18:15:16
- [sshd.8]
- remove some really old rsh references
-
-commit 84c1e7bca8c4ceaccf4d5557e39a833585a3c77e
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:27:53 2014 +1000
-
- - tedu@cvs.openbsd.org 2014/04/19 14:53:48
- [ssh-keysign.c sshd.c]
- Delete futile calls to RAND_seed. ok djm
- NB. Id sync only. This only applies to OpenBSD's libcrypto slashathon
-
-commit 0e6b67423b8662f9ca4c92750309e144fd637ef1
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:27:01 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/19 05:54:59
- [compat.c]
- missing wildcard; pointed out by naddy@
-
-commit 9395b28223334826837c15e8c1bb4dfb3b0d2ca5
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:25:30 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/18 23:52:25
- [compat.c compat.h sshconnect2.c sshd.c version.h]
- OpenSSH 6.5 and 6.6 have a bug that causes ~0.2% of connections
- using the curve25519-sha256@libssh.org KEX exchange method to fail
- when connecting with something that implements the spec properly.
-
- Disable this KEX method when speaking to one of the affected
- versions.
-
- reported by Aris Adamantiadis; ok markus@
-
-commit 8c492da58f8ceb85cf5f7066f23e26fb813a963d
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:25:09 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/16 23:28:12
- [ssh-agent.1]
- remove the identity files from this manpage - ssh-agent doesn't deal
- with them at all and the same information is duplicated in ssh-add.1
- (which does deal with them); prodded by deraadt@
-
-commit adbfdbbdccc70c9bd70d81ae096db115445c6e26
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:24:49 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/16 23:22:45
- [bufaux.c]
- skip leading zero bytes in buffer_put_bignum2_from_string();
- reported by jan AT mojzis.com; ok markus@
-
-commit 75c62728dc87af6805696eeb520b9748faa136c8
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:24:31 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/12 04:55:53
- [sshd.c]
- avoid crash at exit: check that pmonitor!=NULL before dereferencing;
- bz#2225, patch from kavi AT juniper.net
-
-commit 2a328437fb1b0976f2f4522d8645803d5a5d0967
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:24:01 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/01 05:32:57
- [packet.c]
- demote a debug3 to PACKET_DEBUG; ok markus@
-
-commit 7d6a9fb660c808882d064e152d6070ffc3844c3f
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:23:43 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/01 03:34:10
- [sshconnect.c]
- When using VerifyHostKeyDNS with a DNSSEC resolver, down-convert any
- certificate keys to plain keys and attempt SSHFP resolution.
-
- Prevents a server from skipping SSHFP lookup and forcing a new-hostkey
- dialog by offering only certificate keys.
-
- Reported by mcv21 AT cam.ac.uk
-
-commit fcd62c0b66b8415405ed0af29c236329eb88cc0f
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:23:21 2014 +1000
-
- - djm@cvs.openbsd.org 2014/04/01 02:05:27
- [ssh-keysign.c]
- include fingerprint of key not found
- use arc4random_buf() instead of loop+arc4random()
-
-commit 43b156cf72f900f88065b0a1c1ebd09ab733ca46
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:23:03 2014 +1000
-
- - jmc@cvs.openbsd.org 2014/03/31 13:39:34
- [ssh-keygen.1]
- the text for the -K option was inserted in the wrong place in -r1.108;
- fix From: Matthew Clarke
-
-commit c1621c84f2dc1279065ab9fde2aa9327af418900
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:22:46 2014 +1000
-
- - naddy@cvs.openbsd.org 2014/03/28 05:17:11
- [ssh_config.5 sshd_config.5]
- sync available and default algorithms, improve algorithm list formatting
- help from jmc@ and schwarze@, ok deraadt@
-
-commit f2719b7c2b8a3b14d778d8a6d8dc729b5174b054
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:22:18 2014 +1000
-
- - tedu@cvs.openbsd.org 2014/03/26 19:58:37
- [sshd.8 sshd.c]
- remove libwrap support. ok deraadt djm mfriedl
-
-commit 4f40209aa4060b9c066a2f0d9332ace7b8dfb391
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:21:22 2014 +1000
-
- - djm@cvs.openbsd.org 2014/03/26 04:55:35
- [chacha.h cipher-chachapoly.h digest.h hmac.h kex.h kexc25519.c
- [misc.h poly1305.h ssh-pkcs11.c]
- use __bounded(...) attribute recently added to sys/cdefs.h instead of
- longform __attribute__(__bounded(...));
-
- for brevity and a warning free compilation with llvm/clang
-
-commit 9235a030ad1b16903fb495d81544e0f7c7449523
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:17:20 2014 +1000
-
- Three commits in one (since they touch the same heavily-diverged file
- repeatedly):
-
- - markus@cvs.openbsd.org 2014/03/25 09:40:03
- [myproposal.h]
- trimm default proposals.
-
- This commit removes the weaker pre-SHA2 hashes, the broken ciphers
- (arcfour), and the broken modes (CBC) from the default configuration
- (the patch only changes the default, all the modes are still available
- for the config files).
-
- ok djm@, reminded by tedu@ & naddy@ and discussed with many
- - deraadt@cvs.openbsd.org 2014/03/26 17:16:26
- [myproposal.h]
- The current sharing of myproposal[] between both client and server code
- makes the previous diff highly unpallatable. We want to go in that
- direction for the server, but not for the client. Sigh.
- Brought up by naddy.
- - markus@cvs.openbsd.org 2014/03/27 23:01:27
- [myproposal.h ssh-keyscan.c sshconnect2.c sshd.c]
- disable weak proposals in sshd, but keep them in ssh; ok djm@
-
-commit 6e1777f592f15f4559728c78204617537b1ac076
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:02:58 2014 +1000
-
- - tedu@cvs.openbsd.org 2014/03/19 14:42:44
- [scp.1]
- there is no need for rcp anymore
- ok deraadt millert
-
-commit eb1b7c514d2a7b1802ccee8cd50e565a4d419887
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:02:26 2014 +1000
-
- - tedu@cvs.openbsd.org 2014/03/17 19:44:10
- [ssh.1]
- old descriptions of des and blowfish are old. maybe ok deraadt
-
-commit f0858de6e1324ec730752387074b111b8551081e
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:01:30 2014 +1000
-
- - deraadt@cvs.openbsd.org 2014/03/15 17:28:26
- [ssh-agent.c ssh-keygen.1 ssh-keygen.c]
- Improve usage() and documentation towards the standard form.
- In particular, this line saves a lot of man page reading time.
- usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1]
- [-N new_passphrase] [-C comment] [-f output_keyfile]
- ok schwarze jmc
-
-commit 94bfe0fbd6e91a56b5b0ab94ac955d2a67d101aa
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:00:51 2014 +1000
-
- - naddy@cvs.openbsd.org 2014/03/12 13:06:59
- [ssh-keyscan.1]
- scan for Ed25519 keys by default too
-
-commit 3819519288b2b3928c6882f5883b0f55148f4fc0
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:00:28 2014 +1000
-
- - djm@cvs.openbsd.org 2014/03/12 04:51:12
- [authfile.c]
- correct test that kdf name is not "none" or "bcrypt"
-
-commit 8f9cd709c7cf0655d414306a0ed28306b33802be
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 13:00:11 2014 +1000
-
- - djm@cvs.openbsd.org 2014/03/12 04:50:32
- [auth-bsdauth.c ssh-keygen.c]
- don't count on things that accept arguments by reference to clear
- things for us on error; most things do, but it's unsafe form.
-
-commit 1c7ef4be83f6dec84509a312518b9df00ab491d9
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 12:59:46 2014 +1000
-
- - djm@cvs.openbsd.org 2014/03/12 04:44:58
- [ssh-keyscan.c]
- scan for Ed25519 keys by default too
-
-commit c10bf4d051c97939b30a1616c0499310057d07da
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Apr 20 12:58:04 2014 +1000
-
- - djm@cvs.openbsd.org 2014/03/03 22:22:30
- [session.c]
- ignore enviornment variables with embedded '=' or '\0' characters;
- spotted by Jann Horn; ok deraadt@
- Id sync only - portable already has this.
-
-commit c2e49062faccbcd7135c40d1c78c5c329c58fc2e
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 1 14:42:46 2014 +1100
-
- - (djm) Use full release (e.g. 6.5p1) in debug output rather than just
- version. From des@des.no
-
-commit 14928b7492abec82afa4c2b778fc03f78cd419b6
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 1 14:38:07 2014 +1100
-
- - (djm) On platforms that support it, use prctl() to prevent sftp-server
- from accessing /proc/self/{mem,maps}; patch from jann AT thejh.net
-
-commit 48abc47e60048461fe9117e108a7e99ea1ac2bb8
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Mar 17 14:45:56 2014 +1100
-
- - (djm) [sandbox-seccomp-filter.c] Soft-fail stat() syscalls. Add XXX to
- remind myself to add sandbox violation logging via the log socket.
-
-commit 9c36698ca2f554ec221dc7ef29c7a89e97c88705
-Author: Tim Rice <tim@multitalents.net>
-Date: Fri Mar 14 12:45:01 2014 -0700
-
- 20140314
- - (tim) [opensshd.init.in] Add support for ed25519
-
-commit 19158b2447e35838d69b2b735fb640d1e86061ea
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Mar 13 13:14:21 2014 +1100
-
- - (djm) Release OpenSSH 6.6
-
-commit 8569eba5d7f7348ce3955eeeb399f66f25c52ece
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Mar 4 09:35:17 2014 +1100
-
- - djm@cvs.openbsd.org 2014/03/03 22:22:30
- [session.c]
- ignore enviornment variables with embedded '=' or '\0' characters;
- spotted by Jann Horn; ok deraadt@
-
-commit 2476c31b96e89aec7d4e73cb6fbfb9a4290de3a7
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Mar 2 04:01:00 2014 +1100
-
- - (djm) [regress/Makefile] Disable dhgex regress test; it breaks when
- no moduli file exists at the expected location.
-
-commit c83fdf30e9db865575b2521b1fe46315cf4c70ae
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:34:03 2014 +1100
-
- - (djm) [regress/host-expand.sh] Add RCS Id
-
-commit 834aeac3555e53f7d29a6fcf3db010dfb99681c7
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:25:16 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/27 21:21:25
- [agent-ptrace.sh agent.sh]
- keep return values that are printed in error messages;
- from portable
- (Id sync only)
-
-commit 4f7f1a9a0de24410c30952c7e16d433240422182
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:24:11 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/27 20:04:16
- [login-timeout.sh]
- remove any existing LoginGraceTime from sshd_config before adding
- a specific one for the test back in
-
-commit d705d987c27f68080c8798eeb5262adbdd6b4ffd
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:23:26 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/26 10:49:17
- [scp-ssh-wrapper.sh scp.sh]
- make sure $SCP is tested on the remote end rather than whichever one
- happens to be in $PATH; from portable
- (Id sync only)
-
-commit 624a3ca376e3955a4b9d936c9e899e241b65d357
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:22:37 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/26 10:22:10
- [regress/cert-hostkey.sh]
- automatically generate revoked keys from listed keys rather than
- manually specifying each type; from portable
- (Id sync only)
-
-commit b84392328425e4b9a71f8bde5fe6a4a4c48d3ec4
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:21:26 2014 +1100
-
- - dtucker@cvs.openbsd.org 2014/01/25 04:35:32
- [regress/Makefile regress/dhgex.sh]
- Add a test for DH GEX sizes
-
-commit 1e2aa3d90472293ea19008f02336d6d68aa05793
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:19:51 2014 +1100
-
- - dtucker@cvs.openbsd.org 2014/01/20 00:00:30
- [sftp-chroot.sh]
- append to rather than truncating the log file
-
-commit f483cc16fe7314e24a37aa3a4422b03c013c3213
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:19:11 2014 +1100
-
- - dtucker@cvs.openbsd.org 2014/01/19 23:43:02
- [regress/sftp-chroot.sh]
- Don't use -q on sftp as it suppresses logging, instead redirect the
- output to the regress logfile.
-
-commit 6486f16f1c0ebd6f39286f6ab5e08286d90a994a
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:03:52 2014 +1100
-
- - (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
- [contrib/suse/openssh.spec] Crank version numbers
-
-commit 92cf5adea194140380e6af6ec32751f9ad540794
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:01:53 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/27 22:57:40
- [version.h]
- openssh-6.6
-
-commit fc5d6759aba71eb205b296b5f148010ffc828583
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:01:28 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/27 22:47:07
- [sshd_config.5]
- bz#2184 clarify behaviour of a keyword that appears in multiple
- matching Match blocks; ok dtucker@
-
-commit 172ec7e0af1a5f1d682f6a2dca335c6c186153d5
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:00:57 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/27 08:25:09
- [bufbn.c]
- off by one in range check
-
-commit f9a9aaba437c2787e40cf7cc928281950e161678
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 28 10:00:27 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/27 00:41:49
- [bufbn.c]
- fix unsigned overflow that could lead to reading a short ssh protocol
- 1 bignum value; found by Ben Hawkes; ok deraadt@
-
-commit fb3423b612713d9cde67c8a75f6f51188d6a3de3
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Feb 27 10:20:07 2014 +1100
-
- - markus@cvs.openbsd.org 2014/02/26 21:53:37
- [sshd.c]
- ssh_gssapi_prepare_supported_oids needs GSSAPI
-
-commit 1348129a34f0f7728c34d86c100a32dcc8d1f922
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Feb 27 10:18:32 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/26 20:29:29
- [channels.c]
- don't assume that the socks4 username is \0 terminated;
- spotted by Ben Hawkes; ok markus@
-
-commit e6a74aeeacd01d885262ff8e50eb28faee8c8039
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Feb 27 10:17:49 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/26 20:28:44
- [auth2-gss.c gss-serv.c ssh-gss.h sshd.c]
- bz#2107 - cache OIDs of supported GSSAPI mechanisms before privsep
- sandboxing, as running this code in the sandbox can cause violations;
- ok markus@
-
-commit 08b57c67f3609340ff703fe2782d7058acf2529e
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Feb 27 10:17:13 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/26 20:18:37
- [ssh.c]
- bz#2205: avoid early hostname lookups unless canonicalisation is enabled;
- ok dtucker@ markus@
-
-commit 13f97b2286142fd0b8eab94e4ce84fe124eeb752
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Feb 24 15:57:55 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/23 20:11:36
- [readconf.c readconf.h ssh.c ssh_config.5]
- reparse ssh_config and ~/.ssh/config if hostname canonicalisation changes
- the hostname. This allows users to write configurations that always
- refer to canonical hostnames, e.g.
-
- CanonicalizeHostname yes
- CanonicalDomains int.example.org example.org
- CanonicalizeFallbackLocal no
-
- Host *.int.example.org
- Compression off
- Host *.example.org
- User djm
-
- ok markus@
-
-commit bee3a234f3d1ad4244952bcff1b4b7c525330dc2
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Feb 24 15:57:22 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/23 20:03:42
- [ssh-ed25519.c]
- check for unsigned overflow; not reachable in OpenSSH but others might
- copy our code...
-
-commit 0628780abe61e7e50cba48cdafb1837f49ff23b2
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Feb 24 15:56:45 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/22 01:32:19
- [readconf.c]
- when processing Match blocks, skip 'exec' clauses if previous predicates
- failed to match; ok markus@
-
-commit 0890dc8191bb201eb01c3429feec0300a9d3a930
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Feb 24 15:56:07 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/15 23:05:36
- [channels.c]
- avoid spurious "getsockname failed: Bad file descriptor" errors in ssh -W;
- bz#2200, debian#738692 via Colin Watson; ok dtucker@
-
-commit d3cf67e1117c25d151d0f86396e77ee3a827045a
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Feb 24 15:55:36 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/07 06:55:54
- [cipher.c mac.c]
- remove some logging that makes ssh debugging output very verbose;
- ok markus
-
-commit 03ae081aeaa118361c81ece76eb7cc1aaa2b40c5
-Author: Tim Rice <tim@multitalents.net>
-Date: Fri Feb 21 09:09:34 2014 -0800
-
- 20140221
- - (tim) [configure.ac] Fix cut-and-paste error. Patch from Bryan Drewery.
-
-commit 4a20959d2e3c90e9d66897c0b4032c785672d815
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Feb 13 16:38:32 2014 +1100
-
- - (dtucker) [configure.ac openbsd-compat/openssl-compat.{c,h}] Add compat
- code for older OpenSSL versions that don't have EVP_MD_CTX_copy_ex.
-
-commit d1a7a9c0fd1ac2e3314cceb2891959fd2cd9eabb
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 7 09:24:33 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/06 22:21:01
- [sshconnect.c]
- in ssh_create_socket(), only do the getaddrinfo for BindAddress when
- BindAddress is actually specified. Fixes regression in 6.5 for
- UsePrivilegedPort=yes; patch from Corinna Vinschen
-
-commit 6ce35b6cc4ead1bf98abec34cb2e2d6ca0abb15e
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 7 09:24:14 2014 +1100
-
- - naddy@cvs.openbsd.org 2014/02/05 20:13:25
- [ssh-keygen.1 ssh-keygen.c]
- tweak synopsis: calling ssh-keygen without any arguments is fine; ok jmc@
- while here, fix ordering in usage(); requested by jmc@
-
-commit 6434cb2cfbbf0a46375d2d22f2ff9927feb5e478
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Feb 6 11:17:50 2014 +1100
-
- - (djm) [sandbox-seccomp-filter.c] Not all Linux architectures define
- __NR_shutdown; some go via the socketcall(2) multiplexer.
-
-commit 8d36f9ac71eff2e9f5770c0518b73d875f270647
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Feb 6 10:44:13 2014 +1100
-
- - (dtucker) [openbsd-compat/bsd-poll.c] Don't bother checking for non-NULL
- before freeing since free(NULL) is a no-op. ok djm.
-
-commit a0959da3680b4ce8cf911caf3293a6d90f88eeb7
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Feb 5 10:33:45 2014 +1100
-
- - (djm) [sandbox-capsicum.c] Don't fatal if Capsicum is offered by
- headers/libc but not supported by the kernel. Patch from Loganaden
- Velvindron @ AfriNIC
-
-commit 9c449bc183b256c84d8f740727b0bc54d247b15e
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:38:28 2014 +1100
-
- - (djm) [regress/setuid-allowed.c] Missing string.h for strerror()
-
-commit bf7e0f03be661b6f5b3bfe325135ce19391f9c4d
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:37:50 2014 +1100
-
- - (djm) [openbsd-compat/Makefile.in] Add missing explicit_bzero.o
-
-commit eb6d870a0ea8661299bb2ea8f013d3ace04e2024
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:26:34 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/04 00:24:29
- [ssh.c]
- delay lowercasing of hostname until right before hostname
- canonicalisation to unbreak case-sensitive matching of ssh_config;
- reported by Ike Devolder; ok markus@
-
-commit d56b44d2dfa093883a5c4e91be3f72d99946b170
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:26:04 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/04 00:24:29
- [ssh.c]
- delay lowercasing of hostname until right before hostname
- canonicalisation to unbreak case-sensitive matching of ssh_config;
- reported by Ike Devolder; ok markus@
-
-commit db3c595ea74ea9ccd5aa644d7e1f8dc675710731
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:25:45 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/02 03:44:31
- [digest-libc.c digest-openssl.c]
- convert memset of potentially-private data to explicit_bzero()
-
-commit aae07e2e2000dd318418fd7fd4597760904cae32
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:20:40 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/03 23:28:00
- [ssh-ecdsa.c]
- fix memory leak; ECDSA_SIG_new() allocates 'r' and 's' for us, unlike
- DSA_SIG_new. Reported by Batz Spear; ok markus@
-
-commit a5103f413bde6f31bff85d6e1fd29799c647d765
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:20:14 2014 +1100
-
- - djm@cvs.openbsd.org 2014/02/02 03:44:32
- [auth1.c auth2-chall.c auth2-passwd.c authfile.c bufaux.c bufbn.c]
- [buffer.c cipher-3des1.c cipher.c clientloop.c gss-serv.c kex.c]
- [kexdhc.c kexdhs.c kexecdhc.c kexgexc.c kexecdhs.c kexgexs.c key.c]
- [monitor.c monitor_wrap.c packet.c readpass.c rsa.c serverloop.c]
- [ssh-add.c ssh-agent.c ssh-dss.c ssh-ecdsa.c ssh-ed25519.c]
- [ssh-keygen.c ssh-rsa.c sshconnect.c sshconnect1.c sshconnect2.c]
- [sshd.c]
- convert memset of potentially-private data to explicit_bzero()
-
-commit 1d2c4564265ee827147af246a16f3777741411ed
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:18:20 2014 +1100
-
- - tedu@cvs.openbsd.org 2014/01/31 16:39:19
- [auth2-chall.c authfd.c authfile.c bufaux.c bufec.c canohost.c]
- [channels.c cipher-chachapoly.c clientloop.c configure.ac hostfile.c]
- [kexc25519.c krl.c monitor.c sandbox-systrace.c session.c]
- [sftp-client.c ssh-keygen.c ssh.c sshconnect2.c sshd.c sshlogin.c]
- [openbsd-compat/explicit_bzero.c openbsd-compat/openbsd-compat.h]
- replace most bzero with explicit_bzero, except a few that cna be memset
- ok djm dtucker
-
-commit 3928de067c286683a95fbdbdb5fdb3c78a0e5efd
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:13:54 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/30 22:26:14
- [sandbox-systrace.c]
- allow shutdown(2) syscall in sandbox - it may be called by packet_close()
- from portable
- (Id sync only; change is already in portable)
-
-commit e1e480aee8a9af6cfbe7188667b7b940d6b57f9f
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:13:17 2014 +1100
-
- - jmc@cvs.openbsd.org 2014/01/29 14:04:51
- [sshd_config.5]
- document kbdinteractiveauthentication;
- requested From: Ross L Richardson
-
- dtucker/markus helped explain its workings;
-
-commit 7cc194f70d4a5ec9a82d19422eaf18db4a6624c6
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:12:56 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/29 06:18:35
- [Makefile.in auth.h auth2-jpake.c auth2.c jpake.c jpake.h monitor.c]
- [monitor.h monitor_wrap.c monitor_wrap.h readconf.c readconf.h]
- [schnorr.c schnorr.h servconf.c servconf.h ssh2.h sshconnect2.c]
- remove experimental, never-enabled JPAKE code; ok markus@
-
-commit b0f26544cf6f4feeb1a4f6db09fca834f5c9867d
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:10:01 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/29 00:19:26
- [sshd.c]
- use kill(0, ...) instead of killpg(0, ...); on most operating systems
- they are equivalent, but SUSv2 describes the latter as having undefined
- behaviour; from portable; ok dtucker
- (Id sync only; change is already in portable)
-
-commit f8f35bc471500348bb262039fb1fc43175d251b0
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:09:12 2014 +1100
-
- - jmc@cvs.openbsd.org 2014/01/28 14:13:39
- [ssh-keyscan.1]
- kill some bad Pa;
- From: Jan Stary
-
-commit 0ba85d696ae9daf66002c2e4ab0d6bb111e1a787
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:08:38 2014 +1100
-
- ignore a few more regress droppings
-
-commit ec93d15170b7a6ddf63fd654bd0f6a752acc19dd
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:07:13 2014 +1100
-
- - markus@cvs.openbsd.org 2014/01/27 20:13:46
- [digest.c digest-openssl.c digest-libc.c Makefile.in]
- rename digest.c to digest-openssl.c and add libc variant; ok djm@
-
-commit 4a1c7aa640fb97d3472d51b215b6a0ec0fd025c7
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:03:36 2014 +1100
-
- - markus@cvs.openbsd.org 2014/01/27 19:18:54
- [auth-rsa.c cipher.c ssh-agent.c sshconnect1.c sshd.c]
- replace openssl MD5 with our ssh_digest_*; ok djm@
-
-commit 4e8d937af79ce4e253f77ec93489d098b25becc3
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Feb 4 11:02:42 2014 +1100
-
- - markus@cvs.openbsd.org 2014/01/27 18:58:14
- [Makefile.in digest.c digest.h hostfile.c kex.h mac.c hmac.c hmac.h]
- replace openssl HMAC with an implementation based on our ssh_digest_*
- ok and feedback djm@
-
-commit 69d0d09f76bab5aec86fbf78489169f63bd16475
-Author: Tim Rice <tim@multitalents.net>
-Date: Fri Jan 31 14:25:18 2014 -0800
-
- - (tim) [Makefile.in] build regress/setuid-allow.
-
-commit 0eeafcd76b972a3d159f3118227c149a4d7817fe
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 31 14:18:51 2014 +1100
-
- - (dtucker) [readconf.c] Include <arpa/inet.h> for the hton macros. Fixes
- build with HP-UX's compiler. Patch from Kevin Brott.
-
-commit 7e5cec6070673e9f9785ffc749837ada22fbe99f
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jan 31 09:25:34 2014 +1100
-
- - (djm) [sandbox-seccomp-filter.c sandbox-systrace.c] Allow shutdown(2)
- syscall from sandboxes; it may be called by packet_close.
-
-commit cdb6c90811caa5df2df856be9b0b16db020fe31d
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 30 12:50:17 2014 +1100
-
- - (djm) Release openssh-6.5p1
-
-commit 996ea80b1884b676a901439f1f2681eb6ff68501
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 30 12:49:55 2014 +1100
-
- trim entries prior to openssh-6.0p1
-
-commit f5bbd3b657b6340551c8a95f74a70857ff8fac79
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 30 11:26:46 2014 +1100
-
- - (djm) [configure.ac atomicio.c] Kludge around NetBSD offering
- different symbols for 'read' when various compiler flags are
- in use, causing atomicio.c comparisons against it to break and
- read/write operations to hang; ok dtucker
-
-commit c2868192ddc4e1420a50389e18c05db20b0b1f32
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 30 10:21:19 2014 +1100
-
- - (djm) [configure.ac] Only check for width-specified integer types
- in headers that actually exist. patch from Tom G. Christensen;
- ok dtucker@
-
-commit c161fc90fc86e2035710570238a9e1ca7a68d2a5
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jan 29 21:01:33 2014 +1100
-
- - (djm) [configure.ac] Fix broken shell test '==' vs '='; patch from
- Tom G. Christensen
-
-commit 6f917ad376481995ab7d29fb53b08ec8d507eb9e
-Author: Tim Rice <tim@multitalents.net>
-Date: Tue Jan 28 10:26:25 2014 -0800
-
- - (tim) [regress/agent.sh regress/agent-ptrace.sh] Assign $? to a variable
- when used as an error message inside an if statement so we display the
- correct into. agent.sh patch from Petr Lautrbach.
-
-commit ab16ef4152914d44ce6f76e48167d26d22f66a06
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jan 28 15:08:12 2014 +1100
-
- - (djm) [sshd.c] Use kill(0, ...) instead of killpg(0, ...); the
- latter being specified to have undefined behaviour in SUSv3;
- ok dtucker
-
-commit ab0394905884dc6e58c3721211c6b38fb8fc2ca8
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jan 28 15:07:10 2014 +1100
-
- - (djm) [configure.ac] Search for inet_ntop in libnsl and libresovl;
- ok dtucker
-
-commit 4ab20a82d4d4168d62318923f62382f6ef242fcd
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Jan 27 17:35:04 2014 +1100
-
- - (dtucker) [Makefile.in] Remove trailing backslash which some make
- implementations (eg older Solaris) do not cope with.
-
-commit e7e8b3cfe9f8665faaf0e68b33df5bbb431bd129
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Jan 27 17:32:50 2014 +1100
-
- Welcome to 2014
-
-commit 5b447c0aac0dd444251e276f6bb3bbbe1c05331c
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Jan 26 09:46:53 2014 +1100
-
- - (djm) [configure.ac] correct AC_DEFINE for previous.
-
-commit 2035b2236d3b1f76c749c642a43e03c85eae76e6
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Jan 26 09:39:53 2014 +1100
-
- - (djm) [configure.ac sandbox-capsicum.c sandbox-rlimit.c] Disable
- RLIMIT_NOFILE pseudo-sandbox on FreeBSD. In some configurations,
- libc will attempt to open additional file descriptors for crypto
- offload and crash if they cannot be opened.
-
-commit a92ac7410475fbb00383c7402aa954dc0a75ae19
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Jan 26 09:38:03 2014 +1100
-
- - markus@cvs.openbsd.org 2014/01/25 20:35:37
- [kex.c]
- dh_need needs to be set to max(seclen, blocksize, ivlen, mac_len)
- ok dtucker@, noted by mancha
-
-commit 76eea4ab4e658670ca6e76dd1e6d17f262208b57
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Jan 26 09:37:25 2014 +1100
-
- - dtucker@cvs.openbsd.org 2014/01/25 10:12:50
- [cipher.c cipher.h kex.c kex.h kexgexc.c]
- Add a special case for the DH group size for 3des-cbc, which has an
- effective strength much lower than the key size. This causes problems
- with some cryptlib implementations, which don't support group sizes larger
- than 4k but also don't use the largest group size it does support as
- specified in the RFC. Based on a patch from Petr Lautrbach at Redhat,
- reduced by me with input from Markus. ok djm@ markus@
-
-commit 603b8f47f1cd9ed95a2017447db8e60ca6704594
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Jan 25 13:16:59 2014 +1100
-
- - (djm) [configure.ac] autoconf sets finds to 'yes' not '1', so test
- against the correct thing.
-
-commit c96d85376d779b6ac61525b5440010d344d2f23f
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Jan 25 13:12:28 2014 +1100
-
- - (djm) [configure.ac] Do not attempt to use capsicum sandbox unless
- sys/capability.h exists and cap_rights_limit is in libc. Fixes
- build on FreeBSD9x which provides the header but not the libc
- support.
-
-commit f62ecef9939cb3dbeb10602fd705d4db3976d822
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Jan 25 12:34:38 2014 +1100
-
- - (djm) [configure.ac] Fix detection of capsicum sandbox on FreeBSD
-
-commit b0e0f760b861676a3fe5c40133b270713d5321a9
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jan 24 14:27:04 2014 +1100
-
- - (djm) [Makefile.in regress/scp-ssh-wrapper.sh regress/scp.sh] Make
- the scp regress test actually test the built scp rather than the one
- in $PATH. ok dtucker@
-
-commit 42a092530159637da9cb7f9e1b5f4679e34a85e6
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jan 23 23:14:39 2014 +1100
-
- - (dtucker) [configure.ac] NetBSD's (and FreeBSD's) strnvis is gratuitously
- incompatible with OpenBSD's despite post-dating it by more than a decade.
- Declare it as broken, and document FreeBSD's as the same. ok djm@
-
-commit 617da33c20cb59f9ea6c99c881d92493371ef7b8
-Author: Tim Rice <tim@multitalents.net>
-Date: Wed Jan 22 19:16:10 2014 -0800
-
- - (tim) [session.c] Improve error reporting on set_id().
-
-commit 5c2ff5e31f57d303ebb414d84a934c02728fa568
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jan 22 21:30:12 2014 +1100
-
- - (djm) [configure.ac aclocal.m4] More tests to detect fallout from
- platform hardening options: include some long long int arithmatic
- to detect missing support functions for -ftrapv in libgcc and
- equivalents, actually test linking when -ftrapv is supplied and
- set either both -pie/-fPIE or neither. feedback and ok dtucker@
-
-commit 852472a54b8a0dc3e53786b313baaa86850a4273
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jan 22 16:31:18 2014 +1100
-
- - (djm) [configure.ac] Unless specifically requested, only attempt
- to build Position Independent Executables on gcc >= 4.x; ok dtucker
-
-commit ee87838786cef0194db36ae0675b3e7c4e8ec661
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jan 22 16:30:15 2014 +1100
-
- - (djm) [openbsd-compat/setproctitle.c] Don't fail to compile if a
- platform that is expected to use the reuse-argv style setproctitle
- hack surprises us by providing a setproctitle in libc; ok dtucker
-
-commit 5c96a154c7940fa67b1f11c421e390dbbc159f27
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jan 21 13:10:26 2014 +1100
-
- - (djm) [aclocal.m4] Flesh out the code run in the OSSH_CHECK_CFLAG_COMPILE
- and OSSH_CHECK_LDFLAG_LINK tests to give them a better chance of
- detecting toolchain-related problems; ok dtucker
-
-commit 9464ba6fb34bb42eb3501ec3c5143662e75674bf
-Author: Tim Rice <tim@multitalents.net>
-Date: Mon Jan 20 17:59:28 2014 -0800
-
- - (tim) [platform.c session.c] Fix bug affecting SVR5 platforms introduced
- with sftp chroot support. Move set_id call after chroot.
-
-commit a6d573caa14d490e6c42fb991bcb5c6860ec704b
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Jan 21 12:50:46 2014 +1100
-
- - (dtucker) [aclocal.m4] Differentiate between compile-time and link-time
- tests in the configure output. ok djm.
-
-commit 096118dc73ab14810b3c12785c0b5acb01ad6123
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Jan 21 12:48:51 2014 +1100
-
- - (dtucker) [configure.ac] Make PIE a configure-time option which defaults
- to on platforms where it's known to be reliably detected and off elsewhere.
- Works around platforms such as FreeBSD 9.1 where it does not interop with
- -ftrapv (it seems to work but fails when trying to link ssh). ok djm@
-
-commit f9df7f6f477792254eab33cdef71a6d66488cb88
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Jan 20 20:07:15 2014 +1100
-
- - (djm) [regress/cert-hostkey.sh] Fix regress failure on platforms that
- skip one or more key types (e.g. RHEL/CentOS 6.5); ok dtucker@
-
-commit c74e70eb52ccc0082bd5a70b5798bb01c114d138
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Jan 20 13:18:09 2014 +1100
-
- - (dtucker) [gss-serv-krb5.c] Fall back to krb5_cc_gen_new if the Kerberos
- implementation does not have krb5_cc_new_unique, similar to what we do
- in auth-krb5.c.
-
-commit 3510979e83b6a18ec8773c64c3fa04aa08b2e783
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Jan 20 12:41:53 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/20 00:08:48
- [digest.c]
- memleak; found by Loganaden Velvindron @ AfriNIC; ok markus@
-
-commit 7eee358d7a6580479bee5cd7e52810ebfd03e5b2
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jan 19 22:37:02 2014 +1100
-
- - dtucker@cvs.openbsd.org 2014/01/19 11:21:51
- [addrmatch.c]
- Cast the sizeof to socklen_t so it'll work even if the supplied len is
- negative. Suggested by and ok djm, ok deraadt.
-
-commit b7e01c09b56ab26e8fac56bbce0fd25e36d12bb0
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jan 19 22:36:13 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/19 04:48:08
- [ssh_config.5]
- fix inverted meaning of 'no' and 'yes' for CanonicalizeFallbackLocal
-
-commit 7b1ded04adce42efa25ada7c3a39818d3109b724
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jan 19 15:30:02 2014 +1100
-
- - dtucker@cvs.openbsd.org 2014/01/19 04:17:29
- [canohost.c addrmatch.c]
- Cast socklen_t when comparing to size_t and use socklen_t to iterate over
- the ip options, both to prevent signed/unsigned comparison warnings.
- Patch from vinschen at redhat via portable openssh, begrudging ok deraadt.
-
-commit 293ee3c9f0796d99ebb033735f0e315f2e0180bf
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jan 19 15:28:01 2014 +1100
-
- - dtucker@cvs.openbsd.org 2014/01/18 09:36:26
- [session.c]
- explicitly define USE_PIPES to 1 to prevent redefinition warnings in
- portable on platforms that use pipes for everything. From redhat @
- redhat.
-
-commit 2aca159d05f9e7880d1d8f1ce49a218840057f53
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jan 19 15:25:34 2014 +1100
-
- - dtucker@cvs.openbsd.org 2014/01/17 06:23:24
- [sftp-server.c]
- fix log message statvfs. ok djm
-
-commit 841f7da89ae8b367bb502d61c5c41916c6e7ae4c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Jan 18 22:12:15 2014 +1100
-
- - (dtucker) [sandbox-capsicum.c] Correct some error messages and make the
- return value check for cap_enter() consistent with the other uses in
- FreeBSD. From by Loganaden Velvindron @ AfriNIC via bz#2140.
-
-commit fdce3731660699b2429e93e822f2ccbaccd163ae
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Jan 18 21:12:42 2014 +1100
-
- - (dtucker) [configure.ac] On Cygwin the getopt variables (like optargs,
- optind) are defined in getopt.h already. Unfortunately they are defined as
- "declspec(dllimport)" for historical reasons, because the GNU linker didn't
- allow auto-import on PE/COFF targets way back when. The problem is the
- dllexport attributes collide with the definitions in the various source
- files in OpenSSH, which obviousy define the variables without
- declspec(dllimport). The least intrusive way to get rid of these warnings
- is to disable warnings for GCC compiler attributes when building on Cygwin.
- Patch from vinschen at redhat.com.
-
-commit 1411c9263f46e1ee49d0d302bf7258ebe69ce827
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Jan 18 21:03:59 2014 +1100
-
- - (dtucker) [openbsd-compat/bsd-cygwin_util.h] Add missing function
- declarations that stopped being included when we stopped including
- <windows.h> from openbsd-compat/bsd-cygwin_util.h. Patch from vinschen at
- redhat.com.
-
-commit 89c532d843c95a085777c66365067d64d1937eb9
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Jan 18 20:43:49 2014 +1100
-
- - (dtucker) [uidswap.c] Prevent unused variable warnings on Cygwin. Patch
- from vinschen at redhat.com
-
-commit 355f861022be7b23d3009fae8f3c9f6f7fc685f7
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Jan 18 00:12:38 2014 +1100
-
- - (dtucker) [defines.h] Move our definitions of uintXX_t types down to after
- they're defined if we have to define them ourselves. Fixes builds on old
- AIX.
-
-commit a3357661ee1d5d553294f36e4940e8285c7f1332
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Jan 18 00:03:57 2014 +1100
-
- - (dtucker) [readconf.c] Wrap paths.h inside an ifdef. Allows building on
- Solaris.
-
-commit 9edcbff46ff01c8d5dee9c1aa843f09e9ad8a80e
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 21:54:32 2014 +1100
-
- - (dtucker) [configure.ac] Have --without-toolchain-hardening not turn off
- stack-protector since that has a separate flag that's been around a while.
-
-commit 6d725687c490d4ba957a1bbc0ba0a2956c09fa69
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 19:17:34 2014 +1100
-
- - (dtucker) [configure.ac] Also look in inttypes.h for uintXX_t types.
-
-commit 5055699c7f7c7ef21703a443ec73117da392f6ae
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 18:48:22 2014 +1100
-
- - (dtucker) [openbsd-compat/bsd-statvfs.h] Only start including headers if we
- need them to cut down on the name collisions.
-
-commit a5cf1e220def07290260e4125e74f41ac75cf88d
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 18:10:58 2014 +1100
-
- - (dtucker) [configure.ac openbsd-compat/bsd-statvfs.c
- openbsd-compat/bsd-statvfs.h] Implement enough of statvfs on top of statfs
- to be useful (and for the regression tests to pass) on platforms that
- have statfs and fstatfs. ok djm@
-
-commit 1357d71d7b6d269969520aaa3e84d312ec971d5b
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 18:00:40 2014 +1100
-
- - (dtucker) Fix typo in #ifndef.
-
-commit d23a91ffb289d3553a58b7a60cec39fba9f0f506
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 17:32:30 2014 +1100
-
- - (dtucker) [configure.ac digest.c openbsd-compat/openssl-compat.c
- openbsd-compat/openssl-compat.h] Add compatibility layer for older
- openssl versions. ok djm@
-
-commit 868ea1ea1c1bfdbee5dbad78f81999c5983ecf31
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jan 17 16:47:04 2014 +1100
-
- - (djm) [Makefile.in configure.ac sandbox-capsicum.c sandbox-darwin.c]
- [sandbox-null.c sandbox-rlimit.c sandbox-seccomp-filter.c]
- [sandbox-systrace.c ssh-sandbox.h sshd.c] Support preauth sandboxing
- using the Capsicum API introduced in FreeBSD 10. Patch by Dag-Erling
- Smorgrav, updated by Loganaden Velvindron @ AfriNIC; ok dtucker@
-
-commit a9d186a8b50d18869a10e9203abf71c83ddb1f79
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 16:30:49 2014 +1100
-
- - dtucker@cvs.openbsd.org 2014/01/17 05:26:41
- [digest.c]
- remove unused includes. ok djm@
-
-commit 5f1c57a7a7eb39c0e4fee3367712337dbcaef024
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 16:29:45 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/17 00:21:06
- [sftp-client.c]
- signed/unsigned comparison warning fix; from portable (Id sync only)
-
-commit c548722361d89fb12c108528f96b306a26477b18
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 15:12:16 2014 +1100
-
- - (dtucker) [configure.ac] Split AC_CHECK_FUNCS for OpenSSL functions into
- separate lines and alphabetize for easier diffing of changes.
-
-commit acad351a5b1c37de9130c9c1710445cc45a7f6b9
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 14:20:05 2014 +1100
-
- - (dtucker) [defines.h] Add typedefs for uintXX_t types for platforms that
- don't have them.
-
-commit c3ed065ce8417aaa46490836648c173a5010f226
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 14:18:45 2014 +1100
-
- - (dtucker) [openbsd-compat/bcrypt_pbkdf.c] Wrap stdlib.h include inside
- #ifdef HAVE_STDINT_H.
-
-commit f45f78ae437062c7d9506c5f475b7215f486be44
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 12:43:43 2014 +1100
-
- - (dtucker) [blocks.c fe25519.c ge25519.c hash.c sc25519.c verify.c] Include
- includes.h to pull in all of the compatibility stuff.
-
-commit 99df369d0340caac145d57f700d830147ff18b87
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 12:42:17 2014 +1100
-
- - (dtucker) [poly1305.c] Wrap stdlib.h include inside #ifdef HAVE_STDINT_H.
-
-commit ac413b62ea1957e80c711acbe0c11b908273fc01
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 12:31:33 2014 +1100
-
- - (dtucker) [crypto_api.h] Wrap stdlib.h include inside #ifdef HAVE_STDINT_H.
-
-commit 1c4a011e9c939e74815346a560843e1862c300b8
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 12:23:23 2014 +1100
-
- - (dtucker) [loginrec.c] Cast to the types specfied in the format
- specification to prevent warnings.
-
-commit c3d483f9a8275be1113535a1e0d0e384f605f3c4
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jan 17 11:20:26 2014 +1100
-
- - (djm) [sftp-client.c] signed/unsigned comparison fix
-
-commit fd994379dd972417d0491767f7cd9b5bf23f4975
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jan 17 09:53:24 2014 +1100
-
- - (dtucker) [aclocal.m4 configure.ac] Add some additional compiler/toolchain
- hardening flags including -fstack-protector-strong. These default to on
- if the toolchain supports them, but there is a configure-time knob
- (--without-hardening) to disable them if necessary. ok djm@
-
-commit 366224d21768ee8ec28cfbcc5fbade1b32582d58
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 16 18:51:44 2014 +1100
-
- - (djm) [README] update release notes URL.
-
-commit 2ae77e64f8fa82cbf25c9755e8e847709b978b40
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 16 18:51:07 2014 +1100
-
- - (djm) [contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
- [contrib/suse/openssh.spec] Crank RPM spec version numbers.
-
-commit 0fa29e6d777c73a1b4ddd3b996b06ee20022ae8a
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 16 18:42:31 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/16 07:32:00
- [version.h]
- openssh-6.5
-
-commit 52c371cd6d2598cc73d4e633811b3012119c47e2
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jan 16 18:42:10 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/16 07:31:09
- [sftp-client.c]
- needless and incorrect cast to size_t can break resumption of
- large download; patch from tobias@
-
-commit 91b580e4bec55118bf96ab3cdbe5a50839e75d0a
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Jan 12 19:21:22 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/12 08:13:13
- [bufaux.c buffer.h kex.c kex.h kexc25519.c kexc25519c.c kexc25519s.c]
- [kexdhc.c kexdhs.c kexecdhc.c kexecdhs.c kexgexc.c kexgexs.c]
- avoid use of OpenSSL BIGNUM type and functions for KEX with
- Curve25519 by adding a buffer_put_bignum2_from_string() that stores
- a string using the bignum encoding rules. Will make it easier to
- build a reduced-feature OpenSSH without OpenSSL in the future;
- ok markus@
-
-commit af5d4481f4c7c8c3c746e68b961bb85ef907800e
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Jan 12 19:20:47 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/10 05:59:19
- [sshd_config]
- the /etc/ssh/ssh_host_ed25519_key is loaded by default too
-
-commit 58cd63bc63038acddfb4051ed14e11179d8f4941
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jan 10 10:59:24 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/09 23:26:48
- [sshconnect.c sshd.c]
- ban clients/servers that suffer from SSH_BUG_DERIVEKEY, they are ancient,
- deranged and might make some attacks on KEX easier; ok markus@
-
-commit b3051d01e505c9c2dc00faab472a0d06fa6b0e65
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jan 10 10:58:53 2014 +1100
-
- - djm@cvs.openbsd.org 2014/01/09 23:20:00
- [digest.c digest.h hostfile.c kex.c kex.h kexc25519.c kexc25519c.c]
- [kexc25519s.c kexdh.c kexecdh.c kexecdhc.c kexecdhs.c kexgex.c kexgexc.c]
- [kexgexs.c key.c key.h roaming_client.c roaming_common.c schnorr.c]
- [schnorr.h ssh-dss.c ssh-ecdsa.c ssh-rsa.c sshconnect2.c]
- Introduce digest API and use it to perform all hashing operations
- rather than calling OpenSSL EVP_Digest* directly. Will make it easier
- to build a reduced-feature OpenSSH without OpenSSL in future;
- feedback, ok markus@
-
-commit e00e413dd16eb747fb2c15a099971d91c13cf70f
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jan 10 10:40:45 2014 +1100
-
- - guenther@cvs.openbsd.org 2014/01/09 03:26:00
- [sftp-common.c]
- When formating the time for "ls -l"-style output, show dates in the future
- with the year, and rearrange a comparison to avoid a potentional signed
- arithmetic overflow that would give the wrong result.
-
- ok djm@
-
-commit 3e49853650448883685cfa32fa382d0ba6d51d48
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jan 10 10:37:05 2014 +1100
-
- - tedu@cvs.openbsd.org 2014/01/04 17:50:55
- [mac.c monitor_mm.c monitor_mm.h xmalloc.c]
- use standard types and formats for size_t like variables. ok dtucker
-
-commit a9c1e500ef609795cbc662848edb1a1dca279c81
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jan 8 16:13:12 2014 +1100
-
- - (djm) [regress/.cvsignore] Ignore regress test droppings; ok dtucker@
-
-commit 324541e5264e1489ca0babfaf2b39612eb80dfb3
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Dec 31 12:25:40 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/30 23:52:28
- [auth2-hostbased.c auth2-pubkey.c compat.c compat.h ssh-rsa.c]
- [sshconnect.c sshconnect2.c sshd.c]
- refuse RSA keys from old proprietary clients/servers that use the
- obsolete RSA+MD5 signature scheme. it will still be possible to connect
- with these clients/servers but only DSA keys will be accepted, and we'll
- deprecate them entirely in a future release. ok markus@
-
-commit 9f4c8e797ea002a883307ca906f1f1f815010e78
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:57:46 2013 +1100
-
- - (djm) [regress/Makefile] Add some generated files for cleaning
-
-commit 106bf1ca3c7a5fdc34f9fd7a1fe651ca53085bc5
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:54:03 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/29 05:57:02
- [sshconnect.c]
- when showing other hostkeys, don't forget Ed25519 keys
-
-commit 0fa47cfb32c239117632cab41e4db7d3e6de5e91
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:53:39 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/29 05:42:16
- [ssh.c]
- don't forget to load Ed25519 certs too
-
-commit b9a95490daa04cc307589897f95bfaff324ad2c9
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:50:15 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/29 04:35:50
- [authfile.c]
- don't refuse to load Ed25519 certificates
-
-commit f72cdde6e6fabc51d2a62f4e75b8b926d9d7ee89
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:49:55 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/29 04:29:25
- [authfd.c]
- allow deletion of ed25519 keys from the agent
-
-commit 29ace1cb68cc378a464c72c0fd67aa5f9acd6b5b
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:49:31 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/29 04:20:04
- [key.c]
- to make sure we don't omit any key types as valid CA keys again,
- factor the valid key type check into a key_type_is_valid_ca()
- function
-
-commit 9de4fcdc5a9cff48d49a3e2f6194d3fb2d7ae34d
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:49:13 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/29 02:49:52
- [key.c]
- correct comment for key_drop_cert()
-
-commit 5baeacf8a80f054af40731c6f92435f9164b8e02
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:48:55 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/29 02:37:04
- [key.c]
- correct comment for key_to_certified()
-
-commit 83f2fe26cb19330712c952eddbd3c0b621674adc
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:48:38 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/29 02:28:10
- [key.c]
- allow ed25519 keys to appear as certificate authorities
-
-commit 06122e9a74bb488b0fe0a8f64e1135de870f9cc0
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:48:15 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/27 22:37:18
- [ssh-rsa.c]
- correct comment
-
-commit 3e19295c3a253c8dc8660cf45baad7f45fccb969
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:47:50 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/27 22:30:17
- [ssh-dss.c ssh-ecdsa.c ssh-rsa.c]
- make the original RSA and DSA signing/verification code look more like
- the ECDSA/Ed25519 ones: use key_type_plain() when checking the key type
- rather than tediously listing all variants, use __func__ for debug/
- error messages
-
-commit 137977180be6254639e2c90245763e6965f8d815
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:47:14 2013 +1100
-
- - tedu@cvs.openbsd.org 2013/12/21 07:10:47
- [ssh-keygen.1]
- small typo
-
-commit 339a48fe7ffb3186d22bbaa9efbbc3a053e602fd
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:46:49 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/19 22:57:13
- [poly1305.c poly1305.h]
- use full name for author, with his permission
-
-commit 0b36c83148976c7c8268f4f41497359e2fb26251
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:45:51 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/19 01:19:41
- [ssh-agent.c]
- bz#2186: don't crash (NULL deref) when deleting PKCS#11 keys from an agent
- that has a mix of normal and PKCS#11 keys; fix from jay AT slushpupie.com;
- ok dtucker
-
-commit 4def184e9b6c36be6d965a9705632fc4c0c2a8af
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:45:26 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/19 01:04:36
- [channels.c]
- bz#2147: fix multiple remote forwardings with dynamically assigned
- listen ports. In the s->c message to open the channel we were sending
- zero (the magic number to request a dynamic port) instead of the actual
- listen port. The client therefore had no way of discriminating between
- them.
-
- Diagnosis and fix by ronf AT timeheart.net
-
-commit bf25d114e23a803f8feca8926281b1aaedb6191b
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:44:56 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/19 00:27:57
- [auth-options.c]
- simplify freeing of source-address certificate restriction
-
-commit bb3dafe7024a5b4e851252e65ee35d45b965e4a8
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:44:29 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/12/19 00:19:12
- [serverloop.c]
- Cast client_alive_interval to u_int64_t before assinging to
- max_time_milliseconds to avoid potential integer overflow in the timeout.
- bz#2170, patch from Loganaden Velvindron, ok djm@
-
-commit ef275ead3dcadde4db1efe7a0aa02b5e618ed40c
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:44:07 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/19 00:10:30
- [ssh-add.c]
- skip requesting smartcard PIN when removing keys from agent; bz#2187
- patch from jay AT slushpupie.com; ok dtucker
-
-commit 7d97fd9a1cae778c3eacf16e09f5da3689d616c6
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 29 17:40:18 2013 +1100
-
- - (djm) [loginrec.c] Check for username truncation when looking up lastlog
- entries
-
-commit 77244afe3b6d013b485e0952eaab89b9db83380f
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Dec 21 17:02:39 2013 +1100
-
- 20131221
- - (dtucker) [regress/keytype.sh] Actually test ecdsa key types.
-
-commit 53f8e784dc431a82d31c9b0e95b144507f9330e9
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Dec 19 11:31:44 2013 +1100
-
- - (dtucker) [auth-pam.c] bz#2163: check return value from pam_get_item().
- Patch from Loganaden Velvindron.
-
-commit 1fcec9d4f265e38af248c4c845986ca8c174bd68
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Dec 19 11:00:12 2013 +1100
-
- - (dtucker) [configure.ac] bz#2178: Don't try to use BSM on Solaris versions
- greater than 11 either rather than just 11. Patch from Tomas Kuthan.
-
-commit 6674eb9683afd1ea4eb35670b5e66815543a759e
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Dec 18 17:50:39 2013 +1100
-
- - markus@cvs.openbsd.org 2013/12/17 10:36:38
- [crypto_api.h]
- I've assempled the header file by cut&pasting from generated headers
- and the source files.
-
-commit d58a5964426ee014384d67d775d16712e93057f3
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Dec 18 17:50:13 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/15 21:42:35
- [cipher-chachapoly.c]
- add some comments and constify a constant
-
-commit 059321d19af24d87420de3193f79dfab23556078
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Dec 18 17:49:48 2013 +1100
-
- - pascal@cvs.openbsd.org 2013/12/15 18:17:26
- [ssh-add.c]
- Make ssh-add also add .ssh/id_ed25519; fixes lie in manual page.
- ok markus@
-
-commit 155b5a5bf158767f989215479ded2a57f331e1c6
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Dec 18 17:48:32 2013 +1100
-
- - markus@cvs.openbsd.org 2013/12/09 11:08:17
- [crypto_api.h]
- remove unused defines
-
-commit 8a56dc2b6b48b05590810e7f4c3567508410000c
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Dec 18 17:48:11 2013 +1100
-
- - markus@cvs.openbsd.org 2013/12/09 11:03:45
- [blocks.c ed25519.c fe25519.c fe25519.h ge25519.c ge25519.h]
- [ge25519_base.data hash.c sc25519.c sc25519.h verify.c]
- Add Authors for the public domain ed25519/nacl code.
- see also http://nacl.cr.yp.to/features.html
- All of the NaCl software is in the public domain.
- and http://ed25519.cr.yp.to/software.html
- The Ed25519 software is in the public domain.
-
-commit 6575c3acf31fca117352f31f37b16ae46e664837
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Dec 18 17:47:02 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/12/08 09:53:27
- [sshd_config.5]
- Use a literal for the default value of KEXAlgorithms. ok deraadt jmc
-
-commit 8ba0ead6985ea14999265136b14ffd5aeec516f9
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Dec 18 17:46:27 2013 +1100
-
- - naddy@cvs.openbsd.org 2013/12/07 11:58:46
- [ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh-keysign.8 ssh.1]
- [ssh_config.5 sshd.8 sshd_config.5]
- add missing mentions of ed25519; ok djm@
-
-commit 4f752cf71cf44bf4bc777541156c2bf56daf9ce9
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Dec 18 17:45:35 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/07 08:08:26
- [ssh-keygen.1]
- document -a and -o wrt new key format
-
-commit 6d6fcd14e23a9053198342bb379815b15e504084
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 8 15:53:28 2013 +1100
-
- - (djm) [Makefile.in regress/Makefile regress/agent-ptrace.sh]
- [regress/setuid-allowed.c] Check that ssh-agent is not on a no-setuid
- filesystem before running agent-ptrace.sh; ok dtucker
-
-commit 7e6e42fb532c7dafd7078ef5e9e2d3e47fcf6752
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Dec 8 08:23:08 2013 +1100
-
- - (djm) [openbsd-compat/bsd-setres_id.c] Missing header; from Corinna
- Vinschen
-
-commit da3ca351b49d52ae85db2e3998265dc3c6617068
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 21:43:46 2013 +1100
-
- - (djm) [Makefile.in] PATHSUBS and keygen bits for Ed25519; from
- Loganaden Velvindron @ AfriNIC in bz#2179
-
-commit eb401585bb8336cbf81fe4fc58eb9f7cac3ab874
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 17:07:15 2013 +1100
-
- - (djm) [regress/cert-hostkey.sh] Fix merge botch
-
-commit f54542af3ad07532188b10136ae302314ec69ed6
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 16:32:44 2013 +1100
-
- - markus@cvs.openbsd.org 2013/12/06 13:52:46
- [regress/Makefile regress/agent.sh regress/cert-hostkey.sh]
- [regress/cert-userkey.sh regress/keytype.sh]
- test ed25519 support; from djm@
-
-commit f104da263de995f66b6861b4f3368264ee483d7f
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 12:37:53 2013 +1100
-
- - (djm) [ed25519.c ssh-ed25519.c openbsd-compat/Makefile.in]
- [openbsd-compat/bcrypt_pbkdf.c] Make ed25519/new key format compile on
- Linux
-
-commit 1ff130dac9b7aea0628f4ad30683431fe35e0020
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 11:51:51 2013 +1100
-
- - [configure.ac openbsd-compat/Makefile.in openbsd-compat/bcrypt_pbkdf.c]
- [openbsd-compat/blf.h openbsd-compat/blowfish.c]
- [openbsd-compat/openbsd-compat.h] Start at supporting bcrypt_pbkdf in
- portable.
-
-commit 4260828a2958ebe8c96f66d8301dac53f4cde556
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 11:38:03 2013 +1100
-
- - [authfile.c] Conditionalise inclusion of util.h
-
-commit a913442bac8a26fd296a3add51293f8f6f9b3b4c
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 11:35:36 2013 +1100
-
- - [Makefile.in] Add ed25519 sources
-
-commit ca570a519cb846da61d002c7f46fa92e39c83e45
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 11:29:09 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/07 00:19:15
- [key.c]
- set k->cert = NULL after freeing it
-
-commit 3cccc0e155229a2f2d86b6df40bd4559b4f960ff
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 11:27:47 2013 +1100
-
- - [blocks.c ed25519.c fe25519.c fe25519.h ge25519.c ge25519.h]
- [ge25519_base.data hash.c sc25519.c sc25519.h verify.c] Fix RCS idents
-
-commit a7827c11b3f0380b7e593664bd62013ff9c131db
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 11:24:30 2013 +1100
-
- - jmc@cvs.openbsd.org 2013/12/06 15:29:07
- [sshd.8]
- missing comma;
-
-commit 5be9d9e3cbd9c66f24745d25bf2e809c1d158ee0
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 11:24:01 2013 +1100
-
- - markus@cvs.openbsd.org 2013/12/06 13:39:49
- [authfd.c authfile.c key.c key.h myproposal.h pathnames.h readconf.c]
- [servconf.c ssh-agent.c ssh-keygen.c ssh-keyscan.1 ssh-keyscan.c]
- [ssh-keysign.c ssh.c ssh_config.5 sshd.8 sshd.c verify.c ssh-ed25519.c]
- [sc25519.h sc25519.c hash.c ge25519_base.data ge25519.h ge25519.c]
- [fe25519.h fe25519.c ed25519.c crypto_api.h blocks.c]
- support ed25519 keys (hostkeys and user identities) using the public
- domain ed25519 reference code from SUPERCOP, see
- http://ed25519.cr.yp.to/software.html
- feedback, help & ok djm@
-
-commit bcd00abd8451f36142ae2ee10cc657202149201e
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 10:41:55 2013 +1100
-
- - markus@cvs.openbsd.org 2013/12/06 13:34:54
- [authfile.c authfile.h cipher.c cipher.h key.c packet.c ssh-agent.c]
- [ssh-keygen.c PROTOCOL.key] new private key format, bcrypt as KDF by
- default; details in PROTOCOL.key; feedback and lots help from djm;
- ok djm@
-
-commit f0e9060d236c0e38bec2fa1c6579fb0a2ea6458d
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 10:40:26 2013 +1100
-
- - markus@cvs.openbsd.org 2013/12/06 13:30:08
- [authfd.c key.c key.h ssh-agent.c]
- move private key (de)serialization to key.c; ok djm
-
-commit 0f8536da23a6ef26e6495177c0d8a4242b710289
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 10:31:37 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/06 03:40:51
- [ssh-keygen.c]
- remove duplicated character ('g') in getopt() string;
- document the (few) remaining option characters so we don't have to
- rummage next time.
-
-commit 393920745fd328d3fe07f739a3cf7e1e6db45b60
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Dec 7 10:31:08 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/05 22:59:45
- [sftp-client.c]
- fix memory leak in error path in do_readdir(); pointed out by
- Loganaden Velvindron @ AfriNIC in bz#2163
-
-commit 534b2ccadea5e5e9a8b27226e6faac3ed5552e97
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 5 14:07:27 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/05 01:16:41
- [servconf.c servconf.h]
- bz#2161 - fix AuthorizedKeysCommand inside a Match block and
- rearrange things so the same error is harder to make next time;
- with and ok dtucker@
-
-commit 8369c8e61a3408ec6bb75755fad4ffce29b5fdbe
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Dec 5 11:00:16 2013 +1100
-
- - (dtucker) [configure.ac] bz#2173: use pkg-config --libs to include correct
- -L location for libedit. Patch from Serge van den Boom.
-
-commit 9275df3e0a2a3bc3897f7d664ea86a425c8a092d
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 5 10:26:32 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/04 04:20:01
- [sftp-client.c]
- bz#2171: don't leak local_fd on error; from Loganaden Velvindron @
- AfriNIC
-
-commit 960f6a2b5254e4da082d8aa3700302ed12dc769a
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 5 10:26:14 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/02 03:13:14
- [cipher.c]
- correct bzero of chacha20+poly1305 key context. bz#2177 from
- Loganaden Velvindron @ AfriNIC
-
- Also make it a memset for consistency with the rest of cipher.c
-
-commit f7e8a8796d661c9d6692ab837e1effd4f5ada1c2
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 5 10:25:51 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/02 03:09:22
- [key.c]
- make key_to_blob() return a NULL blob on failure; part of
- bz#2175 from Loganaden Velvindron @ AfriNIC
-
-commit f1e44ea9d9a6d4c1a95a0024132e603bd1778c9c
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 5 10:23:21 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/02 02:56:17
- [ssh-pkcs11-helper.c]
- use-after-free; bz#2175 patch from Loganaden Velvindron @ AfriNIC
-
-commit 114e540b15d57618f9ebf624264298f80bbd8c77
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 5 10:22:57 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/02 02:50:27
- [PROTOCOL.chacha20poly1305]
- typo; from Jon Cave
-
-commit e4870c090629e32f2cb649dc16d575eeb693f4a8
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 5 10:22:39 2013 +1100
-
- - djm@cvs.openbsd.org 2013/12/01 23:19:05
- [PROTOCOL]
- mention curve25519-sha256@libssh.org key exchange algorithm
-
-commit 1d2f8804a6d33a4e908b876b2e1266b8260ec76b
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 5 10:22:03 2013 +1100
-
- - deraadt@cvs.openbsd.org 2013/11/26 19:15:09
- [pkcs11.h]
- cleanup 1 << 31 idioms. Resurrection of this issue pointed out by
- Eitan Adler ok markus for ssh, implies same change in kerberosV
-
-commit bdb352a54f82df94a548e3874b22f2d6ae90328d
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 5 10:20:52 2013 +1100
-
- - jmc@cvs.openbsd.org 2013/11/26 12:14:54
- [ssh.1 ssh.c]
- - put -Q in the right place
- - Ar was a poor choice for the arguments to -Q. i've chosen an
- admittedly equally poor Cm, at least consistent with the rest
- of the docs. also no need for multiple instances
- - zap a now redundant Nm
- - usage() sync
-
-commit d937dc084a087090f1cf5395822c3ac958d33759
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 5 10:19:54 2013 +1100
-
- - deraadt@cvs.openbsd.org 2013/11/25 18:04:21
- [ssh.1 ssh.c]
- improve -Q usage and such. One usage change is that the option is now
- case-sensitive
- ok dtucker markus djm
-
-commit dec0393f7ee8aabc7d9d0fc2c5fddb4bc649112e
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Dec 5 10:18:43 2013 +1100
-
- - jmc@cvs.openbsd.org 2013/11/21 08:05:09
- [ssh_config.5 sshd_config.5]
- no need for .Pp before displays;
-
-commit 8a073cf57940aabf85e49799f89f5d5e9b072c1b
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 21 14:26:18 2013 +1100
-
- - djm@cvs.openbsd.org 2013/11/21 03:18:51
- [regress/cipher-speed.sh regress/integrity.sh regress/rekey.sh]
- [regress/try-ciphers.sh]
- use new "ssh -Q cipher-auth" query to obtain lists of authenticated
- encryption ciphers instead of specifying them manually; ensures that
- the new chacha20poly1305@openssh.com mode is tested;
-
- ok markus@ and naddy@ as part of the diff to add
- chacha20poly1305@openssh.com
-
-commit ea61b2179f63d48968dd2c9617621002bb658bfe
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 21 14:25:15 2013 +1100
-
- - djm@cvs.openbsd.org 2013/11/21 03:16:47
- [regress/modpipe.c]
- use unsigned long long instead of u_int64_t here to avoid warnings
- on some systems portable OpenSSH is built on.
-
-commit 36aba25b0409d2db6afc84d54bc47a2532d38424
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 21 14:24:42 2013 +1100
-
- - djm@cvs.openbsd.org 2013/11/21 03:15:46
- [regress/krl.sh]
- add some reminders for additional tests that I'd like to implement
-
-commit fa7a20bc289f09b334808d988746bc260a2f60c9
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 21 14:24:08 2013 +1100
-
- - naddy@cvs.openbsd.org 2013/11/18 05:09:32
- [regress/forward-control.sh]
- bump timeout to 10 seconds to allow slow machines (e.g. Alpha PC164)
- to successfully run this; ok djm@
- (ID sync only; our timeouts are already longer)
-
-commit 0fde8acdad78a4d20cadae974376cc0165f645ee
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 21 14:12:23 2013 +1100
-
- - djm@cvs.openbsd.org 2013/11/21 00:45:44
- [Makefile.in PROTOCOL PROTOCOL.chacha20poly1305 authfile.c chacha.c]
- [chacha.h cipher-chachapoly.c cipher-chachapoly.h cipher.c cipher.h]
- [dh.c myproposal.h packet.c poly1305.c poly1305.h servconf.c ssh.1]
- [ssh.c ssh_config.5 sshd_config.5] Add a new protocol 2 transport
- cipher "chacha20-poly1305@openssh.com" that combines Daniel
- Bernstein's ChaCha20 stream cipher and Poly1305 MAC to build an
- authenticated encryption mode.
-
- Inspired by and similar to Adam Langley's proposal for TLS:
- http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03
- but differs in layout used for the MAC calculation and the use of a
- second ChaCha20 instance to separately encrypt packet lengths.
- Details are in the PROTOCOL.chacha20poly1305 file.
-
- Feedback markus@, naddy@; manpage bits Loganden Velvindron @ AfriNIC
- ok markus@ naddy@
-
-commit fdb2306acdc3eb2bc46b6dfdaaf6005c650af22a
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 21 13:57:15 2013 +1100
-
- - deraadt@cvs.openbsd.org 2013/11/20 20:54:10
- [canohost.c clientloop.c match.c readconf.c sftp.c]
- unsigned casts for ctype macros where neccessary
- ok guenther millert markus
-
-commit e00167307e4d3692695441e9bd712f25950cb894
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 21 13:56:49 2013 +1100
-
- - deraadt@cvs.openbsd.org 2013/11/20 20:53:10
- [scp.c]
- unsigned casts for ctype macros where neccessary
- ok guenther millert markus
-
-commit 23e00aa6ba9eee0e0c218f2026bf405ad4625832
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 21 13:56:28 2013 +1100
-
- - djm@cvs.openbsd.org 2013/11/20 02:19:01
- [sshd.c]
- delay closure of in/out fds until after "Bad protocol version
- identification..." message, as get_remote_ipaddr/get_remote_port
- require them open.
-
-commit 867e6934be6521f87f04a5ab86702e2d1b314245
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 21 13:56:06 2013 +1100
-
- - markus@cvs.openbsd.org 2013/11/13 13:48:20
- [ssh-pkcs11.c]
- add missing braces found by pedro
-
-commit 0600c7020f4fe68a780bd7cf21ff541a8d4b568a
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 21 13:55:43 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/11/08 11:15:19
- [bufaux.c bufbn.c buffer.c sftp-client.c sftp-common.c sftp-glob.c]
- [uidswap.c] Include stdlib.h for free() as per the man page.
-
-commit b6a75b0b93b8faa6f79c3a395ab6c71f3f880b80
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Nov 10 20:25:22 2013 +1100
-
- - (dtucker) [regress/keytype.sh] Populate ECDSA key types to be tested by
- querying the ones that are compiled in.
-
-commit 2c89430119367eb1bc96ea5ee55de83357e4c926
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Nov 10 12:38:42 2013 +1100
-
- - (dtucker) [key.c] Check for the correct defines for NID_secp521r1.
-
-commit dd5264db5f641dbd03186f9e5e83e4b14b3d0003
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Nov 9 22:32:51 2013 +1100
-
- - (dtucker) [configure.ac] Add missing "test".
-
-commit 95cb2d4eb08117be061f3ff076adef3e9a5372c3
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Nov 9 22:02:31 2013 +1100
-
- - (dtucker) [configure.ac] Fix brackets in NID_secp521r1 test.
-
-commit 37bcef51b3d9d496caecea6394814d2f49a1357f
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Nov 9 18:39:25 2013 +1100
-
- - (dtucker) [configure.ac kex.c key.c myproposal.h] Test for the presence of
- NID_X9_62_prime256v1, NID_secp384r1 and NID_secp521r1 and test that the
- latter actually works before using it. Fedora (at least) has NID_secp521r1
- that doesn't work (see https://bugzilla.redhat.com/show_bug.cgi?id=1021897).
-
-commit 6e2fe81f926d995bae4be4a6b5b3c88c1c525187
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Nov 9 16:55:03 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/11/09 05:41:34
- [regress/test-exec.sh regress/rekey.sh]
- Use smaller test data files to speed up tests. Grow test datafiles
- where necessary for a specific test.
-
-commit aff7ef1bb8b7c1eeb1f4812129091c5adbf51848
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Nov 9 00:19:22 2013 +1100
-
- - (dtucker) [contrib/cygwin/ssh-host-config] Simplify host key generation:
- rather than testing and generating each key, call ssh-keygen -A.
- Patch from vinschen at redhat.com.
-
-commit 882abfd3fb3c98cfe70b4fc79224770468b570a5
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Nov 9 00:17:41 2013 +1100
-
- - (dtucker) [Makefile.in configure.ac] Set MALLOC_OPTIONS per platform
- and pass in TEST_ENV. Unknown options cause stderr to get polluted
- and the stderr-data test to fail.
-
-commit 8c333ec23bdf7da917aa20ac6803a2cdd79182c5
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Nov 8 21:12:58 2013 +1100
-
- - (dtucker) [openbsd-compat/bsd-poll.c] Add headers to prevent compile
- warnings.
-
-commit d94240b2f6b376b6e9de187e4a0cd4b89dfc48cb
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Nov 8 21:10:04 2013 +1100
-
- - (dtucker) [myproposal.h] Conditionally enable CURVE25519_SHA256.
-
-commit 1c8ce34909886288a3932dce770deec5449f7bb5
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Nov 8 19:50:32 2013 +1100
-
- - (dtucker) [kex.c] Only enable CURVE25519_SHA256 if we actually have
- EVP_sha256.
-
-commit ccdb9bec46bcc88549b26a94aa0bae2b9f51031c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Nov 8 18:54:38 2013 +1100
-
- - (dtucker) [openbsd-compat/openbsd-compat.h] Add null implementation of
- arc4random_stir for platforms that have arc4random but don't have
- arc4random_stir (right now this is only OpenBSD -current).
-
-commit 3420a50169b52cc8d2775d51316f9f866c73398f
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Nov 8 16:48:13 2013 +1100
-
- - (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
- [contrib/suse/openssh.spec] Update version numbers following release.
-
-commit 3ac4a234df842fd8c94d9cb0ad198e1fe84b895b
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Nov 8 12:39:49 2013 +1100
-
- - djm@cvs.openbsd.org 2013/11/08 01:38:11
- [version.h]
- openssh-6.4
-
-commit 6c81fee693038de7d4a5559043350391db2a2761
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Nov 8 12:19:55 2013 +1100
-
- - djm@cvs.openbsd.org 2013/11/08 00:39:15
- [auth-options.c auth2-chall.c authfd.c channels.c cipher-3des1.c]
- [clientloop.c gss-genr.c monitor_mm.c packet.c schnorr.c umac.c]
- [sftp-client.c sftp-glob.c]
- use calloc for all structure allocations; from markus@
-
-commit 690d989008e18af3603a5e03f1276c9bad090370
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Nov 8 12:16:49 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/11/07 11:58:27
- [cipher.c cipher.h kex.c kex.h mac.c mac.h servconf.c ssh.c]
- Output the effective values of Ciphers, MACs and KexAlgorithms when
- the default has not been overridden. ok markus@
-
-commit 08998c5fb9c7c1d248caa73b76e02ca0482e6d85
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Nov 8 12:11:46 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/11/08 01:06:14
- [regress/rekey.sh]
- Rekey less frequently during tests to speed them up
-
-commit 4bf7e50e533aa956366df7402c132f202e841a48
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Nov 7 22:33:48 2013 +1100
-
- - (dtucker) [Makefile.in configure.ac] Remove TEST_SSH_SHA256 environment
- variable. It's no longer used now that we get the supported MACs from
- ssh -Q.
-
-commit 6e9d6f411288374d1dee4b7debbfa90bc7e73035
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Nov 7 15:32:37 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/11/07 04:26:56
- [regress/kextype.sh]
- trailing space
-
-commit 74cbc22529f3e5de756e1b7677b7624efb28f62c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Nov 7 15:26:12 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/11/07 03:55:41
- [regress/kextype.sh]
- Use ssh -Q to get kex types instead of a static list.
-
-commit a955041c930e63405159ff7d25ef14272f36eab3
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Nov 7 15:21:19 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/11/07 02:48:38
- [regress/integrity.sh regress/cipher-speed.sh regress/try-ciphers.sh]
- Use ssh -Q instead of hardcoding lists of ciphers or MACs.
-
-commit 06595d639577577bc15d359e037a31eb83563269
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Nov 7 15:08:02 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/11/07 01:12:51
- [regress/rekey.sh]
- Factor out the data transfer rekey tests
-
-commit 651dc8b2592202dac6b16ee3b82ce5b331be7da3
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Nov 7 15:04:44 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/11/07 00:12:05
- [regress/rekey.sh]
- Test rekeying for every Cipher, MAC and KEX, plus test every KEX with
- the GCM ciphers.
-
-commit 234557762ba1096a867ca6ebdec07efebddb5153
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Nov 7 15:00:51 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/11/04 12:27:42
- [regress/rekey.sh]
- Test rekeying with all KexAlgorithms.
-
-commit bbfb9b0f386aab0c3e19d11f136199ef1b9ad0ef
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Nov 7 14:56:43 2013 +1100
-
- - markus@cvs.openbsd.org 2013/11/02 22:39:53
- [regress/kextype.sh]
- add curve25519-sha256@libssh.org
-
-commit aa19548a98c0f89283ebd7354abd746ca6bc4fdf
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Nov 7 14:50:09 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/09 23:44:14
- [regress/Makefile] (ID sync only)
- regression test for sftp request white/blacklisting and readonly mode.
-
-commit c8908aabff252f5da772d4e679479c2b7d18cac1
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 7 13:38:35 2013 +1100
-
- - djm@cvs.openbsd.org 2013/11/06 23:05:59
- [ssh-pkcs11.c]
- from portable: s/true/true_val/ to avoid name collisions on dump platforms
- RCSID sync only
-
-commit 49c145c5e89b9d7d48e84328d6347d5ad640b567
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 7 13:35:39 2013 +1100
-
- - markus@cvs.openbsd.org 2013/11/06 16:52:11
- [monitor_wrap.c]
- fix rekeying for AES-GCM modes; ok deraadt
-
-commit 67a8800f290b39fd60e379988c700656ae3f2539
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 7 13:32:51 2013 +1100
-
- - markus@cvs.openbsd.org 2013/11/04 11:51:16
- [monitor.c]
- fix rekeying for KEX_C25519_SHA256; noted by dtucker@
- RCSID sync only; I thought this was a merge botch and fixed it already
-
-commit df8b030b15fcec7baf38ec7944f309f9ca8cc9a7
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 7 13:28:16 2013 +1100
-
- - (djm) [configure.ac defines.h] Skip arc4random_stir() calls on platforms
- that lack it but have arc4random_uniform()
-
-commit a6fd1d3c38a562709374a70fa76423859160aa90
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 7 12:03:26 2013 +1100
-
- - (djm) [regress/modpipe.c regress/rekey.sh] Never intended to commit these
-
-commit c98319750b0bbdd0d1794420ec97d65dd9244613
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 7 12:00:23 2013 +1100
-
- - (djm) [Makefile.in monitor.c] Missed chunks of curve25519 KEX diff
-
-commit 61c5c2319e84a58210810d39b062c8b8e3321160
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Nov 7 11:34:14 2013 +1100
-
- - (djm) [ssh-pkcs11.c] Bring back "non-constant initialiser" fix (rev 1.5)
- that got lost in recent merge.
-
-commit 094003f5454a9f5a607674b2739824a7e91835f4
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Nov 4 22:59:27 2013 +1100
-
- - (djm) [kexc25519.c kexc25519c.c kexc25519s.c] Import missed files from
- KEX/curve25519 change
-
-commit ca67a7eaf8766499ba67801d0be8cdaa550b9a50
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Nov 4 09:05:17 2013 +1100
-
- - djm@cvs.openbsd.org 2013/11/03 10:37:19
- [roaming_common.c]
- fix a couple of function definitions foo() -> foo(void)
- (-Wold-style-definition)
-
-commit 0bd8f1519d51af8d4229be81e8f2f4903a1d440b
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Nov 4 08:55:43 2013 +1100
-
- - markus@cvs.openbsd.org 2013/11/02 22:39:19
- [ssh_config.5 sshd_config.5]
- the default kex is now curve25519-sha256@libssh.org
-
-commit 4c3ba0767fbe4a8a2a748df4035aaf86651f6b30
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Nov 4 08:40:13 2013 +1100
-
- - markus@cvs.openbsd.org 2013/11/02 22:34:01
- [auth-options.c]
- no need to include monitor_wrap.h and ssh-gss.h
-
-commit 660621b2106b987b874c2f120218bec249d0f6ba
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Nov 4 08:37:51 2013 +1100
-
- - markus@cvs.openbsd.org 2013/11/02 22:24:24
- [kexdhs.c kexecdhs.c]
- no need to include ssh-gss.h
-
-commit abdca986decfbbc008c895195b85e879ed460ada
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Nov 4 08:30:05 2013 +1100
-
- - markus@cvs.openbsd.org 2013/11/02 22:10:15
- [kexdhs.c kexecdhs.c]
- no need to include monitor_wrap.h
-
-commit 1e1242604eb0fd510fe93f81245c529237ffc513
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Nov 4 08:26:52 2013 +1100
-
- - markus@cvs.openbsd.org 2013/11/02 21:59:15
- [kex.c kex.h myproposal.h ssh-keyscan.c sshconnect2.c sshd.c]
- use curve25519 for default key exchange (curve25519-sha256@libssh.org);
- initial patch from Aris Adamantiadis; ok djm@
-
-commit d2252c79191d069372ed6effce7c7a2de93448cd
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Nov 4 07:41:48 2013 +1100
-
- - markus@cvs.openbsd.org 2013/11/02 20:03:54
- [ssh-pkcs11.c]
- support pkcs#11 tokes that only provide x509 zerts instead of raw pubkeys;
- fixes bz#1908; based on patch from Laurent Barbe; ok djm
-
-commit 007e3b357e880caa974d5adf9669298ba0751c78
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Nov 3 18:43:55 2013 +1100
-
- - (dtucker) [configure.ac defines.h] Add typedefs for intmax_t and uintmax_t
- for platforms that don't have them.
-
-commit 710f3747352fb93a63e5b69b12379da37f5b3fa9
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Nov 3 17:20:34 2013 +1100
-
- - (dtucker) [openbsd-compat/setproctitle.c] Handle error case form the 2nd
- vsnprintf. From eric at openbsd via chl@.
-
-commit d52770452308e5c2e99f4da6edaaa77ef078b610
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Nov 3 16:30:46 2013 +1100
-
- - (dtucker) [openbsd-compat/bsd-misc.c] Include time.h for nanosleep.
- From OpenSMTPD where it prevents "implicit declaration" warnings (it's
- a no-op in OpenSSH). From chl at openbsd.
-
-commit 63857c9340d3482746a5622ffdacc756751f6448
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 30 22:31:06 2013 +1100
-
- - jmc@cvs.openbsd.org 2013/10/29 18:49:32
- [sshd_config.5]
- pty(4), not pty(7);
-
-commit 5ff30c6b68adeee767dd29bf2369763c6a13c0b3
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 30 22:21:50 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/29 09:48:02
- [servconf.c servconf.h session.c sshd_config sshd_config.5]
- shd_config PermitTTY to disallow TTY allocation, mirroring the
- longstanding no-pty authorized_keys option;
- bz#2070, patch from Teran McKinney; ok markus@
-
-commit 4a3a9d4bbf8048473f5cc202cd8db7164d5e6b8d
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 30 22:19:47 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/29 09:42:11
- [key.c key.h]
- fix potential stack exhaustion caused by nested certificates;
- report by Mateusz Kocielski; ok dtucker@ markus@
-
-commit 28631ceaa7acd9bc500f924614431542893c6a21
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Oct 26 10:07:56 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/25 23:04:51
- [ssh.c]
- fix crash when using ProxyCommand caused by previous commit - was calling
- freeaddrinfo(NULL); spotted by sthen@ and Tim Ruehsen, patch by sthen@
-
-commit 26506ad29350c5681815745cc90b3952a84cf118
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Oct 26 10:05:46 2013 +1100
-
- - (djm) [ssh-keygen.c ssh-keysign.c sshconnect1.c sshd.c] Remove
- unnecessary arc4random_stir() calls. The only ones left are to ensure
- that the PRNG gets a different state after fork() for platforms that
- have broken the API.
-
-commit bd43e8872325e9bbb3319c89da593614709f317c
-Author: Tim Rice <tim@multitalents.net>
-Date: Thu Oct 24 12:22:49 2013 -0700
-
- - (tim) [regress/sftp-perm.sh] We need a shell that understands "! somecmd"
-
-commit a90c0338083ee0e4064c4bdf61f497293a699be0
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 24 21:03:17 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/24 08:19:36
- [ssh.c]
- fix bug introduced in hostname canonicalisation commit: don't try to
- resolve hostnames when a ProxyCommand is set unless the user has forced
- canonicalisation; spotted by Iain Morgan
-
-commit cf31f3863425453ffcda540fbefa9df80088c8d1
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 24 21:02:56 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/10/24 00:51:48
- [readconf.c servconf.c ssh_config.5 sshd_config.5]
- Disallow empty Match statements and add "Match all" which matches
- everything. ok djm, man page help jmc@
-
-commit 4bedd4032a09ce87322ae5ea80f193f109e5c607
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 24 21:02:26 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/10/24 00:49:49
- [moduli.c]
- Periodically print progress and, if possible, expected time to completion
- when screening moduli for DH groups. ok deraadt djm
-
-commit 5ecb41629860687b145be63b8877fabb6bae5eda
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 24 21:02:02 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/23 23:35:32
- [sshd.c]
- include local address and port in "Connection from ..." message (only
- shown at loglevel>=verbose)
-
-commit 03bf2e61ad6ac59a362a1f11b105586cb755c147
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 24 21:01:26 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/10/23 05:40:58
- [servconf.c]
- fix comment
-
-commit 8f1873191478847773906af961c8984d02a49dd6
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 24 10:53:02 2013 +1100
-
- - (djm) [auth-krb5.c] bz#2032 - use local username in krb5_kuserok check
- rather than full client name which may be of form user@REALM;
- patch from Miguel Sanders; ok dtucker@
-
-commit 5b01b0dcb417eb615df77e7ce1b59319bf04342c
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 23 16:31:31 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/23 04:16:22
- [ssh-keygen.c]
- Make code match documentation: relative-specified certificate expiry time
- should be relative to current time and not the validity start time.
- Reported by Petr Lautrbach; ok deraadt@
-
-commit eff5cada589f25793dbe63a76aba9da39837a148
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 23 16:31:10 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/23 03:05:19
- [readconf.c ssh.c]
- comment
-
-commit 084bcd24e9fe874020e4df4e073e7408e1b17fb7
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 23 16:30:51 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/23 03:03:07
- [readconf.c]
- Hostname may have %h sequences that should be expanded prior to Match
- evaluation; spotted by Iain Morgan
-
-commit 8e5a67f46916def40b2758bb7755350dd2eee843
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 23 16:30:25 2013 +1100
-
- - jmc@cvs.openbsd.org 2013/10/20 18:00:13
- [ssh_config.5]
- tweak the "exec" description, as worded by djm;
-
-commit c0049bd0bca02890cd792babc594771c563f91f2
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 23 16:29:59 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/20 09:51:26
- [scp.1 sftp.1]
- add canonicalisation options to -o lists
-
-commit 8a04be795fc28514a09e55a54b2e67968f2e1b3a
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 23 16:29:40 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/20 06:19:28
- [readconf.c ssh_config.5]
- rename "command" subclause of the recently-added "Match" keyword to
- "exec"; it's shorter, clearer in intent and we might want to add the
- ability to match against the command being executed at the remote end in
- the future.
-
-commit 5c86ebdf83b636b6741db4b03569ef4a53b89a58
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 23 16:29:12 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/20 04:39:28
- [ssh_config.5]
- document % expansions performed by "Match command ..."
-
-commit 4502f88774edc56194707167443f94026d3c7cfa
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Oct 18 10:17:36 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/17 22:08:04
- [sshd.c]
- include remote port in bad banner message; bz#2162
-
-commit 1edcbf65ebd2febeaf10a836468f35e519eed7ca
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Oct 18 10:17:17 2013 +1100
-
- - jmc@cvs.openbsd.org 2013/10/17 07:35:48
- [sftp.1 sftp.c]
- tweak previous;
-
-commit a176e1823013dd8533a20235b3a5131f0626f46b
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Oct 18 09:05:41 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/09 23:44:14
- [regress/Makefile regress/sftp-perm.sh]
- regression test for sftp request white/blacklisting and readonly mode.
-
-commit e3ea09494dcfe7ba76536e95765c8328ecfc18fb
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 17 11:57:23 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/17 00:46:49
- [ssh.c]
- rearrange check to reduce diff against -portable
- (Id sync only)
-
-commit f29238e67471a7f1088a99c3c3dbafce76b790cf
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 17 11:48:52 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/17 00:30:13
- [PROTOCOL sftp-client.c sftp-client.h sftp-server.c sftp.1 sftp.c]
- fsync@openssh.com protocol extension for sftp-server
- client support to allow calling fsync() faster successful transfer
- patch mostly by imorgan AT nas.nasa.gov; bz#1798
- "fine" markus@ "grumble OK" deraadt@ "doesn't sound bad to me" millert@
-
-commit 51682faa599550a69d8120e5e2bdbdc0625ef4be
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 17 11:48:31 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/16 22:58:01
- [ssh.c ssh_config.5]
- one I missed in previous: s/isation/ization/
-
-commit 3850559be93f1a442ae9ed370e8c389889dd5f72
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 17 11:48:13 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/16 22:49:39
- [readconf.c readconf.h ssh.1 ssh.c ssh_config.5]
- s/canonicalise/canonicalize/ for consistency with existing spelling,
- e.g. authorized_keys; pointed out by naddy@
-
-commit 607af3434b75acc7199a5d99d5a9c11068c01f27
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 17 11:47:51 2013 +1100
-
- - jmc@cvs.openbsd.org 2013/10/16 06:42:25
- [ssh_config.5]
- tweak previous;
-
-commit 0faf747e2f77f0f7083bcd59cbed30c4b5448444
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 17 11:47:23 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/16 02:31:47
- [readconf.c readconf.h roaming_client.c ssh.1 ssh.c ssh_config.5]
- [sshconnect.c sshconnect.h]
- Implement client-side hostname canonicalisation to allow an explicit
- search path of domain suffixes to use to convert unqualified host names
- to fully-qualified ones for host key matching.
- This is particularly useful for host certificates, which would otherwise
- need to list unqualified names alongside fully-qualified ones (and this
- causes a number of problems).
- "looks fine" markus@
-
-commit d77b81f856e078714ec6b0f86f61c20249b7ead4
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 17 11:39:00 2013 +1100
-
- - jmc@cvs.openbsd.org 2013/10/15 14:10:25
- [ssh.1 ssh_config.5]
- tweak previous;
-
-commit dcd39f29ce3308dc74a0ff27a9056205a932ce05
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 17 11:31:40 2013 +1100
-
- - [ssh.c] g/c unused variable.
-
-commit 5359a628ce3763408da25d83271a8eddec597a0c
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 15 12:20:37 2013 +1100
-
- - [ssh.c] g/c unused variable.
-
-commit 386feab0c4736b054585ee8ee372865d5cde8d69
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 15 12:14:49 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/14 23:31:01
- [ssh.c]
- whitespace at EOL; pointed out by markus@
-
-commit e9fc72edd6c313b670558cd5219601c38a949b67
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 15 12:14:12 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/14 23:28:23
- [canohost.c misc.c misc.h readconf.c sftp-server.c ssh.c]
- refactor client config code a little:
- add multistate option partsing to readconf.c, similar to servconf.c's
- existing code.
- move checking of options that accept "none" as an argument to readconf.c
- add a lowercase() function and use it instead of explicit tolower() in
- loops
- part of a larger diff that was ok markus@
-
-commit 194fd904d8597a274b93e075b2047afdf5a175d4
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 15 12:13:05 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/14 22:22:05
- [readconf.c readconf.h ssh-keysign.c ssh.c ssh_config.5]
- add a "Match" keyword to ssh_config that allows matching on hostname,
- user and result of arbitrary commands. "nice work" markus@
-
-commit 71df752de2a04f423b1cd18d961a79f4fbccbcee
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 15 12:12:02 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/14 21:20:52
- [session.c session.h]
- Add logging of session starts in a useful format; ok markus@ feedback and
- ok dtucker@
-
-commit 6efab27109b82820e8d32a5d811adb7bfc354f65
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 15 12:07:05 2013 +1100
-
- - jmc@cvs.openbsd.org 2013/10/14 14:18:56
- [sftp-server.8 sftp-server.c]
- tweak previous;
- ok djm
-
-commit 61c7de8a94156f6d7e9718ded9be8c65bb902b66
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 15 12:06:45 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/11 02:53:45
- [sftp-client.h]
- obsolete comment
-
-commit 2f93d0556e4892208c9b072624caa8cc5ddd839d
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 15 12:06:27 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/11 02:52:23
- [sftp-client.c]
- missed one arg reorder
-
-commit bda5c8445713ae592d969a5105ed1a65da22bc96
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 15 12:05:58 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/11 02:45:36
- [sftp-client.c]
- rename flag arguments to be more clear and consistent.
- reorder some internal function arguments to make adding additional flags
- easier.
- no functional change
-
-commit 61ee4d68ca0fcc793a826fc7ec70f3b8ffd12ab6
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 15 11:56:47 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/10 01:43:03
- [sshd.c]
- bz#2139: fix re-exec fallback by ensuring that startup_pipe is correctly
- updated; ok dtucker@
-
-commit 73600e51af9ee734a19767e0c084bbbc5eb5b8da
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 15 11:56:25 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/10 00:53:25
- [sftp-server.c]
- add -Q, -P and -p to usage() before jmc@ catches me
-
-commit 6eaeebf27d92f39a38c772aa3f20c2250af2dd29
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 15 11:55:57 2013 +1100
-
- - djm@cvs.openbsd.org 2013/10/09 23:42:17
- [sftp-server.8 sftp-server.c]
- Add ability to whitelist and/or blacklist sftp protocol requests by name.
- Refactor dispatch loop and consolidate read-only mode checks.
- Make global variables static, since sftp-server is linked into sshd(8).
- ok dtucker@
-
-commit df62d71e64d29d1054e7a53d1a801075ef70335f
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Oct 10 10:32:39 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/10/08 11:42:13
- [dh.c dh.h]
- Increase the size of the Diffie-Hellman groups requested for a each
- symmetric key size. New values from NIST Special Publication 800-57 with
- the upper limit specified by RFC4419. Pointed out by Peter Backes, ok
- djm@.
-
-commit e6e52f8c5dc89a6767702e65bb595aaf7bc8991c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Oct 10 10:28:07 2013 +1100
-
- - djm@cvs.openbsd.org 2013/09/19 01:26:29
- [sshconnect.c]
- bz#1211: make BindAddress work with UsePrivilegedPort=yes; patch from
- swp AT swp.pp.ru; ok dtucker@
-
-commit 71152bc9911bc34a98810b2398dac20df3fe8de3
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Oct 10 10:27:21 2013 +1100
-
- - djm@cvs.openbsd.org 2013/09/19 01:24:46
- [channels.c]
- bz#1297 - tell the client (via packet_send_debug) when their preferred
- listen address has been overridden by the server's GatewayPorts;
- ok dtucker@
-
-commit b59aaf3c4f3f449a4b86d8528668bd979be9aa5f
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Oct 10 10:26:21 2013 +1100
-
- - djm@cvs.openbsd.org 2013/09/19 00:49:12
- [sftp-client.c]
- fix swapped pflag and printflag in sftp upload_dir; from Iain Morgan
-
-commit 5d80e4522d6238bdefe9d0c634f0e6d35a241e41
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Oct 10 10:25:09 2013 +1100
-
- - djm@cvs.openbsd.org 2013/09/19 00:24:52
- [progressmeter.c]
- store the initial file offset so the progress meter doesn't freak out
- when resuming sftp transfers. bz#2137; patch from Iain Morgan; ok dtucker@
-
-commit ad92df7e5ed26fea85adfb3f95352d6cd8e86344
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Oct 10 10:24:11 2013 +1100
-
- - sthen@cvs.openbsd.org 2013/09/16 11:35:43
- [ssh_config]
- Remove gssapi config parts from ssh_config, as was already done for
- sshd_config. Req by/ok ajacoutot@
- ID SYNC ONLY for portable; kerberos/gssapi is still pretty popular
-
-commit 720711960b130d36dfdd3d50eb25ef482bdd000e
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 9 10:44:47 2013 +1100
-
- - (djm) [openbsd-compat/Makefile.in openbsd-compat/arc4random.c]
- [openbsd-compat/bsd-arc4random.c] Replace old RC4-based arc4random
- implementation with recent OpenBSD's ChaCha-based PRNG. ok dtucker@,
- tested tim@
-
-commit 9159310087a218e28940a592896808b8eb76a039
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 9 10:42:32 2013 +1100
-
- - (djm) [openbsd-compat/arc4random.c openbsd-compat/chacha_private.h] Pull
- in OpenBSD implementation of arc4random, shortly to replace the existing
- bsd-arc4random.c
-
-commit 67f1d557a68d6fa8966a327d7b6dee3408cf0e72
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 9 09:33:08 2013 +1100
-
- correct incorrect years in datestamps; from des
-
-commit f2bf36c3eb4d969f85ec8aa342e9aecb61cc8bb1
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Sep 22 19:02:40 2013 +1000
-
- - (dtucker) [platform.c platform.h sshd.c] bz#2156: restore Linux oom_adj
- setting when handling SIGHUP to maintain behaviour over retart. Patch
- from Matthew Ife.
-
-commit e90a06ae570fd259a2f5ced873c7f17390f535a5
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Sep 18 15:09:38 2013 +1000
-
- - (dtucker) [sshd_config] Trailing whitespace; from jstjohn at purdue edu.
-
-commit 13840e0103946982cee2a05c40697be7e57dca41
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Sep 14 09:49:43 2013 +1000
-
- - djm@cvs.openbsd.org 2013/09/13 06:54:34
- [channels.c]
- avoid unaligned access in code that reused a buffer to send a
- struct in_addr in a reply; simpler just use use buffer_put_int();
- from portable; spotted by and ok dtucker@
-
-commit 70182522a47d283513a010338cd028cb80dac2ab
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Sep 14 09:49:19 2013 +1000
-
- - djm@cvs.openbsd.org 2013/09/12 01:41:12
- [clientloop.c]
- fix connection crash when sending break (~B) on ControlPersist'd session;
- ok dtucker@
-
-commit ff9d6c2a4171ee32e8fe28fc3b86eb33bd5c845b
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Sep 14 09:48:55 2013 +1000
-
- - sthen@cvs.openbsd.org 2013/09/07 13:53:11
- [sshd_config]
- Remove commented-out kerberos/gssapi config options from sample config,
- kerberos support is currently not enabled in ssh in OpenBSD. Discussed with
- various people; ok deraadt@
- ID SYNC ONLY for portable; kerberos/gssapi is still pretty popular
-
-commit 8bab5e7b5ff6721d926b5ebf05a3a24489889c58
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Sep 14 09:47:00 2013 +1000
-
- - deraadt@cvs.openbsd.org 2013/09/02 22:00:34
- [ssh-keygen.c sshconnect1.c sshd.c]
- All the instances of arc4random_stir() are bogus, since arc4random()
- does this itself, inside itself, and has for a very long time.. Actually,
- this was probably reducing the entropy available.
- ok djm
- ID SYNC ONLY for portable; we don't trust other arc4random implementations
- to do this right.
-
-commit 61353b3208d548fab863e0e0ac5d2400ee5bb340
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Sep 14 09:45:32 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/31 00:13:54
- [sftp.c]
- make ^w match ksh behaviour (delete previous word instead of entire line)
-
-commit 660854859cad31d234edb9353fb7ca2780df8128
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Sep 14 09:45:03 2013 +1000
-
- - mikeb@cvs.openbsd.org 2013/08/28 12:34:27
- [ssh-keygen.c]
- improve batch processing a bit by making use of the quite flag a bit
- more often and exit with a non zero code if asked to find a hostname
- in a known_hosts file and it wasn't there;
- originally from reyk@, ok djm
-
-commit 045bda5cb8acf0eb9d71c275ee1247e3154fc9e5
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Sep 14 09:44:37 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/22 19:02:21
- [sshd.c]
- Stir PRNG after post-accept fork. The child gets a different PRNG state
- anyway via rexec and explicit privsep reseeds, but it's good to be sure.
- ok markus@
-
-commit ed4af412da60a084891b20412433a27966613fb8
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Sep 14 09:40:51 2013 +1000
-
- add marker for 6.3p1 release at the point of the last included change
-
-commit 43968a8e66a0aa1afefb11665bf96f86b113f5d9
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 28 14:00:54 2013 +1000
-
- - (djm) [openbsd-compat/bsd-snprintf.c] #ifdef noytet for intmax_t bits
- until we have configure support.
-
-commit 04be8b9e53f8388c94b531ebc5d1bd6e10e930d1
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 28 12:49:43 2013 +1000
-
- - (djm) [openbsd-compat/bsd-snprintf.c] teach our local snprintf code the
- 'j' (intmax_t/uintmax_t) and 'z' (size_t/ssize_t) conversions in case we
- start to use them in the future.
-
-commit f2f6c315a920a256937e1b6a3702757f3195a592
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:44:58 2013 +1000
-
- - jmc@cvs.openbsd.org 2013/08/20 06:56:07
- [ssh.1 ssh_config.5]
- some proxyusefdpass tweaks;
-
-commit 1262b6638f7d01ab110fd373dd90d915c882fe1a
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:44:24 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/20 00:11:38
- [readconf.c readconf.h ssh_config.5 sshconnect.c]
- Add a ssh_config ProxyUseFDPass option that supports the use of
- ProxyCommands that establish a connection and then pass a connected
- file descriptor back to ssh(1). This allows the ProxyCommand to exit
- rather than have to shuffle data back and forth and enables ssh to use
- getpeername, etc. to obtain address information just like it does with
- regular directly-connected sockets. ok markus@
-
-commit b7727df37efde4dbe4f5a33b19cbf42022aabf66
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:43:49 2013 +1000
-
- - jmc@cvs.openbsd.org 2013/08/14 08:39:27
- [scp.1 ssh.1]
- some Bx/Ox conversion;
- From: Jan Stary
-
-commit d5d9d7b1fdacf0551de4c747728bd159be40590a
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:43:27 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/13 18:33:08
- [ssh-keygen.c]
- another of the same typo
-
-commit d234afb0b3a8de1be78cbeafed5fc86912594c3c
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:42:58 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/13 18:32:08
- [ssh-keygen.c]
- typo in error message; from Stephan Rickauer
-
-commit e0ee727b8281a7c2ae20630ce83f6b200b404059
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:42:35 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/09 03:56:42
- [sftp.c]
- enable ctrl-left-arrow and ctrl-right-arrow to move forward/back a word;
- matching ksh's relatively recent change.
-
-commit fec029f1dc2c338f3fae3fa82aabc988dc07868c
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:42:12 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/09 03:39:13
- [sftp-client.c]
- two problems found by a to-be-committed regress test: 1) msg_id was not
- being initialised so was starting at a random value from the heap
- (harmless, but confusing). 2) some error conditions were not being
- propagated back to the caller
-
-commit 036d30743fc914089f9849ca52d615891d47e616
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:41:46 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/09 03:37:25
- [sftp.c]
- do getopt parsing for all sftp commands (with an empty optstring for
- commands without arguments) to ensure consistent behaviour
-
-commit c7dba12bf95eb1d69711881a153cc286c1987663
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:41:15 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/08 05:04:03
- [sftp-client.c sftp-client.h sftp.c]
- add a "-l" flag for the rename command to force it to use the silly
- standard SSH_FXP_RENAME command instead of the POSIX-rename- like
- posix-rename@openssh.com extension.
-
- intended for use in regress tests, so no documentation.
-
-commit 034f27a0c09e69fe3589045b41f03f6e345b63f5
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:40:44 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/08 04:52:04
- [sftp.c]
- fix two year old regression: symlinking a file would incorrectly
- canonicalise the target path. bz#2129 report from delphij AT freebsd.org
-
-commit c6895c5c67492144dd28589e5788f783be9152ed
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:40:21 2013 +1000
-
- - jmc@cvs.openbsd.org 2013/08/07 06:24:51
- [sftp.1 sftp.c]
- sort -a;
-
-commit a6d6c1f38ac9b4a5e1bd4df889e1020a8370ed55
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:40:01 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/06 23:06:01
- [servconf.c]
- add cast to avoid format warning; from portable
-
-commit eec840673bce3f69ad269672fba7ed8ff05f154f
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:39:39 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/06 23:05:01
- [sftp.1]
- document top-level -a option (the -a option to 'get' was already
- documented)
-
-commit 02e878070d0eddad4e11f2c82644b275418eb112
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 21 02:38:51 2013 +1000
-
- - djm@cvs.openbsd.org 2013/08/06 23:03:49
- [sftp.c]
- fix some whitespace at EOL
- make list of commands an enum rather than a long list of defines
- add -a to usage()
-
-commit acd2060f750c16d48b87b92a10b5a833227baf9d
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Aug 8 17:02:12 2013 +1000
-
- - (dtucker) [regress/Makefile regress/test-exec.sh] Roll back the -nt
- removal. The "make clean" removes modpipe which is built by the top-level
- directory before running the tests. Spotted by tim@
-
-commit 9542de4547beebf707f3640082d471f1a85534c9
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Aug 8 12:50:06 2013 +1000
-
- - (dtucker) [misc.c] Remove define added for fallback testing that was
- mistakenly included in the previous commit.
-
-commit 94396b7f06f512a0acb230640d7f703fb802a9ee
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Aug 8 11:52:37 2013 +1000
-
- - (dtucker) [misc.c] Fall back to time(2) at runtime if clock_gettime(
- CLOCK_MONOTONIC...) fails. Some older versions of RHEL have the
- CLOCK_MONOTONIC define but don't actually support it. Found and tested
- by Kevin Brott, ok djm.
-
-commit a5a3cbfa0fb8ef011d3e7b38910a13f6ebbb8818
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Aug 8 10:58:49 2013 +1000
-
- - (dtucker) [regress/Makefile regress/test-exec.sh] Don't try to use test -nt
- since some platforms (eg really old FreeBSD) don't have it. Instead,
- run "make clean" before a complete regress run. ok djm.
-
-commit f3ab2c5f9cf4aed44971eded3ac9eeb1344b2be5
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Aug 4 21:48:41 2013 +1000
-
- - (dtucker) [auth-krb5.c configure.ac openbsd-compat/bsd-misc.h] Add support
- for building with older Heimdal versions. ok djm.
-
-commit ab3575c055adfbce70fa7405345cf0f80b07c827
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Aug 1 14:34:16 2013 +1000
-
- - (djm) [sshlogin.h] Fix prototype merge botch from 2006; bz#2134
-
-commit c192a4c4f6da907dc0e67a3ca61d806f9a92c931
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Aug 1 14:29:20 2013 +1000
-
- - (djm) [channels.c channels.h] bz#2135: On Solaris, isatty() on a non-
- blocking connecting socket will clear any stored errno that might
- otherwise have been retrievable via getsockopt(). A hack to limit writes
- to TTYs on AIX was triggering this. Since only AIX needs the hack, wrap
- it in an #ifdef. Diagnosis and patch from Ivo Raisr.
-
-commit 81f7cf1ec5bc2fd202eda05abc2e5361c54633c5
-Author: Tim Rice <tim@multitalents.net>
-Date: Thu Jul 25 18:41:40 2013 -0700
-
- more correct comment for last commit
-
-commit 0553ad76ffdff35fb31b9e6df935a71a1cc6daa2
-Author: Tim Rice <tim@multitalents.net>
-Date: Thu Jul 25 16:03:16 2013 -0700
-
- - (tim) [regress/forwarding.sh] Fix for building outside read only source tree.
-
-commit ed899eb597a8901ff7322cba809660515ec0d601
-Author: Tim Rice <tim@multitalents.net>
-Date: Thu Jul 25 15:40:00 2013 -0700
-
- - (tim) [sftp-client.c] Use of a gcc extension trips up native compilers on
- Solaris and UnixWare. Feedback and OK djm@
-
-commit e9e936d33b4b1d77ffbaace9438cb2f1469c1dc7
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 25 12:34:00 2013 +1000
-
- - (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
- [contrib/suse/openssh.spec] Update version numbers
-
-commit d1e26cf391de31128b4edde118bff5fed98a90ea
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 25 12:11:18 2013 +1000
-
- - djm@cvs.openbsd.org 2013/06/21 02:26:26
- [regress/sftp-cmds.sh regress/test-exec.sh]
- unbreak sftp-cmds for renamed test data (s/ls/data/)
-
-commit 78d47b7c5b182e44552913de2b4b7e0363c8e3cc
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 25 12:08:46 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/10 21:56:43
- [regress/forwarding.sh]
- Add test for forward config parsing
-
-commit fea440639e04cea9f2605375a41d654390369402
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 25 12:08:07 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/30 20:12:32
- [regress/test-exec.sh]
- use ssh and sshd as testdata since it needs to be >256k for the rekey test
-
-commit 53435b2d8773a5d7c78359e9f7bf9df2d93b9ef5
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 25 11:57:15 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/25 00:57:37
- [version.h]
- openssh-6.3 for release
-
-commit 0d032419ee6e1968fc1cb187af63bf3b77b506ea
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 25 11:56:52 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/25 00:56:52
- [sftp-client.c sftp-client.h sftp.1 sftp.c]
- sftp support for resuming partial downloads; patch mostly by Loganaden
- Velvindron/AfriNIC with some tweaks by me; feedback and ok dtucker@
-
-commit 98e27dcf581647b5bbe9780e8f59685d942d8ea3
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 25 11:55:52 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/25 00:29:10
- [ssh.c]
- daemonise backgrounded (ControlPersist'ed) multiplexing master to ensure
- it is fully detached from its controlling terminal. based on debugging
-
-commit 94c9cd34d1590ea1d4bf76919a15b5688fa90ed1
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 25 11:55:39 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/22 12:20:02
- [umac.h]
- oops, forgot to commit corresponding header change;
- spotted by jsg and jasper
-
-commit c331dbd22297ab9bf351abee659893d139c9f28a
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 25 11:55:20 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/22 05:00:17
- [umac.c]
- make MAC key, data to be hashed and nonce for final hash const;
- checked with -Wcast-qual
-
-commit c8669a8cd24952b3f16a44eac63d2b6ce8a6343a
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 25 11:52:48 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/20 22:20:42
- [krl.c]
- fix verification error in (as-yet usused) KRL signature checking path
-
-commit 63ddc899d28cf60045b560891894b9fbf6f822e9
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Jul 20 13:35:45 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/20 01:55:13
- [auth-krb5.c gss-serv-krb5.c gss-serv.c]
- fix kerberos/GSSAPI deprecation warnings and linking; "looks okay" millert@
-
-commit 1f0e86f23fcebb026371c0888402a981df2a61c4
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Jul 20 13:22:49 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/20 01:50:20
- [ssh-agent.c]
- call cleanup_handler on SIGINT when in debug mode to ensure sockets
- are cleaned up on manual exit; bz#2120
-
-commit 3009d3cbb89316b1294fb5cedb54770b5d114d04
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Jul 20 13:22:31 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/20 01:44:37
- [ssh-keygen.c ssh.c]
- More useful error message on missing current user in /etc/passwd
-
-commit 32ecfa0f7920db31471ca8c1f4adc20ae38ed9d6
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Jul 20 13:22:13 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/20 01:43:46
- [umac.c]
- use a union to ensure correct alignment; ok deraadt
-
-commit 85b45e09188e7a7fc8f0a900a4c6a0f04a5720a7
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Jul 20 13:21:52 2013 +1000
-
- - markus@cvs.openbsd.org 2013/07/19 07:37:48
- [auth.h kex.h kexdhs.c kexecdhs.c kexgexs.c monitor.c servconf.c]
- [servconf.h session.c sshd.c sshd_config.5]
- add ssh-agent(1) support to sshd(8); allows encrypted hostkeys,
- or hostkeys on smartcards; most of the work by Zev Weiss; bz #1974
- ok djm@
-
-commit d93340cbb6bc0fc0dbd4427e0cec6d994a494dd9
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:14:34 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/18 01:12:26
- [ssh.1]
- be more exact wrt perms for ~/.ssh/config; bz#2078
-
-commit bf836e535dc3a8050c1756423539bac127ee5098
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:14:13 2013 +1000
-
- - schwarze@cvs.openbsd.org 2013/07/16 00:07:52
- [scp.1 sftp-server.8 ssh-keyscan.1 ssh-keysign.8 ssh-pkcs11-helper.8]
- use .Mt for email addresses; from Jan Stary <hans at stare dot cz>; ok jmc@
-
-commit 649fe025a409d0ce88c60a068f3f211193c35873
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:13:55 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/12 05:48:55
- [ssh.c]
- set TCP nodelay for connections started with -N; bz#2124 ok dtucker@
-
-commit 5bb8833e809d827496dffca0dc2c223052c93931
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:13:37 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/12 05:42:03
- [ssh-keygen.c]
- do_print_resource_record() can never be called with a NULL filename, so
- don't attempt (and bungle) asking for one if it has not been specified
- bz#2127 ok dtucker@
-
-commit 7313fc9222785d0c54a7ffcaf2067f4db02c8d72
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:13:19 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/12 00:43:50
- [misc.c]
- in ssh_gai_strerror() don't fallback to strerror for EAI_SYSTEM when
- errno == 0. Avoids confusing error message in some broken resolver
- cases. bz#2122 patch from plautrba AT redhat.com; ok dtucker
-
-commit 746d1a6c524d2e90ebe98cc29e42573a3e1c3c1b
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:13:02 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/12 00:20:00
- [sftp.c ssh-keygen.c ssh-pkcs11.c]
- fix pointer-signedness warnings from clang/llvm-3.3; "seems nice" deraadt@
-
-commit ce98654674648fb7d58f73edf6aa398656a2dba4
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:12:44 2013 +1000
-
- - djm@cvs.openbsd.org 2013/07/12 00:19:59
- [auth-options.c auth-rsa.c bufaux.c buffer.h channels.c hostfile.c]
- [hostfile.h mux.c packet.c packet.h roaming_common.c serverloop.c]
- fix pointer-signedness warnings from clang/llvm-3.3; "seems nice" deraadt@
-
-commit 0d02c3e10e1ed16d6396748375a133d348127a2a
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:12:06 2013 +1000
-
- - markus@cvs.openbsd.org 2013/07/02 12:31:43
- [dh.c]
- remove extra whitespace
-
-commit fecfd118d6c90df4fcd3cec7b14e4d3ce69a41d5
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:11:50 2013 +1000
-
- - jmc@cvs.openbsd.org 2013/06/27 14:05:37
- [ssh-keygen.1 ssh.1 ssh_config.5 sshd.8 sshd_config.5]
- do not use Sx for sections outwith the man page - ingo informs me that
- stuff like html will render with broken links;
-
- issue reported by Eric S. Raymond, via djm
-
-commit bc35d92e78fd53c3f32cbdbdf89d8b1919788c50
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:11:25 2013 +1000
-
- - djm@cvs.openbsd.org 2013/06/22 06:31:57
- [scp.c]
- improved time_t overflow check suggested by guenther@
-
-commit 8158441d01ab84f33a7e70e27f87c02cbf67e709
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:11:07 2013 +1000
-
- - djm@cvs.openbsd.org 2013/06/21 05:43:10
- [scp.c]
- make this -Wsign-compare clean after time_t conversion
-
-commit bbeb1dac550bad8e6aff9bd27113c6bd5ebb7413
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:10:49 2013 +1000
-
- - djm@cvs.openbsd.org 2013/06/21 05:42:32
- [dh.c]
- sprinkle in some error() to explain moduli(5) parse failures
-
-commit 7f2b438ca0b7c3b9684a03d7bf3eaf379da16de9
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:10:29 2013 +1000
-
- - djm@cvs.openbsd.org 2013/06/21 00:37:49
- [ssh_config.5]
- explicitly mention that IdentitiesOnly can be used with IdentityFile
- to control which keys are offered from an agent.
-
-commit 20bdcd72365e8b3d51261993928cc47c5f0d7c8a
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:10:09 2013 +1000
-
- - djm@cvs.openbsd.org 2013/06/21 00:34:49
- [auth-rsa.c auth.h auth2-hostbased.c auth2-pubkey.c monitor.c]
- for hostbased authentication, print the client host and user on
- the auth success/failure line; bz#2064, ok dtucker@
-
-commit 3071070b39e6d1722151c754cdc2b26640eaf45e
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:09:44 2013 +1000
-
- - markus@cvs.openbsd.org 2013/06/20 19:15:06
- [krl.c]
- don't leak the rdata blob on errors; ok djm@
-
-commit 044bd2a7ddb0b6f6b716c87e57261572e2b89028
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:09:25 2013 +1000
-
- - guenther@cvs.openbsd.org 2013/06/17 04:48:42
- [scp.c]
- Handle time_t values as long long's when formatting them and when
- parsing them from remote servers.
- Improve error checking in parsing of 'T' lines.
-
- ok dtucker@ deraadt@
-
-commit 9a6615542108118582f64b7161ca0e12176e3712
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 18 16:09:04 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/10 19:19:44
- [readconf.c]
- revert 1.203 while we investigate crashes reported by okan@
-
-commit b7482cff46e7e76bfb3cda86c365a08f58d4fca0
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Jul 2 20:06:46 2013 +1000
-
- - (dtucker) [contrib/cygwin/README contrib/cygwin/ssh-host-config
- contrib/cygwin/ssh-user-config] Modernizes and improve readability of
- the Cygwin README file (which hasn't been updated for ages), drop
- unsupported OSes from the ssh-host-config help text, and drop an
- unneeded option from ssh-user-config. Patch from vinschen at redhat com.
-
-commit b8ae92d08b91beaef34232c6ef34b9941473fdd6
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Jun 11 12:10:02 2013 +1000
-
- - (dtucker) [myproposal.h] Make the conditional algorithm support consistent
- and add some comments so it's clear what goes where.
-
-commit 97b62f41adcb0dcbeff142d0540793a7ea17c910
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Jun 11 11:47:24 2013 +1000
-
- - (dtucker) [myproposal.h] Do not advertise AES GSM ciphers if we don't have
- the required OpenSSL support. Patch from naddy at freebsd.
-
-commit 6d8bd57448b45b42809da32857d7804444349ee7
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Jun 11 11:26:10 2013 +1000
-
- - (dtucker) [Makefile.in configure.ac fixalgorithms] Remove unsupported
- algorithms (Ciphers, MACs and HostKeyAlgorithms) from man pages.
-
-commit 36187093ea0b2d2240c043417b8949611687e105
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Jun 10 13:07:11 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/07 15:37:52
- [channels.c channels.h clientloop.c]
- Add an "ABANDONED" channel state and use for mux sessions that are
- disconnected via the ~. escape sequence. Channels in this state will
- be able to close if the server responds, but do not count as active channels.
- This means that if you ~. all of the mux clients when using ControlPersist
- on a broken network, the backgrounded mux master will exit when the
- Control Persist time expires rather than hanging around indefinitely.
- bz#1917, also reported and tested by tedu@. ok djm@ markus@.
-
-commit ae133d4b31af05bb232d797419f498f3ae7e9f2d
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 6 08:30:20 2013 +1000
-
- - (dtucker) [configure.ac sftp.c openbsd-compat/openbsd-compat.h] Cater for
- platforms that don't have multibyte character support (specifically,
- mblen).
-
-commit 408eaf3ab716096f8faf30f091bd54a2c7a17a09
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 6 08:22:46 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/05 22:00:28
- [readconf.c]
- plug another memleak. bz#1967, from Zhenbo Xu, detected by Melton, ok djm
-
-commit e52a260f16888ca75390f97de4606943e61785e8
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 6 08:22:05 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/05 12:52:38
- [sshconnect2.c]
- Fix memory leaks found by Zhenbo Xu and the Melton tool. bz#1967, ok djm
-
-commit 0cca17fa1819d3a0ba06a6db41ab3eaa8d769587
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 6 08:21:14 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/05 02:27:50
- [sshd.c]
- When running sshd -D, close stderr unless we have explicitly requesting
- logging to stderr. From james.hunt at ubuntu.com via bz#1976, djm's patch
- so, err, ok dtucker.
-
-commit 746e9067bd9b3501876e1c86f38f3c510a12f895
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 6 08:20:13 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/05 02:07:29
- [mux.c]
- fix leaks in mux error paths, from Zhenbo Xu, found by Melton. bz#1967,
- ok djm
-
-commit ea64721275a81c4788af36294d94bf4f74012e06
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 6 08:19:09 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/04 20:42:36
- [sftp.c]
- Make sftp's libedit interface marginally multibyte aware by building up
- the quoted string by character instead of by byte. Prevents failures
- when linked against a libedit built with wide character support (bz#1990).
- "looks ok" djm
-
-commit 194454d7a8f8cb8ac55f2b9d0199ef9445788bee
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 6 08:16:04 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/04 19:12:23
- [scp.c]
- use MAXPATHLEN for buffer size instead of fixed value. ok markus
-
-commit 4ac66af091cf6db5a42c18e43738ca9c41e338e5
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 6 08:12:37 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/03 00:03:18
- [mac.c]
- force the MAC output to be 64-bit aligned so umac won't see unaligned
- accesses on strict-alignment architectures. bz#2101, patch from
- tomas.kuthan at oracle.com, ok djm@
-
-commit ea8342c248ad6c0a4fe1a70de133f954973bd2b2
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 6 08:11:40 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/02 23:36:29
- [clientloop.h clientloop.c mux.c]
- No need for the mux cleanup callback to be visible so restore it to static
- and call it through the detach_user function pointer. ok djm@
-
-commit 5d12b8f05d79ba89d0807910a664fa80f6f3bf8c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 6 08:09:10 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/02 21:01:51
- [channels.h]
- typo in comment
-
-commit dc62edbf121c41e8b5270904091039450206d98a
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 6 05:12:35 2013 +1000
-
- - (dtucker) [Makefile.in] append $CFLAGS to compiler options when building
- modpipe in case there's anything in there we need.
-
-commit 2a22873cd869679415104bc9f6bb154811ee604c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 6 01:59:13 2013 +1000
-
- - (dtucker) [regress/forwarding.sh] For (as yet unknown) reason, the
- forwarding test is extremely slow copying data on some machines so switch
- back to copying the much smaller ls binary until we can figure out why
- this is.
-
-commit b4e00949f01176cd4fae3e0cef5ffa8dea379042
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jun 5 22:48:44 2013 +1000
-
- - (dtucker) [contrib/ssh-copy-id] bz#2117: Use portable operator in test.
- Patch from cjwatson at debian.
-
-commit 2ea9eb77a7fcab3190564ef5a6a5377a600aa391
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Jun 5 15:04:00 2013 +1000
-
- - (dtucker) Enable sha256 kex methods based on the presence of the necessary
- functions, not from the openssl version.
-
-commit 16cac190ebb9b5612cccea63a7c22ac33bc9a07a
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Jun 4 12:55:24 2013 +1000
-
- - (dtucker) [configure.ac] Some other platforms need sys/types.h before
- sys/socket.h.
-
-commit 0b43ffe143a5843703c3755fa040b8684fb04134
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Jun 3 09:30:44 2013 +1000
-
- - (dtucker) [configure.ac] Some platforms need sys/types.h before sys/un.h.
-
-commit 3f3064c82238c486706471d300217d73dd0f125e
-Author: Tim Rice <tim@multitalents.net>
-Date: Sun Jun 2 15:13:09 2013 -0700
-
- - (tim) [regress/sftp-chroot.sh] skip if no sudo. ok dtucker
-
-commit 01ec0af301f60fefdd0079647f13ef9abadd2db5
-Author: Tim Rice <tim@multitalents.net>
-Date: Sun Jun 2 14:31:27 2013 -0700
-
- - (tim) [aclocal.m4] Enhance OSSH_CHECK_CFLAG_COMPILE to check stderr.
- feedback and ok dtucker
-
-commit 5ab9b63468100757479534edeb53f788a61fe08b
-Author: Tim Rice <tim@multitalents.net>
-Date: Sun Jun 2 14:05:48 2013 -0700
-
- - (tim) [configure.ac regress/Makefile] With rev 1.47 of test-exec.sh we
- need a shell that can handle "[ file1 -nt file2 ]". Rather than keep
- dealing with shell portability issues in regression tests, we let
- configure find us a capable shell on those platforms with an old /bin/sh.
-
-commit 898ac935e56a7ac5d8b686c590fdb8b7aca27e59
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Jun 3 02:03:25 2013 +1000
-
- - (dtucker) [configure.ac] bz#2111: don't try to use lastlog on Android.
- Patch from Nathan Osman.
-
-commit ef4901c3eb98c7ab1342c3cd8f2638da1f4b0678
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Jun 3 01:59:13 2013 +1000
-
- - (dtucker) [configure.ac] sys/un.h needs sys/socket.h on some platforms
- to prevent noise from configure. Patch from Nathan Osman.
-
-commit 073f795bc1c7728c320e5982c0d417376b0907f5
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 23:47:11 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/02 13:35:58
- [ssh-agent.c]
- Make parent_alive_interval time_t to avoid signed/unsigned comparison
-
-commit 00e1abb1ebe13ab24e812f68715f46e65e7c5271
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 23:46:24 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/02 13:33:05
- [progressmeter.c]
- Add misc.h for monotime prototype. (id sync only)
-
-commit 86211d1738695e63b2a68f0c3a4f60e1a9d9bda3
-Author: Tim Rice <tim@multitalents.net>
-Date: Sat Jun 1 18:38:23 2013 -0700
-
- 20130602
- - (tim) [Makefile.in] Make Solaris, UnixWare, & OpenServer linkers happy
- linking regress/modpipe.
-
-commit e9887d1c37940b9d6c72d55cfad7a40de4c6e28d
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 09:17:09 2013 +1000
-
- - (dtucker) [sandbox-seccomp-filter.c] Allow clock_gettimeofday.
-
-commit 65cf74079a2d563c4ede649116a13ca78c8cc2a4
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 09:11:19 2013 +1000
-
- fix typo
-
-commit c9a1991b95a4c9f04f9dcef299a8110d2ec80d3e
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 08:37:05 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/01 22:34:50
- [sftp-client.c]
- Update progressmeter when data is acked, not when it's sent. bz#2108, from
- Debian via Colin Watson, ok djm@
-
-commit a710891659202c82545e84725d4e5cd77aef567c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 08:18:31 2013 +1000
-
- - (dtucker) [configure.ac misc.c] Look for clock_gettime in librt and fall
- back to time(NULL) if we can't find it anywhere.
-
-commit f60845fde29cead9d75e812db1c04916b4c58ffd
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 08:07:31 2013 +1000
-
- - (dtucker) [M auth-chall.c auth-krb5.c auth-pam.c cipher-aes.c cipher-ctr.c
- groupaccess.c loginrec.c monitor.c monitor_wrap.c session.c sshd.c
- sshlogin.c uidswap.c openbsd-compat/bsd-cygwin_util.c
- openbsd-compat/getrrsetbyname-ldns.c openbsd-compat/port-aix.c
- openbsd-compat/port-linux.c] Replace portable-specific instances of xfree
- with the equivalent calls to free.
-
-commit 12f6533215c0a36ab29d11ff52a853fce45573b4
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 08:01:24 2013 +1000
-
- Remove stray '+' accidentally introduced in sync
-
-commit 3750fce6ac6b287f62584ac55a4406df95c71b92
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 07:52:21 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/01 20:59:25
- [scp.c sftp-client.c]
- Replace S_IWRITE, which isn't standardized, with S_IWUSR, which is. Patch
- from Nathan Osman via bz#2113. ok deraadt.
-
- (note: corrected bug number from 2085)
-
-commit b759c9c2efebe7b416ab81093ca8eb17836b6933
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 07:46:16 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/06/01 13:15:52
- [ssh-agent.c clientloop.c misc.h packet.c progressmeter.c misc.c
- channels.c sandbox-systrace.c]
- Use clock_gettime(CLOCK_MONOTONIC ...) for ssh timers so that things like
- keepalives and rekeying will work properly over clock steps. Suggested by
- markus@, "looks good" djm@.
-
-commit 55119253c64808b0d3b2ab5d2bc67ee9dac3430b
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 07:43:59 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/31 12:28:10
- [ssh-agent.c]
- Use time_t where appropriate. ok djm
-
-commit 0acca3797d53d958d240c69a5f222f2aa8444858
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 07:41:51 2013 +1000
-
- - djm@cvs.openbsd.org 2013/05/19 02:42:42
- [auth.h auth.c key.c monitor.c auth-rsa.c auth2.c auth1.c key.h]
- Standardise logging of supplemental information during userauth. Keys
- and ruser is now logged in the auth success/failure message alongside
- the local username, remote host/port and protocol in use. Certificates
- contents and CA are logged too.
- Pushing all logging onto a single line simplifies log analysis as it is
- no longer necessary to relate information scattered across multiple log
- entries. "I like it" markus@
-
-commit 74836ae0fabcc1a76b9d9eacd1629c88a054b2d0
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 07:32:00 2013 +1000
-
- - djm@cvs.openbsd.org 2013/05/19 02:38:28
- [auth2-pubkey.c]
- fix failure to recognise cert-authority keys if a key of a different type
- appeared in authorized_keys before it; ok markus@
-
-commit a627d42e51ffa71e014d7b2d2c07118122fd3ec3
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 07:31:17 2013 +1000
-
- - djm@cvs.openbsd.org 2013/05/17 00:13:13
- [xmalloc.h cipher.c sftp-glob.c ssh-keyscan.c ssh.c sftp-common.c
- ssh-ecdsa.c auth2-chall.c compat.c readconf.c kexgexs.c monitor.c
- gss-genr.c cipher-3des1.c kex.c monitor_wrap.c ssh-pkcs11-client.c
- auth-options.c rsa.c auth2-pubkey.c sftp.c hostfile.c auth2.c
- servconf.c auth.c authfile.c xmalloc.c uuencode.c sftp-client.c
- auth2-gss.c sftp-server.c bufaux.c mac.c session.c jpake.c kexgexc.c
- sshconnect.c auth-chall.c auth2-passwd.c sshconnect1.c buffer.c
- kexecdhs.c kexdhs.c ssh-rsa.c auth1.c ssh-pkcs11.c auth2-kbdint.c
- kexdhc.c sshd.c umac.c ssh-dss.c auth2-jpake.c bufbn.c clientloop.c
- monitor_mm.c scp.c roaming_client.c serverloop.c key.c auth-rsa.c
- ssh-pkcs11-helper.c ssh-keysign.c ssh-keygen.c match.c channels.c
- sshconnect2.c addrmatch.c mux.c canohost.c kexecdhc.c schnorr.c
- ssh-add.c misc.c auth2-hostbased.c ssh-agent.c bufec.c groupaccess.c
- dns.c packet.c readpass.c authfd.c moduli.c]
- bye, bye xfree(); ok markus@
-
-commit c7aad0058c957afeb26a3f703e8cb0eddeb62365
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 07:18:47 2013 +1000
-
- - (dtucker) [configure.ac defines.h] Test for fd_mask, howmany and NFDBITS
- rather than trying to enumerate the plaforms that don't have them.
- Based on a patch from Nathan Osman, with help from tim@.
-
-commit c0c3373216801797053e123b5f62d35bf41b3611
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Jun 2 06:28:03 2013 +1000
-
- - (dtucker) [configure.ac openbsd-compat/xcrypt.c] bz#2112: fall back to
- using openssl's DES_crpyt function on platorms that don't have a native
- one, eg Android. Based on a patch from Nathan Osman.
-
-commit efdf5342143a887013a1daae583167dadf6752a7
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 30 08:29:08 2013 +1000
-
- - (dtucker) [configure.ac openbsd-compat/bsd-misc.h] bz#2087: Add a null
- implementation of endgrent for platforms that don't have it (eg Android).
- Loosely based on a patch from Nathan Osman, ok djm
-
-commit 9b42d327380e5cd04efde6fb70e1535fecedf0d7
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 20:48:59 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 10:35:43
- [regress/scp.sh]
- use a file extention that's not special on some platforms. from portable
- (id sync only)
-
-commit 0a404b0ed79ba45ccaf7ed5528a8f5004c3698cb
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 20:47:29 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 10:34:30
- [regress/portnum.sh]
- use a more portable negated if structure. from portable (id sync only)
-
-commit 62ee222e6f3f5ee288434f58b5136ae3d56f5164
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 20:46:00 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 10:33:09
- [regress/agent-getpeereid.sh]
- don't redirect stdout from sudo. from portable (id sync only)
-
-commit 00478d30cb4bcc18dc1ced8144d16b03cdf790f6
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 20:45:06 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 10:30:07
- [regress/test-exec.sh]
- wait a bit longer for startup and use case for absolute path.
- from portable (id sync only)
-
-commit 98989eb95eef0aefed7e9fb4e65c2f625be946f6
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 20:44:09 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 10:28:11
- [regress/sftp.sh]
- only compare copied data if sftp succeeds. from portable (id sync only)
-
-commit 438f60eb9a5f7cd40bb242cfec865e4fde71b07c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 20:43:13 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 10:26:26
- [regress/sftp-badcmds.sh]
- remove unused BATCH variable. (id sync only)
-
-commit 1466bd25a8d1ff7ae455a795d2d7d52dc17d2938
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 20:42:05 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 10:24:48
- [localcommand.sh]
- use backticks for portability. (id sync only)
-
-commit 05b5e518c9969d63471f2ccfd85b1de6e724d30b
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 20:41:07 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 10:23:52
- [regress/login-timeout.sh regress/reexec.sh regress/test-exec.sh]
- Use SUDO when cat'ing pid files and running the sshd log wrapper so that
- it works with a restrictive umask and the pid files are not world readable.
- Changes from -portable. (id sync only)
-
-commit dd669173f93ea8c8397e0af758eaf13ab4f1c591
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 20:39:57 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 10:16:26
- [regress/try-ciphers.sh]
- use expr for math to keep diffs vs portable down
- (id sync only)
-
-commit 044f32f4c6fd342f9f5949bb0ca77624c0db4494
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 20:12:57 2013 +1000
-
- - (dtucker) [regress/cfgmatch.sh] Remove unneeded sleep renderd obsolete by
- rev 1.6 which calls wait.
-
-commit 9cc8ff7b63f175661c8807006f6d2649d56ac402
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 20:01:52 2013 +1000
-
- - (dtucker) [regress/runtests.sh] Remove obsolete test driver script.
-
-commit f8d5b3451726530a864b172c556c311370c244e1
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 19:53:25 2013 +1000
-
- - (dtucker) [regress/stderr-after-eof.sh regress/test-exec.sh] Move the md5
- helper function to the portable part of test-exec.sh.
-
-commit 6f66981ed3c6bb83b937959f329323975e356c33
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 19:28:51 2013 +1000
-
- - (dtucker) [regress/test-exec.sh] Move the portable-specific functions
- together and add a couple of missing lines from openbsd.
-
-commit 5f1a89a3b67264f4aa83e057cd4f74fd60b9ffa4
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 19:17:58 2013 +1000
-
- - (dtucker) [regress/integrity.sh regress/krl.sh regress/test-exec.sh]
- Move the jot helper function to portable-specific part of test-exec.sh.
-
-commit 96457a54d05dea81f34ecb4e059d2f8b98382b85
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 19:03:38 2013 +1000
-
- - (dtucker) [regress/agent-getpeereid.sh] Resync spaces with openbsd.
-
-commit 7f193236594e8328ad133ea05eded31f837b45b5
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 19:02:28 2013 +1000
-
- - (dtucker) [regress/cfgmatch.sh] Resync config file setup with openbsd.
-
-commit 8654dd2d737800d09e7730b3dfc2a54411f4cf90
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 16:03:48 2013 +1000
-
- - (dtucker) [openbsd-compat/getopt.h] Remove unneeded bits.
-
-commit 59d928d3b47e8298f4a8b4b3fb37fb8c8ce1b098
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 15:32:29 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 04:29:14
- [regress/sftp.sh regress/putty-ciphers.sh regress/cipher-speed.sh
- regress/test-exec.sh regress/sftp-batch.sh regress/dynamic-forward.sh
- regress/putty-transfer.sh regress/conch-ciphers.sh regress/sftp-cmds.sh
- regress/scp.sh regress/ssh-com-sftp.sh regress/rekey.sh
- regress/putty-kex.sh regress/stderr-data.sh regress/stderr-after-eof.sh
- regress/sftp-badcmds.sh regress/reexec.sh regress/ssh-com-client.sh
- regress/sftp-chroot.sh regress/forwarding.sh regress/transfer.sh
- regress/multiplex.sh]
- Move the setting of DATA and COPY into test-exec.sh
-
-commit 34035be27b7ddd84706fe95c39d37cba7d5c9572
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 14:47:51 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 01:32:11
- [regress/integrity.sh]
- don't print output from ssh before getting it (it's available in ssh.log)
-
-commit b8b96b0aa634d440feba4331c80ae4de9dda2081
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 14:46:20 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 01:16:09
- [regress/agent-timeout.sh]
- Pull back some portability changes from -portable:
- - TIMEOUT is a read-only variable in some shells
- - not all greps have -q so redirect to /dev/null instead.
- (ID sync only)
-
-commit a40d97ff46831c9081a6a4472036689360847fb1
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 14:44:53 2013 +1000
-
- sync missing ID
-
-commit 56347efe796a0506e846621ae65562b978e45f1d
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 13:28:36 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/17 00:37:40
- [regress/agent.sh regress/keytype.sh regress/cfgmatch.sh
- regress/forcecommand.sh regress/proto-version.sh regress/test-exec.sh
- regress/cipher-speed.sh regress/cert-hostkey.sh regress/cert-userkey.sh
- regress/ssh-com.sh]
- replace 'echo -n' with 'printf' since it's more portable
- also remove "echon" hack.
-
-commit 91af05c5167fe0aa5bd41d2e4a83757d9f627c18
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 13:16:59 2013 +1000
-
- - (dtucker) [regress/integrity.sh]. Force fixed Diffie-Hellman key exchange
- methods. When the openssl version doesn't support ECDH then next one on
- the list is DH group exchange, but that causes a bit more traffic which can
- mean that the tests flip bits in the initial exchange rather than the MACed
- traffic and we get different errors to what the tests look for.
-
-commit 6e1e60c3c2e16c32bb7ca0876caaa6182a4e4b2c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 11:23:41 2013 +1000
-
- - (dtucker) [regress/bsd.regress.mk] Remove unused file. We've never used it
- in portable and it's long gone in openbsd.
-
-commit 982b0cbc4c2b5ea14725f4b339393cdf343dd0fe
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 09:45:12 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/16 05:48:31
- [regress/rekey.sh]
- add tests for RekeyLimit parsing
-
-commit 14490fe7b0f45b1b19f8a3dc10eb3d214f27f5bd
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 09:44:20 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/16 04:26:10
- [regress/rekey.sh]
- add server-side rekey test
-
-commit c31c8729c15f83fba14ef9da0d66bda6215ff69a
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 09:43:33 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/16 03:33:30
- [regress/rekey.sh]
- test rekeying when there's no data being transferred
-
-commit a8a62fcc46c19997797846197a6256ed9a777a47
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 09:42:34 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/16 02:10:35
- [rekey.sh]
- Add test for time-based rekeying
-
-commit 5e95173715d516e6014485e2b6def1fb3db84036
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 09:41:33 2013 +1000
-
- - djm@cvs.openbsd.org 2013/05/10 03:46:14
- [modpipe.c]
- sync some portability changes from portable OpenSSH (id sync only)
-
-commit a4df65b9fc68a555a7d8781700475fb03ed6e694
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 09:37:31 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/04/22 07:28:53
- [multiplex.sh]
- Add tests for -Oforward and -Ocancel for local and remote forwards
-
-commit 40aaff7e4bcb05b05e3d24938b6d34885be817da
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 09:36:20 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/04/22 07:23:08
- [multiplex.sh]
- Write mux master logs to regress.log instead of ssh.log to keep separate
-
-commit f3568fc62b73b50a0a3c8447e4a00f4892cab25e
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 09:35:26 2013 +1000
-
- - djm@cvs.openbsd.org 2013/04/18 02:46:12
- [Makefile regress/sftp-chroot.sh]
- test sshd ChrootDirectory+internal-sftp; feedback & ok dtucker@
-
-commit dfea3bcdd7c980c2335402464b7dd8d8721e426d
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 09:31:39 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/04/07 02:16:03
- [regress/Makefile regress/rekey.sh regress/integrity.sh
- regress/sshd-log-wrapper.sh regress/forwarding.sh regress/test-exec.sh]
- use -E option for ssh and sshd to write debuging logs to ssh{,d}.log and
- save the output from any failing tests. If a test fails the debug output
- from ssh and sshd for the failing tests (and only the failing tests) should
- be available in failed-ssh{,d}.log.
-
-commit 75129025a2d504b630d1718fef0da002f5662f63
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 09:19:10 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/04/06 06:00:22
- [regress/rekey.sh regress/test-exec.sh regress/integrity.sh
- regress/multiplex.sh Makefile regress/cfgmatch.sh]
- Split the regress log into 3 parts: the debug output from ssh, the debug
- log from sshd and the output from the client command (ssh, scp or sftp).
- Somewhat functional now, will become more useful when ssh/sshd -E is added.
-
-commit 7c8b1e72331293b4707dc6f7f68a69e975a3fa70
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 09:10:20 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/03/23 11:09:43
- [test-exec.sh]
- Only regenerate host keys if they don't exist or if ssh-keygen has changed
- since they were. Reduces test runtime by 5-30% depending on machine
- speed.
-
-commit 712de4d1100963b11bc618472f95ce36bf7e2ae3
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 17 09:07:12 2013 +1000
-
- - djm@cvs.openbsd.org 2013/03/07 00:20:34
- [regress/proxy-connect.sh]
- repeat test with a style appended to the username
-
-commit 09c0f0325b2f538de9a1073e03b8ef26dece4c16
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:48:57 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/16 10:44:06
- [servconf.c]
- remove another now-unused variable
-
-commit 9113d0c2381202412c912a20c8083ab7d6824ec9
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:48:14 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/16 10:43:34
- [servconf.c readconf.c]
- remove now-unused variables
-
-commit e194ba4111ffd47cd1f4c8be1ddc8a4cb673d005
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:47:31 2013 +1000
-
- - (dtucker) [configure.ac readconf.c servconf.c
- openbsd-compat/openbsd-compat.h] Add compat bits for scan_scaled.
-
-commit b7ee8521448100e5b268111ff90feb017e657e44
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:33:10 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/16 09:12:31
- [readconf.c servconf.c]
- switch RekeyLimit traffic volume parsing to scan_scaled. ok djm@
-
-commit dbee308253931f8c1aeebf781d7e7730ff6a0dc1
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:32:29 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/16 09:08:41
- [log.c scp.c sshd.c serverloop.c schnorr.c sftp.c]
- Fix some "unused result" warnings found via clang and -portable.
- ok markus@
-
-commit 64d22946d664dad8165f1fae9e78b53831ed728d
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:31:29 2013 +1000
-
- - jmc@cvs.openbsd.org 2013/05/16 06:30:06
- [sshd_config.5]
- oops! avoid Xr to self;
-
-commit 63e0df2b936770baadc8844617b99e5174b476d0
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:30:31 2013 +1000
-
- - jmc@cvs.openbsd.org 2013/05/16 06:28:45
- [ssh_config.5]
- put IgnoreUnknown in the right place;
-
-commit 0763698f71efef8b3f8460c5700758359219eb7c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:30:03 2013 +1000
-
- - djm@cvs.openbsd.org 2013/05/16 04:27:50
- [ssh_config.5 readconf.h readconf.c]
- add the ability to ignore specific unrecognised ssh_config options;
- bz#866; ok markus@
-
-commit 5f96f3b4bee11ae2b9b32ff9b881c3693e210f96
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:29:28 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/16 04:09:14
- [sshd_config.5 servconf.c servconf.h packet.c serverloop.c monitor.c sshd_config
- sshd.c] Add RekeyLimit to sshd with the same syntax as the client allowing
- rekeying based on traffic volume or time. ok djm@, help & ok jmc@ for the man
- page.
-
-commit c53c2af173cf67fd1c26f98e7900299b1b65b6ec
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:28:16 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/16 02:00:34
- [ssh_config sshconnect2.c packet.c readconf.h readconf.c clientloop.c
- ssh_config.5 packet.h]
- Add an optional second argument to RekeyLimit in the client to allow
- rekeying based on elapsed time in addition to amount of traffic.
- with djm@ jmc@, ok djm
-
-commit 64c6fceecd27e1739040b42de8f3759454260b39
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:27:14 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/10 10:13:50
- [ssh-pkcs11-helper.c]
- remove unused extern optarg. ok markus@
-
-commit caf00109346e4ab6bb495b0e22bc5b1e7ee22f26
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:26:18 2013 +1000
-
- - djm@cvs.openbsd.org 2013/05/10 04:08:01
- [key.c]
- memleak in cert_free(), wasn't actually freeing the struct;
- bz#2096 from shm AT digitalsun.pl
-
-commit 7e831edbf7a1b0b9aeeb08328b9fceafaad1bf22
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:25:40 2013 +1000
-
- add missing attribution
-
-commit 54da6be320495604ddf65d10ac4cc8cf7849c533
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:25:04 2013 +1000
-
- - djm@cvs.openbsd.org 2013/05/10 03:40:07
- [sshconnect2.c]
- fix bzero(ptr_to_struct, sizeof(ptr_to_struct)); bz#2100 from
-
-commit 5d8b702d95c0dfc338726fecfbb709695afd1377
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:24:23 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/05/06 07:35:12
- [sftp-server.8]
- Reference the version of the sftp draft we actually implement. ok djm@
-
-commit 026d9db3fbe311b5a7e98d62472cb666aa559648
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:23:52 2013 +1000
-
- - tedu@cvs.openbsd.org 2013/04/24 16:01:46
- [misc.c]
- remove extra parens noticed by nicm
-
-commit 2ca51bf140ef2c2409fd220778529dc17c11d8fa
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu May 16 20:22:46 2013 +1000
-
- - tedu@cvs.openbsd.org 2013/04/23 17:49:45
- [misc.c]
- use xasprintf instead of a series of strlcats and strdup. ok djm
-
-commit 6aa3eacc5e5f39702b6dd5b27970d9fd97bc2383
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu May 16 11:10:17 2013 +1000
-
- - (djm) [contrib/ssh-copy-id] Fix bug that could cause "rm *" to be
- executed if mktemp failed; bz#2105 ok dtucker@
-
-commit c54e3e0741a27119b3badd8ff92b1988b7e9bd50
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 10 18:53:14 2013 +1000
-
- - (dtucker) [configure.ac] Add -Werror to the -Qunused-arguments test so
- we don't get a warning on compilers that *don't* support it. Add
- -Wno-unknown-warning-option. Move both to the start of the list for
- maximum noise suppression. Tested with gcc 4.6.3, gcc 2.95.4 and clang 2.9.
-
-commit a75d247a18a5099c60226395354eb252c097ac86
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 10 18:11:55 2013 +1000
-
- - (dtucker) [kex.c] Only include sha256 and ECC key exchange methods when the
- underlying libraries support them.
-
-commit 0abfb559e3f79d1f217773510d7626c3722aa3c1
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 10 18:08:49 2013 +1000
-
- - (dtucker) [openbsd-compat/getopt.h openbsd-compat/getopt_long.c
- openbsd-compat/openbsd-compat.h] pull in getopt.h from openbsd and plumb
- in to use it when we're using our own getopt.
-
-commit ccfdfceacb7e23d1479ed4cc91976c5ac6e23c56
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 10 16:28:55 2013 +1000
-
- - (dtucker) [openbsd-compat/Makefile.in openbsd-compat/getopt.c
- openbsd-compat/getopt_long.c regress/modpipe.c] Remove getopt.c, add
- portability code to getopt_long.c and switch over Makefile and the ugly
- hack in modpipe.c. Fixes bz#1448.
-
-commit 39332020078aa8fd4fc28e00b336438dc64b0f5a
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 10 15:38:11 2013 +1000
-
- - (dtucker) [openbsd-compat/getopt_long.c] Import from OpenBSD. No
- portability changes yet.
-
-commit 35b2fe99bee4f332d1c1efa49107cdb3c67da07a
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 10 15:35:26 2013 +1000
-
- - (dtucker) [openbsd-compat/getopt.c] Factor out portibility changes to
- getopt.c. Preprocessed source is identical other than line numbers.
-
-commit abbc7a7c02e45787d023f50a30f62d7a3e14fe9e
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri May 10 13:54:23 2013 +1000
-
- - (dtucker) [configure.ac] Enable -Wsizeof-pointer-memaccess if the compiler
- supports it. Mentioned by Colin Watson in bz#2100, ok djm.
-
-commit bc02f163f6e882d390abfb925b47b41e13ae523b
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 19:25:49 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/04/22 01:17:18
- [mux.c]
- typo in debug output: evitval->exitval
-
-commit f8b894e31dc3530c7eb6d0a378848260d54f74c4
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 19:25:29 2013 +1000
-
- - djm@cvs.openbsd.org 2013/04/19 12:07:08
- [kex.c]
- remove duplicated list entry pointed out by naddy@
-
-commit 34bd20a1e53b63ceb01f06c1654d9112e6784b0a
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 19:25:00 2013 +1000
-
- - djm@cvs.openbsd.org 2013/04/19 11:10:18
- [ssh.c]
- add -Q to usage; reminded by jmc@
-
-commit ea11119eee3c5e2429b1f5f8688b25b028fa991a
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 19:24:32 2013 +1000
-
- - djm@cvs.openbsd.org 2013/04/19 01:06:50
- [authfile.c cipher.c cipher.h kex.c kex.h kexecdh.c kexecdhc.c kexecdhs.c]
- [key.c key.h mac.c mac.h packet.c ssh.1 ssh.c]
- add the ability to query supported ciphers, MACs, key type and KEX
- algorithms to ssh. Includes some refactoring of KEX and key type handling
- to be table-driven; ok markus@
-
-commit a56086b9903b62c1c4fdedf01b68338fe4dc90e4
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:24:18 2013 +1000
-
- - djm@cvs.openbsd.org 2013/04/19 01:03:01
- [session.c]
- reintroduce 1.262 without the connection-killing bug:
- fatal() when ChrootDirectory specified by running without root privileges;
- ok markus@
-
-commit 0d6771b4648889ae5bc4235f9e3fc6cd82b710bd
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:23:24 2013 +1000
-
- - djm@cvs.openbsd.org 2013/04/19 01:01:00
- [ssh-keygen.c]
- fix some memory leaks; bz#2088 ok dtucker@
-
-commit 467b00c38ba244f9966466e57a89d003f3afb159
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:23:07 2013 +1000
-
- - djm@cvs.openbsd.org 2013/04/19 01:00:10
- [sshd_config.5]
- document the requirment that the AuthorizedKeysCommand be owned by root;
- ok dtucker@ markus@
-
-commit 9303e6527bb5ca7630c765f28624702c212bfd6c
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:22:40 2013 +1000
-
- - djm@cvs.openbsd.org 2013/04/18 02:16:07
- [sftp.c]
- make "sftp -q" do what it says on the sticker: hush everything but errors;
-
-commit f1a02aea35504e8bef2ed9eef6f9ddeab12bacb3
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:22:13 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/04/17 09:04:09
- [session.c]
- revert rev 1.262; it fails because uid is already set here. ok djm@
-
-commit d5edefd27a30768cc7a4817302e964b6cb2f9be7
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:21:39 2013 +1000
-
- - djm@cvs.openbsd.org 2013/04/11 02:27:50
- [packet.c]
- quiet disconnect notifications on the server from error() back to logit()
- if it is a normal client closure; bz#2057 ok+feedback dtucker@
-
-commit 6901032b05291fc5d2bd4067fc47904de3506fda
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:21:24 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/04/07 09:40:27
- [sshd.8]
- clarify -e text. suggested by & ok jmc@
-
-commit 03d4d7e60b16f913c75382e32e136ddfa8d6485f
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:21:06 2013 +1000
-
- - dtucker@cvs.openbsd.org 2013/04/07 02:10:33
- [log.c log.h ssh.1 ssh.c sshd.8 sshd.c]
- Add -E option to ssh and sshd to append debugging logs to a specified file
- instead of stderr or syslog. ok markus@, man page help jmc@
-
-commit 37f1c08473b1ef2a188ee178ce2e11e841f88563
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:20:43 2013 +1000
-
- - markus@cvs.openbsd.org 2013/04/06 16:07:00
- [channels.c sshd.c]
- handle ECONNABORTED for accept(); ok deraadt some time ago...
-
-commit 172859cff7df9fd8a29a1f0a4de568f644bbda50
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:19:27 2013 +1000
-
- - djm@cvs.openbsd.org 2013/04/05 00:58:51
- [mux.c]
- cleanup mux-created channels that are in SSH_CHANNEL_OPENING state too
- (in addition to ones already in OPEN); bz#2079, ok dtucker@
-
-commit 9f12b5dcd5f7772e633fb2786c63bfcbea1f1aea
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:19:11 2013 +1000
-
- - djm@cvs.openbsd.org 2013/04/05 00:31:49
- [pathnames.h]
- use the existing _PATH_SSH_USER_RC define to construct the other
- pathnames; bz#2077, ok dtucker@ (no binary change)
-
-commit d677ad14ff7efedf21745ee1694058350e758e18
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:18:51 2013 +1000
-
- - djm@cvs.openbsd.org 2013/04/05 00:14:00
- [auth2-gss.c krl.c sshconnect2.c]
- hush some {unused, printf type} warnings
-
-commit 508b6c3d3b95c8ec078fd4801368597ab29b2db9
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:18:28 2013 +1000
-
- - djm@cvs.openbsd.org 2013/03/08 06:32:58
- [ssh.c]
- allow "ssh -f none ..." ok markus@
-
-commit 91a55f28f35431f9000b95815c343b5a18fda712
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:18:10 2013 +1000
-
- - markus@cvs.openbsd.org 2013/03/07 19:27:25
- [auth.h auth2-chall.c auth2.c monitor.c sshd_config.5]
- add submethod support to AuthenticationMethods; ok and freedback djm@
-
-commit 4ce189d9108c62090a0dd5dea973d175328440db
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:17:52 2013 +1000
-
- - djm@cvs.openbsd.org 2013/03/07 00:19:59
- [auth2-pubkey.c monitor.c]
- reconstruct the original username that was sent by the client, which may
- have included a style (e.g. "root:skey") when checking public key
- signatures. Fixes public key and hostbased auth when the client specified
- a style; ok markus@
-
-commit 5cbec4c25954b184e43bf3d3ac09e65eb474f5f9
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:17:12 2013 +1000
-
- - djm@cvs.openbsd.org 2013/03/06 23:36:53
- [readconf.c]
- g/c unused variable (-Wunused)
-
-commit 998cc56b65682d490c9bbf5977dceb1aa84a0233
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:16:43 2013 +1000
-
- - djm@cvs.openbsd.org 2013/03/06 23:35:23
- [session.c]
- fatal() when ChrootDirectory specified by running without root privileges;
- ok markus@
-
-commit 62e9c4f9b6027620f9091a2f43328e057bdb33f1
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 15:15:49 2013 +1000
-
- - (djm) OpenBSD CVS Sync
- - markus@cvs.openbsd.org 2013/03/05 20:16:09
- [sshconnect2.c]
- reset pubkey order on partial success; ok djm@
-
-commit 6332da2ae88db623d7da8070dd807efa26d9dfe8
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 23 14:25:52 2013 +1000
-
- - (djm) [auth.c configure.ac misc.c monitor.c monitor_wrap.c] Support
- platforms, such as Android, that lack struct passwd.pw_gecos. Report
- and initial patch from Nathan Osman bz#2086; feedback tim@ ok dtucker@
-
-commit ce1c9574fcfaf753a062276867335c1e237f725c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Apr 18 21:36:19 2013 +1000
-
- - (dtucker) [configure.ac] Use -Qunused-arguments to suppress warnings from
- unused argument warnings (in particular, -fno-builtin-memset) from clang.
-
-commit bc68f2451b836e6a3fa65df8774a8b1f10049ded
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Apr 18 11:26:25 2013 +1000
-
- - (djm) [config.guess config.sub] Update to last versions before they switch
- to GPL3. ok dtucker@
-
-commit 15fd19c4c9943cf02bc6f462d52c86ee6a8f422e
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Apr 5 11:22:26 2013 +1100
-
- - djm@cvs.openbsd.org 2013/02/22 22:09:01
- [ssh.c]
- Allow IdenityFile=none; ok markus deraadt (and dtucker for an earlier
- version)
-
-commit 5d1d9541a7c83963cd887b6b36e25b46463a05d4
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Apr 5 11:20:00 2013 +1100
-
- - markus@cvs.openbsd.org 2013/02/22 19:13:56
- [sshconnect.c]
- support ProxyCommand=- (stdin/out already point to the proxy); ok djm@
-
-commit aefa3682431f59cf1ad9a0f624114b135135aa44
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Apr 5 11:18:35 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/02/22 04:45:09
- [ssh.c readconf.c readconf.h]
- Don't complain if IdentityFiles specified in system-wide configs are
- missing. ok djm, deraadt
-
-commit f3c38142435622d056582e851579d8647a233c7f
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Apr 5 11:16:52 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/02/19 02:12:47
- [krl.c]
- Remove bogus include. ok djm
- (id sync only)
-
-commit 1910478c2d2c3d0e1edacaeff21ed388d70759e9
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Apr 5 11:13:08 2013 +1100
-
- - dtucker@cvs.openbsd.org 2013/02/17 23:16:57
- [readconf.c ssh.c readconf.h sshconnect2.c]
- Keep track of which IndentityFile options were manually supplied and which
- were default options, and don't warn if the latter are missing.
- ok markus@
-
-commit c9627cdbc65b25da943f24e6a953da899f08eefc
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Apr 1 12:40:48 2013 +1100
-
- - (dtucker) [openbsd-compat/bsd-cygwin_util.{c,h}] Don't include windows.h
- to avoid conflicting definitions of __int64, adding the required bits.
- Patch from Corinna Vinschen.
-
-commit 75db01d2ce29a85f8e5a2aff2011446896cf3f8a
-Author: Tim Rice <tim@multitalents.net>
-Date: Fri Mar 22 10:14:32 2013 -0700
-
- - (tim) [Makefile.in] remove some duplication introduced in 20130220 commit.
-
-commit 221b4b2436ac78a65c3b775c25ccd396a1fed208
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Mar 22 12:51:09 2013 +1100
-
- - (dtucker) [includes.h] Check if _GNU_SOURCE is already defined before
- defining it again. Prevents warnings if someone, eg, sets it in CFLAGS.
-
-commit c8a0f27c6d761d1335d13ed84d773e9ddf1d95c8
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Mar 22 12:49:14 2013 +1100
-
- - (dtucker) [configure.ac] Add stdlib.h to zlib check for exit() prototype.
-
-commit eed8dc261018aea4d6b8606ca3addc9f8cf9ed1e
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Mar 22 10:25:22 2013 +1100
-
- - (djm) Release 6.2p1
-
-commit 83efe7c86168cc07b8e6cc6df6b54f7ace3b64a3
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Mar 22 10:17:36 2013 +1100
-
- - (djm) [contrib/ssh-copy-id contrib/ssh-copy-id.1] Updated to Phil
- Hands' greatly revised version.
-
-commit 63b4bcd04e1c57b77eabb4e4d359508a4b2af685
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Mar 20 12:55:14 2013 +1100
-
- - (djm) [configure.ac log.c scp.c sshconnect2.c openbsd-compat/vis.c]
- [openbsd-compat/vis.h] FreeBSD's strnvis isn't compatible with OpenBSD's
- so mark it as broken. Patch from des AT des.no
diff --git a/INSTALL b/INSTALL
index cbbb2df5..443ff9f3 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,38 +1,58 @@
1. Prerequisites
----------------
-You will need working installations of Zlib and libcrypto (LibreSSL /
-OpenSSL)
+A C compiler. Any C89 or better compiler should work. Where supported,
+configure will attempt to enable the compiler's run-time integrity checking
+options. Some notes about specific compilers:
+ - clang: -ftrapv and -sanitize=integer require the compiler-rt runtime
+ (CC=clang LDFLAGS=--rtlib=compiler-rt ./configure)
-Zlib 1.1.4 or 1.2.1.2 or greater (ealier 1.2.x versions have problems):
+To support Privilege Separation (which is now required) you will need
+to create the user, group and directory used by sshd for privilege
+separation. See README.privsep for details.
+
+
+The remaining items are optional.
+
+A working installation of zlib:
+Zlib 1.1.4 or 1.2.1.2 or greater (earlier 1.2.x versions have problems):
http://www.gzip.org/zlib/
-libcrypto (LibreSSL or OpenSSL >= 0.9.8f)
-LibreSSL http://www.libressl.org/ ; or
-OpenSSL http://www.openssl.org/
+libcrypto from either of LibreSSL or OpenSSL. Building without libcrypto
+is supported but severely restricts the available ciphers and algorithms.
+ - LibreSSL (https://www.libressl.org/)
+ - OpenSSL (https://www.openssl.org) with any of the following versions:
+ - 1.0.x >= 1.0.1 or 1.1.0 >= 1.1.0g or any 1.1.1
+
+Note that due to a bug in EVP_CipherInit OpenSSL 1.1 versions prior to
+1.1.0g can't be used.
LibreSSL/OpenSSL should be compiled as a position-independent library
-(i.e. with -fPIC) otherwise OpenSSH will not be able to link with it.
-If you must use a non-position-independent libcrypto, then you may need
-to configure OpenSSH --without-pie.
+(i.e. -fPIC, eg by configuring OpenSSL as "./config [options] -fPIC"
+or LibreSSL as "CFLAGS=-fPIC ./configure") otherwise OpenSSH will not
+be able to link with it. If you must use a non-position-independent
+libcrypto, then you may need to configure OpenSSH --without-pie.
-The remaining items are optional.
+If you build either from source, running the OpenSSL self-test ("make
+tests") or the LibreSSL equivalent ("make check") and ensuring that all
+tests pass is strongly recommended.
NB. If you operating system supports /dev/random, you should configure
libcrypto (LibreSSL/OpenSSL) to use it. OpenSSH relies on libcrypto's
-direct support of /dev/random, or failing that, either prngd or egd
+direct support of /dev/random, or failing that, either prngd or egd.
PRNGD:
If your system lacks kernel-based random collection, the use of Lutz
-Jaenicke's PRNGd is recommended.
+Jaenicke's PRNGd is recommended. It requires that libcrypto be configured
+to support it.
http://prngd.sourceforge.net/
EGD:
-If the kernel lacks /dev/random the Entropy Gathering Daemon (EGD) is
-supported only if libcrypto supports it.
+The Entropy Gathering Daemon (EGD) supports the same interface as prngd.
+It also supported only if libcrypto is configured to support it.
http://egd.sourceforge.net/
@@ -40,7 +60,7 @@ PAM:
OpenSSH can utilise Pluggable Authentication Modules (PAM) if your
system supports it. PAM is standard most Linux distributions, Solaris,
-HP-UX 11, AIX >= 5.2, FreeBSD and NetBSD.
+HP-UX 11, AIX >= 5.2, FreeBSD, NetBSD and Mac OS X.
Information about the various PAM implementations are available:
@@ -59,13 +79,6 @@ passphrase requester. This is maintained separately at:
http://www.jmknoble.net/software/x11-ssh-askpass/
-S/Key Libraries:
-
-If you wish to use --with-skey then you will need the library below
-installed. No other S/Key library is currently known to be supported.
-
-http://www.sparc.spb.su/solaris/skey/
-
LibEdit:
sftp supports command-line editing via NetBSD's libedit. If your platform
@@ -84,7 +97,7 @@ http://nlnetlabs.nl/projects/ldns/
Autoconf:
If you modify configure.ac or configure doesn't exist (eg if you checked
-the code out of CVS yourself) then you will need autoconf-2.68 to rebuild
+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.
@@ -92,10 +105,26 @@ http://www.gnu.org/software/autoconf/
Basic Security Module (BSM):
-Native BSM support is know to exist in Solaris from at least 2.5.1,
+Native BSM support is known to exist in Solaris from at least 2.5.1,
FreeBSD 6.1 and OS X. Alternatively, you may use the OpenBSM
implementation (http://www.openbsm.org).
+makedepend:
+
+https://www.x.org/archive/individual/util/
+
+If you are making significant changes to the code you may need to rebuild
+the dependency (.depend) file using "make depend", which requires the
+"makedepend" tool from the X11 distribution.
+
+libfido2:
+
+libfido2 allows the use of hardware security keys over USB. libfido2
+in turn depends on libcbor.
+
+https://github.com/Yubico/libfido2
+https://github.com/pjk/libcbor
+
2. Building / Installation
--------------------------
@@ -124,10 +153,6 @@ make install
This will install the binaries in /opt/{bin,lib,sbin}, but will place the
configuration files in /etc/ssh.
-If you are using Privilege Separation (which is enabled by default)
-then you will also need to create the user, group and directory used by
-sshd for privilege separation. See README.privsep for details.
-
If you are using PAM, you may need to manually install a PAM control
file as "/etc/pam.d/sshd" (or wherever your system prefers to keep
them). Note that the service name used to start PAM is __progname,
@@ -155,13 +180,11 @@ also be enabled in sshd_config (refer to the UsePAM directive).
--with-prngd-socket=/some/file allows you to enable EGD or PRNGD
support and to specify a PRNGd socket. Use this if your Unix lacks
-/dev/random and you don't want to use OpenSSH's builtin entropy
-collection support.
+/dev/random.
--with-prngd-port=portnum allows you to enable EGD or PRNGD support
and to specify a EGD localhost TCP port. Use this if your Unix lacks
-/dev/random and you don't want to use OpenSSH's builtin entropy
-collection support.
+/dev/random.
--with-lastlog=FILE will specify the location of the lastlog file.
./configure searches a few locations for lastlog, but may not find
@@ -172,9 +195,6 @@ it if lastlog is installed in a different place.
--with-osfsia, --without-osfsia will enable or disable OSF1's Security
Integration Architecture. The default for OSF1 machines is enable.
---with-skey=PATH will enable S/Key one time password support. You will
-need the S/Key libraries and header files installed for this to work.
-
--with-md5-passwords will enable the use of MD5 passwords. Enable this
if your operating system uses MD5 passwords and the system crypt() does
not support them directly (see the crypt(3/3c) man page). If enabled, the
@@ -197,8 +217,7 @@ created.
--with-xauth=PATH specifies the location of the xauth binary
--with-ssl-dir=DIR allows you to specify where your Libre/OpenSSL
-libraries
-are installed.
+libraries are installed.
--with-ssl-engine enables Libre/OpenSSL's (hardware) ENGINE support
@@ -209,7 +228,7 @@ If you need to pass special options to the compiler or linker, you
can specify these as environment variables before running ./configure.
For example:
-CFLAGS="-O -m486" LDFLAGS="-s" LIBS="-lrubbish" LD="/usr/foo/ld" ./configure
+CC="/usr/foo/cc" CFLAGS="-O" LDFLAGS="-s" LIBS="-lrubbish" ./configure
3. Configuration
----------------
@@ -223,13 +242,17 @@ review it to ensure that it matches your security requirements.
To generate a host key, run "make host-key". Alternately you can do so
manually using the following commands:
- ssh-keygen -t rsa1 -f /etc/ssh/ssh_host_key -N ""
- ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ""
- ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ""
+ ssh-keygen -t [type] -f /etc/ssh/ssh_host_key -N ""
+
+for each of the types you wish to generate (rsa, dsa or ecdsa) or
+
+ ssh-keygen -A
+
+to generate keys for all supported types.
Replacing /etc/ssh with the correct path to the configuration directory.
(${prefix}/etc or whatever you specified with --sysconfdir during
-configuration)
+configuration).
If you have configured OpenSSH with EGD support, ensure that EGD is
running and has collected some Entropy.
@@ -254,9 +277,6 @@ summary data may be published.
5. Problems?
------------
-If you experience problems compiling, installing or running OpenSSH.
-Please refer to the "reporting bugs" section of the webpage at
-http://www.openssh.com/
-
-
-$Id: INSTALL,v 1.91 2014/09/09 02:23:11 dtucker Exp $
+If you experience problems compiling, installing or running OpenSSH,
+please refer to the "reporting bugs" section of the webpage at
+https://www.openssh.com/
diff --git a/LICENCE b/LICENCE
index f5238713..a2278a05 100644
--- a/LICENCE
+++ b/LICENCE
@@ -75,27 +75,6 @@ OpenSSH contains no GPL code.
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
-2)
- The 32-bit CRC compensation attack detector in deattack.c was
- contributed by CORE SDI S.A. under a BSD-style license.
-
- * Cryptographic attack detector for ssh - source code
- *
- * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
- *
- * All rights reserved. Redistribution and use in source and binary
- * forms, with or without modification, are permitted provided that
- * this copyright notice is retained.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
- * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
- * SOFTWARE.
- *
- * Ariel Futoransky <futo@core-sdi.com>
- * <http://www.core-sdi.com>
-
3)
ssh-keyscan was contributed by David Mazieres under a BSD-style
license.
@@ -195,7 +174,7 @@ OpenSSH contains no GPL code.
Gert Doering
Jakob Schlyter
Jason Downs
- Juha Yrjölä
+ Juha Yrjölä
Michael Stone
Networks Associates Technology, Inc.
Solar Designer
@@ -337,4 +316,4 @@ OpenSSH contains no GPL code.
------
-$OpenBSD: LICENCE,v 1.19 2004/08/30 09:18:08 markus Exp $
+$OpenBSD: LICENCE,v 1.20 2017/04/30 23:26:16 djm Exp $
diff --git a/METADATA b/METADATA
new file mode 100644
index 00000000..eef037a7
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,17 @@
+name: "openssh"
+description:
+ "Secure Shell (SSH) protocol client, server and utilities"
+
+third_party {
+ url {
+ type: HOMEPAGE
+ value: "https://www.openssh.com/"
+ }
+ url {
+ type: GIT
+ value: "https://github.com/openssh/openssh-portable"
+ }
+ version: "8.3p1"
+ last_upgrade_date { year: 2020 month: 8 day: 20 }
+ license_type: NOTICE
+}
diff --git a/Makefile.in b/Makefile.in
index 40cc7aae..c9e4294d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,6 +1,4 @@
-# $Id: Makefile.in,v 1.365 2014/08/30 06:23:07 djm Exp $
-
-# uncomment if you run a non bourne compatable shell. Ie. csh
+# uncomment if you run a non bourne compatible shell. Ie. csh
#SHELL = @SH@
AUTORECONF=autoreconf
@@ -26,6 +24,7 @@ ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
SFTP_SERVER=$(libexecdir)/sftp-server
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
+SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper
PRIVSEP_PATH=@PRIVSEP_PATH@
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
STRIP_OPT=@STRIP_OPT@
@@ -37,32 +36,48 @@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \
-D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \
-D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \
-D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \
+ -D_PATH_SSH_SK_HELPER=\"$(SSH_SK_HELPER)\" \
-D_PATH_SSH_PIDDIR=\"$(piddir)\" \
-D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\"
CC=@CC@
LD=@LD@
CFLAGS=@CFLAGS@
+CFLAGS_NOPIE=@CFLAGS_NOPIE@
CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
+PICFLAG=@PICFLAG@
LIBS=@LIBS@
K5LIBS=@K5LIBS@
GSSLIBS=@GSSLIBS@
SSHLIBS=@SSHLIBS@
SSHDLIBS=@SSHDLIBS@
LIBEDIT=@LIBEDIT@
+LIBFIDO2=@LIBFIDO2@
AR=@AR@
AWK=@AWK@
RANLIB=@RANLIB@
INSTALL=@INSTALL@
-PERL=@PERL@
SED=@SED@
ENT=@ENT@
XAUTH_PATH=@XAUTH_PATH@
LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
+LDFLAGS_NOPIE=-L. -Lopenbsd-compat/ @LDFLAGS_NOPIE@
EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
+MKDIR_P=@MKDIR_P@
+
+.SUFFIXES: .lo
+
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT)
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT)
+XMSS_OBJS=\
+ ssh-xmss.o \
+ sshkey-xmss.o \
+ xmss_commons.o \
+ xmss_fast.o \
+ xmss_hash.o \
+ xmss_hash_address.o \
+ xmss_wots.o
LIBOPENSSH_OBJS=\
ssh_api.o \
@@ -73,47 +88,72 @@ LIBOPENSSH_OBJS=\
sshbuf-misc.o \
sshbuf-getput-crypto.o \
krl.o \
- bitmap.o
+ bitmap.o \
+ ${XMSS_OBJS}
LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
- authfd.o authfile.o bufaux.o bufbn.o bufec.o buffer.o \
+ authfd.o authfile.o \
canohost.o channels.o cipher.o cipher-aes.o cipher-aesctr.o \
- cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \
- compat.o crc32.o deattack.o fatal.o hostfile.o \
- log.o match.o md-sha256.o moduli.o nchan.o packet.o opacket.o \
- readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
- atomicio.o key.o dispatch.o mac.o uidswap.o uuencode.o misc.o \
- monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
+ 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 \
+ atomicio.o dispatch.o mac.o misc.o utf8.o \
+ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \
+ ssh-ed25519-sk.o ssh-rsa.o dh.o \
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
ssh-pkcs11.o smult_curve25519_ref.o \
- poly1305.o chacha.o cipher-chachapoly.o \
- ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \
- sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \
+ poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \
+ ssh-ed25519.o digest-openssl.o digest-libc.o \
+ hmac.o sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \
kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
- kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
- kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o
+ kexgexc.o kexgexs.o \
+ sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \
+ sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \
+ sshbuf-io.o
+
+SKOBJS= ssh-sk-client.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
- sshconnect.o sshconnect1.o sshconnect2.o mux.o \
- roaming_common.o roaming_client.o
+ sshconnect.o sshconnect2.o mux.o $(SKOBJS)
-SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
+SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
audit.o audit-bsm.o audit-linux.o platform.o \
sshpty.o sshlogin.o servconf.o serverloop.o \
- auth.o auth1.o auth2.o auth-options.o session.o \
- auth-chall.o auth2-chall.o groupaccess.o \
- auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
+ auth.o auth2.o auth-options.o session.o \
+ auth2-chall.o groupaccess.o \
+ auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
auth2-none.o auth2-passwd.o auth2-pubkey.o \
- monitor_mm.o monitor.o monitor_wrap.o auth-krb5.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 \
- roaming_common.o roaming_serv.o \
sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
- sandbox-seccomp-filter.o sandbox-capsicum.o
+ sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
+ sandbox-solaris.o uidswap.o $(SKOBJS)
+
+SCP_OBJS= scp.o progressmeter.o
+
+SSHADD_OBJS= ssh-add.o $(SKOBJS)
+
+SSHAGENT_OBJS= ssh-agent.o ssh-pkcs11-client.o $(SKOBJS)
+
+SSHKEYGEN_OBJS= ssh-keygen.o sshsig.o $(SKOBJS)
+
+SSHKEYSIGN_OBJS=ssh-keysign.o readconf.o uidswap.o $(SKOBJS)
-MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
-MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
+P11HELPER_OBJS= ssh-pkcs11-helper.o ssh-pkcs11.o $(SKOBJS)
+
+SKHELPER_OBJS= ssh-sk-helper.o ssh-sk.o sk-usbhid.o
+
+SSHKEYSCAN_OBJS=ssh-keyscan.o $(SKOBJS)
+
+SFTPSERVER_OBJS=sftp-common.o sftp-server.o sftp-server-main.o
+
+SFTP_OBJS= sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
+
+MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-sk-helper.8.out sshd_config.5.out ssh_config.5.out
+MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-sk-helper.8 sshd_config.5 ssh_config.5
MANTYPE = @MANTYPE@
CONFIGFILES=sshd_config.out ssh_config.out moduli.out
@@ -142,11 +182,16 @@ FIXPATHSCMD = $(SED) $(PATHSUBS)
FIXALGORITHMSCMD= $(SHELL) $(srcdir)/fixalgorithms $(SED) \
@UNSUPPORTED_ALGORITHMS@
-all: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
+all: configure-check $(CONFIGFILES) $(MANPAGES) $(TARGETS)
$(LIBSSH_OBJS): Makefile.in config.h
$(SSHOBJS): Makefile.in config.h
$(SSHDOBJS): Makefile.in config.h
+configure-check: $(srcdir)/configure
+
+$(srcdir)/configure: configure.ac aclocal.m4
+ @echo "ERROR: configure is out of date; please run ${AUTORECONF} (and configure)" 1>&2
+ @exit 1
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
@@ -166,32 +211,35 @@ ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS)
$(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS)
-scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
- $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+scp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SCP_OBJS)
+ $(LD) -o $@ $(SCP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHADD_OBJS)
+ $(LD) -o $@ $(SSHADD_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
-ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHAGENT_OBJS)
+ $(LD) -o $@ $(SSHAGENT_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
-ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
- $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYGEN_OBJS)
+ $(LD) -o $@ $(SSHKEYGEN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
-ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSIGN_OBJS)
+ $(LD) -o $@ $(SSHKEYSIGN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
-ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o
- $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(P11HELPER_OBJS)
+ $(LD) -o $@ $(P11HELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
-ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
- $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS)
+ $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2)
-ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o
- $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS)
+ $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
-sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
- $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTPSERVER_OBJS)
+ $(LD) -o $@ $(SFTPSERVER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
-sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
- $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
+sftp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTP_OBJS)
+ $(LD) -o $@ $(SFTP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
# test driver for the loginrec code - not built by default
logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
@@ -218,28 +266,34 @@ $(CONFIGFILES): $(CONFIGFILES_IN)
moduli:
echo
-# special case target for umac128
-umac128.o: umac.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -o umac128.o -c $(srcdir)/umac.c \
- -DUMAC_OUTPUT_LEN=16 -Dumac_new=umac128_new \
- -Dumac_update=umac128_update -Dumac_final=umac128_final \
- -Dumac_delete=umac128_delete
-
clean: regressclean
- rm -f *.o *.a $(TARGETS) logintest config.cache config.log
+ rm -f *.o *.lo *.a $(TARGETS) logintest config.cache config.log
rm -f *.out core survey
+ rm -f regress/check-perm$(EXEEXT)
+ rm -f regress/mkdtemp$(EXEEXT)
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/sshbuf/test_sshbuf$(EXEEXT)
rm -f regress/unittests/sshkey/*.o
- rm -f regress/unittests/sshkey/test_sshkey
+ rm -f regress/unittests/sshkey/test_sshkey$(EXEEXT)
rm -f regress/unittests/bitmap/*.o
- rm -f regress/unittests/bitmap/test_bitmap
+ rm -f regress/unittests/bitmap/test_bitmap$(EXEEXT)
+ rm -f regress/unittests/conversion/*.o
+ rm -f regress/unittests/conversion/test_conversion$(EXEEXT)
rm -f regress/unittests/hostkeys/*.o
- rm -f regress/unittests/hostkeys/test_hostkeys
+ rm -f regress/unittests/hostkeys/test_hostkeys$(EXEEXT)
rm -f regress/unittests/kex/*.o
- rm -f regress/unittests/kex/test_kex
+ rm -f regress/unittests/kex/test_kex$(EXEEXT)
+ rm -f regress/unittests/match/*.o
+ rm -f regress/unittests/match/test_match$(EXEEXT)
+ rm -f regress/unittests/utf8/*.o
+ rm -f regress/unittests/utf8/test_utf8$(EXEEXT)
+ rm -f regress/misc/kexfuzz/*.o
+ rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT)
+ rm -f regress/misc/sk-dummy/*.o
+ rm -f regress/misc/sk-dummy/*.lo
+ rm -f regress/misc/sk-dummy/sk-dummy.so
(cd openbsd-compat && $(MAKE) clean)
distclean: regressclean
@@ -248,6 +302,8 @@ distclean: regressclean
rm -f Makefile buildpkg.sh config.h config.status
rm -f survey.sh openbsd-compat/regress/Makefile *~
rm -rf autom4te.cache
+ rm -f regress/check-perm
+ rm -f regress/mkdtemp
rm -f regress/unittests/test_helper/*.a
rm -f regress/unittests/test_helper/*.o
rm -f regress/unittests/sshbuf/*.o
@@ -256,10 +312,18 @@ distclean: regressclean
rm -f regress/unittests/sshkey/test_sshkey
rm -f regress/unittests/bitmap/*.o
rm -f regress/unittests/bitmap/test_bitmap
+ rm -f regress/unittests/conversion/*.o
+ rm -f regress/unittests/conversion/test_conversion
rm -f regress/unittests/hostkeys/*.o
rm -f regress/unittests/hostkeys/test_hostkeys
rm -f regress/unittests/kex/*.o
rm -f regress/unittests/kex/test_kex
+ rm -f regress/unittests/match/*.o
+ rm -f regress/unittests/match/test_match
+ rm -f regress/unittests/utf8/*.o
+ rm -f regress/unittests/utf8/test_utf8
+ rm -f regress/misc/kexfuzz/*.o
+ rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT)
(cd openbsd-compat && $(MAKE) distclean)
if test -d pkg ; then \
rm -fr pkg ; \
@@ -282,9 +346,27 @@ catman-do:
>$$base.0 ; \
done
-distprep: catman-do
+depend: depend-rebuild
+ rm -f .depend.bak
+
+depend-rebuild:
+ mv .depend .depend.old
+ rm -f config.h .depend
+ touch config.h .depend
+ makedepend -w1000 -Y. -f .depend *.c 2>/dev/null
+ (echo '# Automatically generated by makedepend.'; \
+ echo '# Run "make depend" to rebuild.'; sort .depend ) >.depend.tmp
+ mv .depend.tmp .depend
+ rm -f .depend.bak
+ mv .depend.old .depend.bak
+ rm -f config.h
+
+depend-check: depend-rebuild
+ cmp .depend .depend.bak || (echo .depend stale && exit 1)
+
+distprep: catman-do depend-check
$(AUTORECONF)
- -rm -rf autom4te.cache
+ -rm -rf autom4te.cache .depend.bak
install: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config
install-nokeys: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf
@@ -294,14 +376,13 @@ check-config:
-$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config
install-files:
- $(srcdir)/mkinstalldirs $(DESTDIR)$(bindir)
- $(srcdir)/mkinstalldirs $(DESTDIR)$(sbindir)
- $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)
- $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)1
- $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)5
- $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)8
- $(srcdir)/mkinstalldirs $(DESTDIR)$(libexecdir)
- (umask 022 ; $(srcdir)/mkinstalldirs $(DESTDIR)$(PRIVSEP_PATH))
+ $(MKDIR_P) $(DESTDIR)$(bindir)
+ $(MKDIR_P) $(DESTDIR)$(sbindir)
+ $(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)1
+ $(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)5
+ $(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)8
+ $(MKDIR_P) $(DESTDIR)$(libexecdir)
+ $(MKDIR_P) -m 0755 $(DESTDIR)$(PRIVSEP_PATH)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh$(EXEEXT) $(DESTDIR)$(bindir)/ssh$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) scp$(EXEEXT) $(DESTDIR)$(bindir)/scp$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-add$(EXEEXT) $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
@@ -311,6 +392,7 @@ install-files:
$(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
$(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
+ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
@@ -327,15 +409,10 @@ install-files:
$(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
$(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
$(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
- -rm -f $(DESTDIR)$(bindir)/slogin
- ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
- -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
- ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+ $(INSTALL) -m 644 ssh-sk-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8
install-sysconf:
- if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \
- $(srcdir)/mkinstalldirs $(DESTDIR)$(sysconfdir); \
- fi
+ $(MKDIR_P) $(DESTDIR)$(sysconfdir)
@if [ ! -f $(DESTDIR)$(sysconfdir)/ssh_config ]; then \
$(INSTALL) -m 644 ssh_config.out $(DESTDIR)$(sysconfdir)/ssh_config; \
else \
@@ -359,41 +436,16 @@ install-sysconf:
host-key: ssh-keygen$(EXEEXT)
@if [ -z "$(DESTDIR)" ] ; then \
- if [ -f "$(sysconfdir)/ssh_host_key" ] ; then \
- echo "$(sysconfdir)/ssh_host_key already exists, skipping." ; \
- else \
- ./ssh-keygen -t rsa1 -f $(sysconfdir)/ssh_host_key -N "" ; \
- fi ; \
- if [ -f $(sysconfdir)/ssh_host_dsa_key ] ; then \
- echo "$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \
- else \
- ./ssh-keygen -t dsa -f $(sysconfdir)/ssh_host_dsa_key -N "" ; \
- fi ; \
- if [ -f $(sysconfdir)/ssh_host_rsa_key ] ; then \
- echo "$(sysconfdir)/ssh_host_rsa_key already exists, skipping." ; \
- else \
- ./ssh-keygen -t rsa -f $(sysconfdir)/ssh_host_rsa_key -N "" ; \
- fi ; \
- if [ -f $(sysconfdir)/ssh_host_ed25519_key ] ; then \
- echo "$(sysconfdir)/ssh_host_ed25519_key already exists, skipping." ; \
- else \
- ./ssh-keygen -t ed25519 -f $(sysconfdir)/ssh_host_ed25519_key -N "" ; \
- fi ; \
- if [ -z "@COMMENT_OUT_ECC@" ] ; then \
- if [ -f $(sysconfdir)/ssh_host_ecdsa_key ] ; then \
- echo "$(sysconfdir)/ssh_host_ecdsa_key already exists, skipping." ; \
- else \
- ./ssh-keygen -t ecdsa -f $(sysconfdir)/ssh_host_ecdsa_key -N "" ; \
- fi ; \
- fi ; \
- fi ;
+ ./ssh-keygen -A; \
+ fi
-host-key-force: ssh-keygen$(EXEEXT)
- ./ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N ""
+host-key-force: ssh-keygen$(EXEEXT) ssh$(EXEEXT)
./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N ""
./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N ""
./ssh-keygen -t ed25519 -f $(DESTDIR)$(sysconfdir)/ssh_host_ed25519_key -N ""
- test -z "@COMMENT_OUT_ECC@" && ./ssh-keygen -t ecdsa -f $(DESTDIR)$(sysconfdir)/ssh_host_ecdsa_key -N ""
+ if ./ssh -Q key | grep ecdsa >/dev/null ; then \
+ ./ssh-keygen -t ecdsa -f $(DESTDIR)$(sysconfdir)/ssh_host_ecdsa_key -N ""; \
+ fi
uninstallall: uninstall
-rm -f $(DESTDIR)$(sysconfdir)/ssh_config
@@ -407,7 +459,6 @@ uninstallall: uninstall
-rmdir $(DESTDIR)$(libexecdir)
uninstall:
- -rm -f $(DESTDIR)$(bindir)/slogin
-rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
@@ -419,6 +470,7 @@ uninstall:
-rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
-rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
-rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
+ -rm -f $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT)
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
@@ -430,36 +482,43 @@ uninstall:
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
- -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8
regress-prep:
- [ -d `pwd`/regress ] || mkdir -p `pwd`/regress
- [ -d `pwd`/regress/unittests ] || mkdir -p `pwd`/regress/unittests
- [ -d `pwd`/regress/unittests/test_helper ] || \
- mkdir -p `pwd`/regress/unittests/test_helper
- [ -d `pwd`/regress/unittests/sshbuf ] || \
- mkdir -p `pwd`/regress/unittests/sshbuf
- [ -d `pwd`/regress/unittests/sshkey ] || \
- mkdir -p `pwd`/regress/unittests/sshkey
- [ -d `pwd`/regress/unittests/bitmap ] || \
- mkdir -p `pwd`/regress/unittests/bitmap
- [ -d `pwd`/regress/unittests/hostkeys ] || \
- mkdir -p `pwd`/regress/unittests/hostkeys
- [ -d `pwd`/regress/unittests/kex ] || \
- mkdir -p `pwd`/regress/unittests/kex
+ $(MKDIR_P) `pwd`/regress/unittests/test_helper
+ $(MKDIR_P) `pwd`/regress/unittests/sshbuf
+ $(MKDIR_P) `pwd`/regress/unittests/sshkey
+ $(MKDIR_P) `pwd`/regress/unittests/bitmap
+ $(MKDIR_P) `pwd`/regress/unittests/conversion
+ $(MKDIR_P) `pwd`/regress/unittests/hostkeys
+ $(MKDIR_P) `pwd`/regress/unittests/kex
+ $(MKDIR_P) `pwd`/regress/unittests/match
+ $(MKDIR_P) `pwd`/regress/unittests/utf8
+ $(MKDIR_P) `pwd`/regress/misc/kexfuzz
+ $(MKDIR_P) `pwd`/regress/misc/sk-dummy
[ -f `pwd`/regress/Makefile ] || \
ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile
-regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \
+REGRESSLIBS=libssh.a $(LIBCOMPAT)
+
+regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
-regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \
+regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c $(REGRESSLIBS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/setuid-allowed.c \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
-regress/netcat$(EXEEXT): $(srcdir)/regress/netcat.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \
+regress/netcat$(EXEEXT): $(srcdir)/regress/netcat.c $(REGRESSLIBS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/netcat.c \
+ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+
+regress/check-perm$(EXEEXT): $(srcdir)/regress/check-perm.c $(REGRESSLIBS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/check-perm.c \
+ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+
+regress/mkdtemp$(EXEEXT): $(srcdir)/regress/mkdtemp.c $(REGRESSLIBS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/mkdtemp.c \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_HELPER_OBJS=\
@@ -491,7 +550,8 @@ UNITTESTS_TEST_SSHKEY_OBJS=\
regress/unittests/sshkey/tests.o \
regress/unittests/sshkey/common.o \
regress/unittests/sshkey/test_file.o \
- regress/unittests/sshkey/test_sshkey.o
+ regress/unittests/sshkey/test_sshkey.o \
+ $(SKOBJS)
regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
@@ -508,10 +568,20 @@ 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_CONVERSION_OBJS=\
+ regress/unittests/conversion/tests.o
+
+regress/unittests/conversion/test_conversion$(EXEEXT): \
+ ${UNITTESTS_TEST_CONVERSION_OBJS} \
+ regress/unittests/test_helper/libtest_helper.a libssh.a
+ $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_CONVERSION_OBJS) \
+ regress/unittests/test_helper/libtest_helper.a \
+ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+
UNITTESTS_TEST_KEX_OBJS=\
regress/unittests/kex/tests.o \
regress/unittests/kex/test_kex.o \
- roaming_dummy.o
+ $(SKOBJS)
regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
@@ -521,7 +591,8 @@ regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \
UNITTESTS_TEST_HOSTKEYS_OBJS=\
regress/unittests/hostkeys/tests.o \
- regress/unittests/hostkeys/test_iterate.o
+ regress/unittests/hostkeys/test_iterate.o \
+ $(SKOBJS)
regress/unittests/hostkeys/test_hostkeys$(EXEEXT): \
${UNITTESTS_TEST_HOSTKEYS_OBJS} \
@@ -530,34 +601,83 @@ regress/unittests/hostkeys/test_hostkeys$(EXEEXT): \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
-REGRESS_BINARIES=\
+UNITTESTS_TEST_MATCH_OBJS=\
+ regress/unittests/match/tests.o
+
+regress/unittests/match/test_match$(EXEEXT): \
+ ${UNITTESTS_TEST_MATCH_OBJS} \
+ regress/unittests/test_helper/libtest_helper.a libssh.a
+ $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_MATCH_OBJS) \
+ regress/unittests/test_helper/libtest_helper.a \
+ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+
+UNITTESTS_TEST_UTF8_OBJS=\
+ regress/unittests/utf8/tests.o
+
+regress/unittests/utf8/test_utf8$(EXEEXT): \
+ ${UNITTESTS_TEST_UTF8_OBJS} \
+ regress/unittests/test_helper/libtest_helper.a libssh.a
+ $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_UTF8_OBJS) \
+ regress/unittests/test_helper/libtest_helper.a \
+ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+
+MISC_KEX_FUZZ_OBJS=\
+ regress/misc/kexfuzz/kexfuzz.o \
+ $(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 \
+ regress/misc/sk-dummy/fatal.lo \
+ ed25519.lo hash.lo ge25519.lo fe25519.lo sc25519.lo verify.lo
+
+SK_DUMMY_LIBRARY=@SK_DUMMY_LIBRARY@
+
+.c.lo: Makefile.in config.h
+ $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $< -o $@
+
+regress/misc/sk-dummy/sk-dummy.so: $(SK_DUMMY_OBJS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -shared -o $@ $(SK_DUMMY_OBJS) \
+ -L. -Lopenbsd-compat -lopenbsd-compat $(LDFLAGS_NOPIE) $(LIBS)
+
+regress-binaries: regress-prep $(LIBCOMPAT) \
regress/modpipe$(EXEEXT) \
regress/setuid-allowed$(EXEEXT) \
regress/netcat$(EXEEXT) \
+ regress/check-perm$(EXEEXT) \
+ regress/mkdtemp$(EXEEXT) \
+ $(SK_DUMMY_LIBRARY)
+
+regress-unit-binaries: regress-prep $(REGRESSLIBS) \
regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \
regress/unittests/sshkey/test_sshkey$(EXEEXT) \
regress/unittests/bitmap/test_bitmap$(EXEEXT) \
+ regress/unittests/conversion/test_conversion$(EXEEXT) \
regress/unittests/hostkeys/test_hostkeys$(EXEEXT) \
- regress/unittests/kex/test_kex$(EXEEXT)
+ regress/unittests/kex/test_kex$(EXEEXT) \
+ regress/unittests/match/test_match$(EXEEXT) \
+ regress/unittests/utf8/test_utf8$(EXEEXT) \
+ regress/misc/kexfuzz/kexfuzz$(EXEEXT)
-tests interop-tests t-exec: regress-prep $(TARGETS) $(REGRESS_BINARIES)
+tests: file-tests t-exec interop-tests unit
+ echo all tests passed
+
+unit: regress-unit-binaries
+ BUILDDIR=`pwd`; \
+ cd $(srcdir)/regress || exit $$?; \
+ $(MAKE) \
+ .OBJDIR="$${BUILDDIR}/regress" \
+ .CURDIR="`pwd`" \
+ $@ && echo $@ tests passed
+
+interop-tests t-exec file-tests: regress-prep regress-binaries $(TARGETS)
BUILDDIR=`pwd`; \
- TEST_SSH_SCP="$${BUILDDIR}/scp"; \
- TEST_SSH_SSH="$${BUILDDIR}/ssh"; \
- TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \
- TEST_SSH_SSHAGENT="$${BUILDDIR}/ssh-agent"; \
- TEST_SSH_SSHADD="$${BUILDDIR}/ssh-add"; \
- TEST_SSH_SSHKEYGEN="$${BUILDDIR}/ssh-keygen"; \
- TEST_SSH_SSHPKCS11HELPER="$${BUILDDIR}/ssh-pkcs11-helper"; \
- TEST_SSH_SSHKEYSCAN="$${BUILDDIR}/ssh-keyscan"; \
- TEST_SSH_SFTP="$${BUILDDIR}/sftp"; \
- TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server"; \
- TEST_SSH_PLINK="plink"; \
- TEST_SSH_PUTTYGEN="puttygen"; \
- TEST_SSH_CONCH="conch"; \
- TEST_SSH_IPV6="@TEST_SSH_IPV6@" ; \
- TEST_SSH_ECC="@TEST_SSH_ECC@" ; \
cd $(srcdir)/regress || exit $$?; \
+ EGREP='@EGREP@' \
$(MAKE) \
.OBJDIR="$${BUILDDIR}/regress" \
.CURDIR="`pwd`" \
@@ -565,24 +685,28 @@ tests interop-tests t-exec: regress-prep $(TARGETS) $(REGRESS_BINARIES)
OBJ="$${BUILDDIR}/regress/" \
PATH="$${BUILDDIR}:$${PATH}" \
TEST_ENV=MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \
- TEST_SSH_SCP="$${TEST_SSH_SCP}" \
- TEST_SSH_SSH="$${TEST_SSH_SSH}" \
- TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \
- TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT}" \
- TEST_SSH_SSHADD="$${TEST_SSH_SSHADD}" \
- TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN}" \
- TEST_SSH_SSHPKCS11HELPER="$${TEST_SSH_SSHPKCS11HELPER}" \
- TEST_SSH_SSHKEYSCAN="$${TEST_SSH_SSHKEYSCAN}" \
- TEST_SSH_SFTP="$${TEST_SSH_SFTP}" \
- TEST_SSH_SFTPSERVER="$${TEST_SSH_SFTPSERVER}" \
- TEST_SSH_PLINK="$${TEST_SSH_PLINK}" \
- TEST_SSH_PUTTYGEN="$${TEST_SSH_PUTTYGEN}" \
- TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \
- TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \
- TEST_SSH_ECC="$${TEST_SSH_ECC}" \
+ TEST_MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \
+ TEST_SSH_SCP="$${BUILDDIR}/scp" \
+ TEST_SSH_SSH="$${BUILDDIR}/ssh" \
+ TEST_SSH_SSHD="$${BUILDDIR}/sshd" \
+ TEST_SSH_SSHAGENT="$${BUILDDIR}/ssh-agent" \
+ TEST_SSH_SSHADD="$${BUILDDIR}/ssh-add" \
+ TEST_SSH_SSHKEYGEN="$${BUILDDIR}/ssh-keygen" \
+ TEST_SSH_SSHPKCS11HELPER="$${BUILDDIR}/ssh-pkcs11-helper" \
+ TEST_SSH_SSHKEYSCAN="$${BUILDDIR}/ssh-keyscan" \
+ TEST_SSH_SFTP="$${BUILDDIR}/sftp" \
+ TEST_SSH_PKCS11_HELPER="$${BUILDDIR}/ssh-pkcs11-helper" \
+ TEST_SSH_SK_HELPER="$${BUILDDIR}/ssh-sk-helper" \
+ TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server" \
+ TEST_SSH_PLINK="plink" \
+ TEST_SSH_PUTTYGEN="puttygen" \
+ TEST_SSH_CONCH="conch" \
+ TEST_SSH_IPV6="@TEST_SSH_IPV6@" \
+ TEST_SSH_UTF8="@TEST_SSH_UTF8@" \
+ TEST_SSH_ECC="@TEST_SSH_ECC@" \
TEST_SHELL="${TEST_SHELL}" \
EXEEXT="$(EXEEXT)" \
- $@ && echo all tests passed
+ $@ && echo all $@ passed
compat-tests: $(LIBCOMPAT)
(cd openbsd-compat/regress && $(MAKE))
@@ -605,3 +729,5 @@ package: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
if [ "@MAKE_PACKAGE_SUPPORTED@" = yes ]; then \
sh buildpkg.sh; \
fi
+
+# @DEPEND@
diff --git a/OVERVIEW b/OVERVIEW
index 2e1cc0ba..cec7cd75 100644
--- a/OVERVIEW
+++ b/OVERVIEW
@@ -23,9 +23,8 @@ these programs.
- These provide an arbitrary size buffer, where data can be appended.
Data can be consumed from either end. The code is used heavily
- throughout ssh. The basic buffer manipulation functions are in
- buffer.c (header buffer.h), and additional code to manipulate specific
- data types is in bufaux.c.
+ throughout ssh. The buffer manipulation functions are in
+ sshbuf*.c (header sshbuf.h).
Compression Library
@@ -35,11 +34,12 @@ these programs.
- Ssh contains several encryption algorithms. These are all
accessed through the cipher.h interface. The interface code is
- in cipher.c, and the implementations are in libc.
+ in cipher.c, and the implementations are either in libc or
+ LibreSSL.
Multiple Precision Integer Library
- - Uses the SSLeay BIGNUM sublibrary.
+ - Uses the LibreSSL BIGNUM sublibrary.
Random Numbers
@@ -62,11 +62,11 @@ these programs.
code in packet.c does not concern itself with packet types or their
execution; it contains code to build packets, to receive them and
extract data from them, and the code to compress and/or encrypt
- packets. CRC code comes from crc32.c.
+ packets.
- The code in packet.c calls the buffer manipulation routines
- (buffer.c, bufaux.c), compression routines (compress.c, zlib),
- and the encryption routines.
+ (buffer.c, bufaux.c), compression routines (zlib), and the
+ encryption routines.
X11, TCP/IP, and Agent forwarding
@@ -106,12 +106,6 @@ these programs.
calls client_loop in clientloop.c. This does the real work for
the session.
- - The client is suid root. It tries to temporarily give up this
- rights while reading the configuration data. The root
- privileges are only used to make the connection (from a
- privileged socket). Any extra privileges are dropped before
- calling ssh_login.
-
Pseudo-tty manipulation and tty modes
- Code to allocate and use a pseudo tty is in pty.c. Code to
@@ -165,4 +159,4 @@ these programs.
uidswap.c uid-swapping
xmalloc.c "safe" malloc routines
-$OpenBSD: OVERVIEW,v 1.11 2006/08/03 03:34:41 deraadt Exp $
+$OpenBSD: OVERVIEW,v 1.15 2018/10/23 05:56:35 djm Exp $
diff --git a/PROTOCOL b/PROTOCOL
index 91bfe270..c702fca4 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -4,7 +4,7 @@ protocol.
Note that OpenSSH's sftp and sftp-server implement revision 3 of the SSH
filexfer protocol described in:
-http://www.openssh.com/txt/draft-ietf-secsh-filexfer-02.txt
+https://www.openssh.com/txt/draft-ietf-secsh-filexfer-02.txt
Newer versions of the draft will not be supported, though some features
are individually implemented as extensions described below.
@@ -20,7 +20,7 @@ This is a new transport-layer MAC method using the UMAC algorithm
(rfc4418). This method is identical to the "umac-64" method documented
in:
-http://www.openssh.com/txt/draft-miller-secsh-umac-01.txt
+https://www.openssh.com/txt/draft-miller-secsh-umac-01.txt
1.2. transport: Protocol 2 compression algorithm "zlib@openssh.com"
@@ -31,10 +31,10 @@ avoids exposing compression code to attacks from unauthenticated users.
The method is documented in:
-http://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt
+https://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt
-1.3. transport: New public key algorithms "ssh-rsa-cert-v00@openssh.com",
- "ssh-dsa-cert-v00@openssh.com",
+1.3. transport: New public key algorithms "ssh-rsa-cert-v01@openssh.com",
+ "ssh-dsa-cert-v01@openssh.com",
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
"ecdsa-sha2-nistp384-cert-v01@openssh.com" and
"ecdsa-sha2-nistp521-cert-v01@openssh.com"
@@ -175,7 +175,7 @@ whitelisted to receive this message upon request.
OpenSSH supports layer 2 and layer 3 tunnelling via the "tun@openssh.com"
channel type. This channel type supports forwarding of network packets
-with datagram boundaries intact between endpoints equipped with
+with datagram boundaries intact between endpoints equipped with
interfaces like the BSD tun(4) device. Tunnel forwarding channels are
requested by the client with the following packet:
@@ -194,7 +194,7 @@ layer 2 frames or layer 3 packets. It may take one of the following values:
SSH_TUNMODE_ETHERNET 2 /* layer 2 frames */
The "tunnel unit number" specifies the remote interface number, or may
-be 0x7fffffff to allow the server to automatically chose an interface. A
+be 0x7fffffff to allow the server to automatically choose an interface. A
server that is not willing to open a client-specified unit should refuse
the request with a SSH_MSG_CHANNEL_OPEN_FAILURE error. On successful
open, the server should reply with SSH_MSG_CHANNEL_OPEN_SUCCESS.
@@ -247,7 +247,8 @@ to request that the server make a connection to a Unix domain socket.
uint32 initial window size
uint32 maximum packet size
string socket path
- string reserved for future use
+ string reserved
+ uint32 reserved
Similar to forwarded-tcpip, forwarded-streamlocal is sent by the
server when the client has previously send the server a streamlocal-forward
@@ -294,10 +295,14 @@ has completed.
string[] hostkeys
Upon receiving this message, a client should check which of the
-supplied host keys are present in known_hosts. For keys that are
-not present, it should send a "hostkeys-prove@openssh.com" message
-to request the server prove ownership of the private half of the
-key.
+supplied host keys are present in known_hosts.
+
+Note that the server may send key types that the client does not
+support. The client should disregard such keys if they are received.
+
+If the client identifies any keys that are not present for the host,
+it should send a "hostkeys-prove@openssh.com" message to request the
+server prove ownership of the private half of the key.
byte SSH_MSG_GLOBAL_REQUEST
string "hostkeys-prove-00@openssh.com"
@@ -329,6 +334,13 @@ a server may offer multiple keys of the same type for a period (to
give clients an opportunity to learn them using this extension) before
removing the deprecated key from those offered.
+2.6. connection: SIGINFO support for "signal" channel request
+
+The SSH channels protocol (RFC4254 section 6.9) supports sending a
+signal to a session attached to a channel. OpenSSH supports one
+extension signal "INFO@openssh.com" that allows sending SIGINFO on
+BSD-derived systems.
+
3. SFTP protocol changes
3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
@@ -423,7 +435,7 @@ The values of the f_flag bitmask are as follows:
Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are
advertised in the SSH_FXP_VERSION hello with version "2".
-10. sftp: Extension request "hardlink@openssh.com"
+3.5. sftp: Extension request "hardlink@openssh.com"
This request is for creating a hard link to a regular file. This
request is implemented as a SSH_FXP_EXTENDED request with the
@@ -439,7 +451,7 @@ link(oldpath, newpath) and will respond with a SSH_FXP_STATUS message.
This extension is advertised in the SSH_FXP_VERSION hello with version
"1".
-10. sftp: Extension request "fsync@openssh.com"
+3.6. sftp: Extension request "fsync@openssh.com"
This request asks the server to call fsync(2) on an open file handle.
@@ -453,4 +465,35 @@ respond with a SSH_FXP_STATUS message.
This extension is advertised in the SSH_FXP_VERSION hello with version
"1".
-$OpenBSD: PROTOCOL,v 1.27 2015/02/20 22:17:21 djm Exp $
+4. Miscellaneous changes
+
+4.1 Public key format
+
+OpenSSH public keys, as generated by ssh-keygen(1) and appearing in
+authorized_keys files, are formatted as a single line of text consisting
+of the public key algorithm name followed by a base64-encoded key blob.
+The public key blob (before base64 encoding) is the same format used for
+the encoding of public keys sent on the wire: as described in RFC4253
+section 6.6 for RSA and DSA keys, RFC5656 section 3.1 for ECDSA keys
+and the "New public key formats" section of PROTOCOL.certkeys for the
+OpenSSH certificate formats.
+
+4.2 Private key format
+
+OpenSSH private keys, as generated by ssh-keygen(1) use the format
+described in PROTOCOL.key by default. As a legacy option, PEM format
+(RFC7468) private keys are also supported for RSA, DSA and ECDSA keys
+and were the default format before OpenSSH 7.8.
+
+4.3 KRL format
+
+OpenSSH supports a compact format for Key Revocation Lists (KRLs). This
+format is described in the PROTOCOL.krl file.
+
+4.4 Connection multiplexing
+
+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 $
diff --git a/PROTOCOL.agent b/PROTOCOL.agent
index 3fcaa14d..da338194 100644
--- a/PROTOCOL.agent
+++ b/PROTOCOL.agent
@@ -1,560 +1,5 @@
-This describes the protocol used by OpenSSH's ssh-agent.
+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:
-OpenSSH's agent supports managing keys for the standard SSH protocol
-2 as well as the legacy SSH protocol 1. Support for these key types
-is almost completely disjoint - in all but a few cases, operations on
-protocol 2 keys cannot see or affect protocol 1 keys and vice-versa.
-
-Protocol 1 and protocol 2 keys are separated because of the differing
-cryptographic usage: protocol 1 private RSA keys are used to decrypt
-challenges that were encrypted with the corresponding public key,
-whereas protocol 2 RSA private keys are used to sign challenges with
-a private key for verification with the corresponding public key. It
-is considered unsound practice to use the same key for signing and
-encryption.
-
-With a couple of exceptions, the protocol message names used in this
-document indicate which type of key the message relates to. SSH_*
-messages refer to protocol 1 keys only. SSH2_* messages refer to
-protocol 2 keys. Furthermore, the names also indicate whether the
-message is a request to the agent (*_AGENTC_*) or a reply from the
-agent (*_AGENT_*). Section 3 below contains the mapping of the
-protocol message names to their integer values.
-
-1. Data types
-
-Because of support for legacy SSH protocol 1 keys, OpenSSH's agent
-protocol makes use of some data types not defined in RFC 4251.
-
-1.1 uint16
-
-The "uint16" data type is a simple MSB-first 16 bit unsigned integer
-encoded in two bytes.
-
-1.2 mpint1
-
-The "mpint1" type represents an arbitrary precision integer (bignum).
-Its format is as follows:
-
- uint16 bits
- byte[(bits + 7) / 8] bignum
-
-"bignum" contains an unsigned arbitrary precision integer encoded as
-eight bits per byte in big-endian (MSB first) format.
-
-Note the difference between the "mpint1" encoding and the "mpint"
-encoding defined in RFC 4251. Also note that the length of the encoded
-integer is specified in bits, not bytes and that the byte length of
-the integer must be calculated by rounding up the number of bits to the
-nearest eight.
-
-2. Protocol Messages
-
-All protocol messages are prefixed with their length in bytes, encoded
-as a 32 bit unsigned integer. Specifically:
-
- uint32 message_length
- byte[message_length] message
-
-The following message descriptions refer only to the content the
-"message" field.
-
-2.1 Generic server responses
-
-The following generic messages may be sent by the server in response to
-requests from the client. On success the agent may reply either with:
-
- byte SSH_AGENT_SUCCESS
-
-or a request-specific success message.
-
-On failure, the agent may reply with:
-
- byte SSH_AGENT_FAILURE
-
-SSH_AGENT_FAILURE messages are also sent in reply to unknown request
-types.
-
-2.2 Adding keys to the agent
-
-Keys are added to the agent using the SSH_AGENTC_ADD_RSA_IDENTITY and
-SSH2_AGENTC_ADD_IDENTITY requests for protocol 1 and protocol 2 keys
-respectively.
-
-Two variants of these requests are SSH_AGENTC_ADD_RSA_ID_CONSTRAINED
-and SSH2_AGENTC_ADD_ID_CONSTRAINED - these add keys with optional
-"constraints" on their usage.
-
-OpenSSH may be built with support for keys hosted on a smartcard
-or other hardware security module. These keys may be added
-to the agent using the SSH_AGENTC_ADD_SMARTCARD_KEY and
-SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED requests.
-
-2.2.1 Key constraints
-
-The OpenSSH agent supports some basic optional constraints on key usage.
-At present there are two constraints defined.
-
-The first constraint limits the validity duration of a key. It is
-encoded as:
-
- byte SSH_AGENT_CONSTRAIN_LIFETIME
- uint32 seconds
-
-Where "seconds" contains the number of seconds that the key shall remain
-valid measured from the moment that the agent receives it. After the
-validity period has expired, OpenSSH's agent will erase these keys from
-memory.
-
-The second constraint requires the agent to seek explicit user
-confirmation before performing private key operations with the loaded
-key. This constraint is encoded as:
-
- byte SSH_AGENT_CONSTRAIN_CONFIRM
-
-Zero or more constraints may be specified when adding a key with one
-of the *_CONSTRAINED requests. Multiple constraints are appended
-consecutively to the end of the request:
-
- byte constraint1_type
- .... constraint1_data
- byte constraint2_type
- .... constraint2_data
- ....
- byte constraintN_type
- .... constraintN_data
-
-Such a sequence of zero or more constraints will be referred to below
-as "constraint[]". Agents may determine whether there are constraints
-by checking whether additional data exists in the "add key" request
-after the key data itself. OpenSSH will refuse to add a key if it
-contains unknown constraints.
-
-2.2.2 Add protocol 1 key
-
-A client may add a protocol 1 key to an agent with the following
-request:
-
- byte SSH_AGENTC_ADD_RSA_IDENTITY or
- SSH_AGENTC_ADD_RSA_ID_CONSTRAINED
- uint32 ignored
- mpint1 rsa_n
- mpint1 rsa_e
- mpint1 rsa_d
- mpint1 rsa_iqmp
- mpint1 rsa_q
- mpint1 rsa_p
- string key_comment
- constraint[] key_constraints
-
-Note that there is some redundancy in the key parameters; a key could be
-fully specified using just rsa_q, rsa_p and rsa_e at the cost of extra
-computation.
-
-"key_constraints" may only be present if the request type is
-SSH_AGENTC_ADD_RSA_ID_CONSTRAINED.
-
-The agent will reply with a SSH_AGENT_SUCCESS if the key has been
-successfully added or a SSH_AGENT_FAILURE if an error occurred.
-
-2.2.3 Add protocol 2 key
-
-The OpenSSH agent supports DSA, ECDSA and RSA keys for protocol 2. DSA
-keys may be added using the following request
-
- byte SSH2_AGENTC_ADD_IDENTITY or
- SSH2_AGENTC_ADD_ID_CONSTRAINED
- string "ssh-dss"
- mpint dsa_p
- mpint dsa_q
- mpint dsa_g
- mpint dsa_public_key
- mpint dsa_private_key
- string key_comment
- constraint[] key_constraints
-
-DSA certificates may be added with:
- byte SSH2_AGENTC_ADD_IDENTITY or
- SSH2_AGENTC_ADD_ID_CONSTRAINED
- string "ssh-dss-cert-v00@openssh.com"
- string certificate
- mpint dsa_private_key
- string key_comment
- constraint[] key_constraints
-
-ECDSA keys may be added using the following request
-
- byte SSH2_AGENTC_ADD_IDENTITY or
- SSH2_AGENTC_ADD_ID_CONSTRAINED
- string "ecdsa-sha2-nistp256" |
- "ecdsa-sha2-nistp384" |
- "ecdsa-sha2-nistp521"
- string ecdsa_curve_name
- string ecdsa_public_key
- mpint ecdsa_private
- string key_comment
- constraint[] key_constraints
-
-ECDSA certificates may be added with:
- byte SSH2_AGENTC_ADD_IDENTITY or
- SSH2_AGENTC_ADD_ID_CONSTRAINED
- string "ecdsa-sha2-nistp256-cert-v01@openssh.com" |
- "ecdsa-sha2-nistp384-cert-v01@openssh.com" |
- "ecdsa-sha2-nistp521-cert-v01@openssh.com"
- string certificate
- mpint ecdsa_private_key
- string key_comment
- constraint[] key_constraints
-
-RSA keys may be added with this request:
-
- byte SSH2_AGENTC_ADD_IDENTITY or
- SSH2_AGENTC_ADD_ID_CONSTRAINED
- string "ssh-rsa"
- mpint rsa_n
- mpint rsa_e
- mpint rsa_d
- mpint rsa_iqmp
- mpint rsa_p
- mpint rsa_q
- string key_comment
- constraint[] key_constraints
-
-RSA certificates may be added with this request:
-
- byte SSH2_AGENTC_ADD_IDENTITY or
- SSH2_AGENTC_ADD_ID_CONSTRAINED
- string "ssh-rsa-cert-v00@openssh.com"
- string certificate
- mpint rsa_d
- mpint rsa_iqmp
- mpint rsa_p
- mpint rsa_q
- string key_comment
- constraint[] key_constraints
-
-Note that the 'rsa_p' and 'rsa_q' parameters are sent in the reverse
-order to the protocol 1 add keys message. As with the corresponding
-protocol 1 "add key" request, the private key is overspecified to avoid
-redundant processing.
-
-For DSA, ECDSA and RSA key add requests, "key_constraints" may only be
-present if the request type is SSH2_AGENTC_ADD_ID_CONSTRAINED.
-
-The agent will reply with a SSH_AGENT_SUCCESS if the key has been
-successfully added or a SSH_AGENT_FAILURE if an error occurred.
-
-2.2.4 Loading keys from a smartcard
-
-The OpenSSH agent may have optional smartcard support built in to it. If
-so, it supports an operation to load keys from a smartcard. Technically,
-only the public components of the keys are loaded into the agent so
-this operation really arranges for future private key operations to be
-delegated to the smartcard.
-
- byte SSH_AGENTC_ADD_SMARTCARD_KEY or
- SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED
- string reader_id
- string pin
- constraint[] key_constraints
-
-"reader_id" is an identifier to a smartcard reader and "pin"
-is a PIN or passphrase used to unlock the private key(s) on the
-device. "key_constraints" may only be present if the request type is
-SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED.
-
-This operation may load all SSH keys that are unlocked using the
-"pin" on the specified reader. The type of key loaded (protocol 1
-or protocol 2) will be specified by the smartcard itself, it is not
-client-specified.
-
-The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have
-been successfully loaded or a SSH_AGENT_FAILURE if an error occurred.
-The agent will also return SSH_AGENT_FAILURE if it does not support
-smartcards.
-
-2.3 Removing multiple keys
-
-A client may request that an agent delete all protocol 1 keys using the
-following request:
-
- byte SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES
-
-This message requests the deletion of all protocol 2 keys:
-
- byte SSH2_AGENTC_REMOVE_ALL_IDENTITIES
-
-On success, the agent will delete all keys of the requested type and
-reply with a SSH_AGENT_SUCCESS message. If an error occurred, the agent
-will reply with SSH_AGENT_FAILURE.
-
-Note that, to delete all keys (both protocol 1 and 2), a client
-must send both a SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES and a
-SSH2_AGENTC_REMOVE_ALL_IDENTITIES request.
-
-2.4 Removing specific keys
-
-2.4.1 Removing a protocol 1 key
-
-Removal of a protocol 1 key may be requested with the following message:
-
- byte SSH_AGENTC_REMOVE_RSA_IDENTITY
- uint32 key_bits
- mpint1 rsa_e
- mpint1 rsa_n
-
-Note that key_bits is strictly redundant, as it may be inferred by the
-length of rsa_n.
-
-The agent will delete any private key matching the specified public key
-and return SSH_AGENT_SUCCESS. If no such key was found, the agent will
-return SSH_AGENT_FAILURE.
-
-2.4.2 Removing a protocol 2 key
-
-Protocol 2 keys may be removed with the following request:
-
- byte SSH2_AGENTC_REMOVE_IDENTITY
- string key_blob
-
-Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
-Algorithms" for any of the supported protocol 2 key types.
-
-The agent will delete any private key matching the specified public key
-and return SSH_AGENT_SUCCESS. If no such key was found, the agent will
-return SSH_AGENT_FAILURE.
-
-2.4.3 Removing keys loaded from a smartcard
-
-A client may request that a server remove one or more smartcard-hosted
-keys using this message:
-
- byte SSH_AGENTC_REMOVE_SMARTCARD_KEY
- string reader_id
- string pin
-
-"reader_id" the an identifier to a smartcard reader and "pin" is a PIN
-or passphrase used to unlock the private key(s) on the device.
-
-When this message is received, and if the agent supports
-smartcard-hosted keys, it will delete all keys that are hosted on the
-specified smartcard that may be accessed with the given "pin".
-
-The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have
-been successfully removed or a SSH_AGENT_FAILURE if an error occurred.
-The agent will also return SSH_AGENT_FAILURE if it does not support
-smartcards.
-
-2.5 Requesting a list of known keys
-
-An agent may be requested to list which keys it holds. Different
-requests exist for protocol 1 and protocol 2 keys.
-
-2.5.1 Requesting a list of protocol 1 keys
-
-To request a list of protocol 1 keys that are held in the agent, a
-client may send the following message:
-
- byte SSH_AGENTC_REQUEST_RSA_IDENTITIES
-
-The agent will reply with the following message:
-
- byte SSH_AGENT_RSA_IDENTITIES_ANSWER
- uint32 num_keys
-
-Followed by zero or more consecutive keys, encoded as:
-
- uint32 bits
- mpint1 rsa_e
- mpint1 rsa_n
- string key_comment
-
-2.5.2 Requesting a list of protocol 2 keys
-
-A client may send the following message to request a list of
-protocol 2 keys that are stored in the agent:
-
- byte SSH2_AGENTC_REQUEST_IDENTITIES
-
-The agent will reply with the following message header:
-
- byte SSH2_AGENT_IDENTITIES_ANSWER
- uint32 num_keys
-
-Followed by zero or more consecutive keys, encoded as:
-
- string key_blob
- string key_comment
-
-Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
-Algorithms" for any of the supported protocol 2 key types.
-
-2.6 Private key operations
-
-The purpose of the agent is to perform private key operations, such as
-signing and encryption without requiring a passphrase to unlock the
-key and without allowing the private key itself to be exposed. There
-are separate requests for the protocol 1 and protocol 2 private key
-operations.
-
-2.6.1 Protocol 1 private key challenge
-
-The private key operation used in version 1 of the SSH protocol is
-decrypting a challenge that has been encrypted with a public key.
-It may be requested using this message:
-
- byte SSH_AGENTC_RSA_CHALLENGE
- uint32 ignored
- mpint1 rsa_e
- mpint1 rsa_n
- mpint1 encrypted_challenge
- byte[16] session_id
- uint32 response_type /* must be 1 */
-
-"rsa_e" and "rsa_n" are used to identify which private key to use.
-"encrypted_challenge" is a challenge blob that has (presumably)
-been encrypted with the public key and must be in the range
-1 <= encrypted_challenge < 2^256. "session_id" is the SSH protocol 1
-session ID (computed from the server host key, the server semi-ephemeral
-key and the session cookie).
-
-"ignored" and "response_type" exist for compatibility with legacy
-implementations. "response_type" must be equal to 1; other response
-types are not supported.
-
-On receiving this request, the server decrypts the "encrypted_challenge"
-using the private key matching the supplied (rsa_e, rsa_n) values. For
-the response derivation, the decrypted challenge is represented as an
-unsigned, big-endian integer encoded in a 32 byte buffer (i.e. values
-smaller than 2^248 will have leading 0 bytes).
-
-The response value is then calculated as:
-
- response = MD5(decrypted_challenge || session_id)
-
-and returned in the following message
-
- byte SSH_AGENT_RSA_RESPONSE
- byte[16] response
-
-If the agent cannot find the key specified by the supplied (rsa_e,
-rsa_n) then it will return SSH_AGENT_FAILURE.
-
-2.6.2 Protocol 2 private key signature request
-
-A client may use the following message to request signing of data using
-a protocol 2 key:
-
- byte SSH2_AGENTC_SIGN_REQUEST
- string key_blob
- string data
- uint32 flags
-
-Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
-Algorithms" for any of the supported protocol 2 key types. "flags" is
-a bit-mask, but at present only one possible value is defined (see below
-for its meaning):
-
- SSH_AGENT_OLD_SIGNATURE 1
-
-Upon receiving this request, the agent will look up the private key that
-corresponds to the public key contained in key_blob. It will use this
-private key to sign the "data" and produce a signature blob using the
-key type-specific method described in RFC 4253 section 6.6 "Public Key
-Algorithms".
-
-An exception to this is for "ssh-dss" keys where the "flags" word
-contains the value SSH_AGENT_OLD_SIGNATURE. In this case, a legacy
-signature encoding is used in lieu of the standard one. In this case,
-the DSA signature blob is encoded as:
-
- byte[40] signature
-
-The signature will be returned in the response message:
-
- byte SSH2_AGENT_SIGN_RESPONSE
- string signature_blob
-
-If the agent cannot find the key specified by the supplied key_blob then
-it will return SSH_AGENT_FAILURE.
-
-2.7 Locking or unlocking an agent
-
-The agent supports temporary locking with a passphrase to suspend
-processing of sensitive operations until it has been unlocked with the
-same passphrase. To lock an agent, a client send the following request:
-
- byte SSH_AGENTC_LOCK
- string passphrase
-
-Upon receipt of this message and if the agent is not already locked,
-it will suspend processing requests and return a SSH_AGENT_SUCCESS
-reply. If the agent is already locked, it will return SSH_AGENT_FAILURE.
-
-While locked, the agent will refuse all requests except
-SSH_AGENTC_UNLOCK, SSH_AGENTC_REQUEST_RSA_IDENTITIES and
-SSH2_AGENTC_REQUEST_IDENTITIES. The "request identities" requests are
-treated specially by a locked agent: it will always return an empty list
-of keys.
-
-To unlock an agent, a client may request:
-
- byte SSH_AGENTC_UNLOCK
- string passphrase
-
-If the passphrase matches and the agent is locked, then it will resume
-processing all requests and return SSH_AGENT_SUCCESS. If the agent
-is not locked or the passphrase does not match then it will return
-SSH_AGENT_FAILURE.
-
-Locking and unlocking affects both protocol 1 and protocol 2 keys.
-
-3. Protocol message numbers
-
-3.1 Requests from client to agent for protocol 1 key operations
-
- SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
- SSH_AGENTC_RSA_CHALLENGE 3
- SSH_AGENTC_ADD_RSA_IDENTITY 7
- SSH_AGENTC_REMOVE_RSA_IDENTITY 8
- SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
- SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
-
-3.2 Requests from client to agent for protocol 2 key operations
-
- SSH2_AGENTC_REQUEST_IDENTITIES 11
- SSH2_AGENTC_SIGN_REQUEST 13
- SSH2_AGENTC_ADD_IDENTITY 17
- SSH2_AGENTC_REMOVE_IDENTITY 18
- SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
- SSH2_AGENTC_ADD_ID_CONSTRAINED 25
-
-3.3 Key-type independent requests from client to agent
-
- SSH_AGENTC_ADD_SMARTCARD_KEY 20
- SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
- SSH_AGENTC_LOCK 22
- SSH_AGENTC_UNLOCK 23
- SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
-
-3.4 Generic replies from agent to client
-
- SSH_AGENT_FAILURE 5
- SSH_AGENT_SUCCESS 6
-
-3.5 Replies from agent to client for protocol 1 key operations
-
- SSH_AGENT_RSA_IDENTITIES_ANSWER 2
- SSH_AGENT_RSA_RESPONSE 4
-
-3.6 Replies from agent to client for protocol 2 key operations
-
- SSH2_AGENT_IDENTITIES_ANSWER 12
- SSH2_AGENT_SIGN_RESPONSE 14
-
-3.7 Key constraint identifiers
-
- SSH_AGENT_CONSTRAIN_LIFETIME 1
- SSH_AGENT_CONSTRAIN_CONFIRM 2
-
-$OpenBSD: PROTOCOL.agent,v 1.7 2013/01/02 00:33:49 djm Exp $
+https://tools.ietf.org/html/draft-miller-ssh-agent-02
diff --git a/PROTOCOL.certkeys b/PROTOCOL.certkeys
index c9859109..1fce8700 100644
--- a/PROTOCOL.certkeys
+++ b/PROTOCOL.certkeys
@@ -25,6 +25,10 @@ raw user keys. The ssh client will support automatic verification of
acceptance of certified host keys, by adding a similar ability to
specify CA keys in ~/.ssh/known_hosts.
+All certificate types include certification information along with the
+public key that is used to sign challenges. In OpenSSH, ssh-keygen
+performs the CA signing operation.
+
Certified keys are represented using new key types:
ssh-rsa-cert-v01@openssh.com
@@ -32,10 +36,19 @@ Certified keys are represented using new key types:
ecdsa-sha2-nistp256-cert-v01@openssh.com
ecdsa-sha2-nistp384-cert-v01@openssh.com
ecdsa-sha2-nistp521-cert-v01@openssh.com
+ ssh-ed25519-cert-v01@openssh.com
+
+Two additional types exist for RSA certificates to force use of
+SHA-2 signatures (SHA-256 and SHA-512 respectively):
+
+ rsa-sha2-256-cert-v01@openssh.com
+ rsa-sha2-512-cert-v01@openssh.com
-These include certification information along with the public key
-that is used to sign challenges. ssh-keygen performs the CA signing
-operation.
+These RSA/SHA-2 types should not appear in keys at rest or transmitted
+on their wire, but do appear in a SSH_MSG_KEXINIT's host-key algorithms
+field or in the "public key algorithm name" field of a "publickey"
+SSH_USERAUTH_REQUEST to indicate that the signature will use the
+specified algorithm.
Protocol extensions
-------------------
@@ -100,9 +113,9 @@ DSA certificate
ECDSA certificate
- string "ecdsa-sha2-nistp256@openssh.com" |
- "ecdsa-sha2-nistp384@openssh.com" |
- "ecdsa-sha2-nistp521@openssh.com"
+ string "ecdsa-sha2-nistp256-cert-v01@openssh.com" |
+ "ecdsa-sha2-nistp384-cert-v01@openssh.com" |
+ "ecdsa-sha2-nistp521-cert-v01@openssh.com"
string nonce
string curve
string public_key
@@ -118,6 +131,23 @@ ECDSA certificate
string signature key
string signature
+ED25519 certificate
+
+ string "ssh-ed25519-cert-v01@openssh.com"
+ string nonce
+ string pk
+ uint64 serial
+ uint32 type
+ string key id
+ string valid principals
+ uint64 valid after
+ uint64 valid before
+ string critical options
+ string extensions
+ string reserved
+ string signature key
+ string signature
+
The nonce field is a CA-provided random bitstring of arbitrary length
(but typically 16 or 32 bytes) included to make attacks that depend on
inducing collisions in the signature hash infeasible.
@@ -129,6 +159,9 @@ p, q, g, y are the DSA parameters as described in FIPS-186-2.
curve and public key are respectively the ECDSA "[identifier]" and "Q"
defined in section 3.1 of RFC5656.
+pk is the encoded Ed25519 public key as defined by
+draft-josefsson-eddsa-ed25519-03.
+
serial is an optional certificate serial number set by the CA to
provide an abbreviated way to refer to certificates from that CA.
If a CA does not wish to number its certificates it must set this
@@ -146,7 +179,7 @@ strings packed inside it. These principals list the names for which this
certificate is valid; hostnames for SSH_CERT_TYPE_HOST certificates and
usernames for SSH_CERT_TYPE_USER certificates. As a special case, a
zero-length "valid principals" field means the certificate is valid for
-any principal of the specified type. XXX DNS wildcards?
+any principal of the specified type.
"valid after" and "valid before" specify a validity period for the
certificate. Each represents a time in seconds since 1970-01-01
@@ -154,7 +187,7 @@ certificate. Each represents a time in seconds since 1970-01-01
valid after <= current time < valid before
-criticial options is a set of zero or more key options encoded as
+critical options is a set of zero or more key options encoded as
below. All such options are "critical" in the sense that an implementation
must refuse to authorise a key that has an unrecognised option.
@@ -172,18 +205,19 @@ compatibility.
The reserved field is currently unused and is ignored in this version of
the protocol.
-signature key contains the CA key used to sign the certificate.
-The valid key types for CA keys are ssh-rsa, ssh-dss and the ECDSA types
-ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained"
-certificates, where the signature key type is a certificate type itself
-are NOT supported. Note that it is possible for a RSA certificate key to
-be signed by a DSS or ECDSA CA key and vice-versa.
+The signature key field contains the CA key used to sign the
+certificate. The valid key types for CA keys are ssh-rsa,
+ssh-dss, ssh-ed25519 and the ECDSA types ecdsa-sha2-nistp256,
+ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained" certificates, where
+the signature key type is a certificate type itself are NOT supported.
+Note that it is possible for a RSA certificate key to be signed by a
+Ed25519 or ECDSA CA key and vice-versa.
signature is computed over all preceding fields from the initial string
up to, and including the signature key. Signatures are computed and
encoded according to the rules defined for the CA's public key algorithm
(RFC4253 section 6.6 for ssh-rsa and ssh-dss, RFC5656 for the ECDSA
-types).
+types), and draft-josefsson-eddsa-ed25519-03 for Ed25519.
Critical options
----------------
@@ -203,8 +237,12 @@ option-specific information (see below). All options are
"critical", if an implementation does not recognise a option
then the validating party should refuse to accept the certificate.
-The supported options and the contents and structure of their
-data fields are:
+Custom options should append the originating author or organisation's
+domain name to the option name, e.g. "my-option@example.com".
+
+No critical options are defined for host certificates at present. The
+supported user certificate options and the contents and structure of
+their data fields are:
Name Format Description
-----------------------------------------------------------------------------
@@ -233,11 +271,22 @@ as is the requirement that each name appear only once.
If an implementation does not recognise an extension, then it should
ignore it.
-The supported extensions and the contents and structure of their data
-fields are:
+Custom options should append the originating author or organisation's
+domain name to the option name, e.g. "my-option@example.com".
+
+No extensions are defined for host certificates at present. The
+supported user certificate extensions and the contents and structure of
+their data fields are:
Name Format Description
-----------------------------------------------------------------------------
+no-presence-required empty Flag indicating that signatures made
+ with this certificate need not assert
+ user presence. This option only make
+ sense for the U2F/FIDO security key
+ types that support this feature in
+ their signature formats.
+
permit-X11-forwarding empty Flag indicating that X11 forwarding
should be permitted. X11 forwarding will
be refused if this option is absent.
@@ -262,4 +311,4 @@ permit-user-rc empty Flag indicating that execution of
of this script will not be permitted if
this option is not present.
-$OpenBSD: PROTOCOL.certkeys,v 1.9 2012/03/28 07:23:22 djm Exp $
+$OpenBSD: PROTOCOL.certkeys,v 1.17 2019/11/25 00:57:51 djm Exp $
diff --git a/PROTOCOL.chacha20poly1305 b/PROTOCOL.chacha20poly1305
index 9cf73a92..0bfff28d 100644
--- a/PROTOCOL.chacha20poly1305
+++ b/PROTOCOL.chacha20poly1305
@@ -16,7 +16,7 @@ that computes a 128 bit integrity tag given a message and a single-use
The chacha20-poly1305@openssh.com combines these two primitives into an
authenticated encryption mode. The construction used is based on that
proposed for TLS by Adam Langley in [3], but differs in the layout of
-data passed to the MAC and in the addition of encyption of the packet
+data passed to the MAC and in the addition of encryption of the packet
lengths.
Negotiation
@@ -34,6 +34,8 @@ Detailed Construction
The chacha20-poly1305@openssh.com cipher requires 512 bits of key
material as output from the SSH key exchange. This forms two 256 bit
keys (K_1 and K_2), used by two separate instances of chacha20.
+The first 256 bits constitute K_2 and the second 256 bits become
+K_1.
The instance keyed by K_1 is a stream cipher that is used only
to encrypt the 4 byte packet length field. The second instance,
@@ -101,5 +103,5 @@ References
[3] "ChaCha20 and Poly1305 based Cipher Suites for TLS", Adam Langley
http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03
-$OpenBSD: PROTOCOL.chacha20poly1305,v 1.2 2013/12/02 02:50:27 djm Exp $
+$OpenBSD: PROTOCOL.chacha20poly1305,v 1.5 2020/02/21 00:04:43 dtucker Exp $
diff --git a/PROTOCOL.krl b/PROTOCOL.krl
index b9695107..115f80e5 100644
--- a/PROTOCOL.krl
+++ b/PROTOCOL.krl
@@ -36,6 +36,7 @@ The available section types are:
#define KRL_SECTION_EXPLICIT_KEY 2
#define KRL_SECTION_FINGERPRINT_SHA1 3
#define KRL_SECTION_SIGNATURE 4
+#define KRL_SECTION_FINGERPRINT_SHA256 5
2. Certificate section
@@ -127,25 +128,26 @@ must be a raw key (i.e. not a certificate).
This section may appear multiple times.
-4. SHA1 fingerprint sections
+4. SHA1/SHA256 fingerprint sections
-These sections, identified as KRL_SECTION_FINGERPRINT_SHA1, revoke
-plain keys (i.e. not certificates) by listing their SHA1 hashes:
+These sections, identified as KRL_SECTION_FINGERPRINT_SHA1 and
+KRL_SECTION_FINGERPRINT_SHA256, revoke plain keys (i.e. not
+certificates) by listing their hashes:
string public_key_hash[0]
....
This section must contain at least one "public_key_hash". The hash blob
-is obtained by taking the SHA1 hash of the public key blob. Hashes in
-this section must appear in numeric order, treating each hash as a big-
-endian integer.
+is obtained by taking the SHA1 or SHA256 hash of the public key blob.
+Hashes in this section must appear in numeric order, treating each hash
+as a big-endian integer.
This section may appear multiple times.
5. KRL signature sections
The KRL_SECTION_SIGNATURE section serves a different purpose to the
-preceeding ones: to provide cryptographic authentication of a KRL that
+preceding ones: to provide cryptographic authentication of a KRL that
is retrieved over a channel that does not provide integrity protection.
Its format is slightly different to the previously-described sections:
in order to simplify the signature generation, it includes as a "body"
@@ -166,4 +168,4 @@ Implementations that retrieve KRLs over untrusted channels must verify
signatures. Signature sections are optional for KRLs distributed by
trusted means.
-$OpenBSD: PROTOCOL.krl,v 1.3 2015/01/30 01:10:33 djm Exp $
+$OpenBSD: PROTOCOL.krl,v 1.5 2018/09/12 01:21:34 djm Exp $
diff --git a/PROTOCOL.mux b/PROTOCOL.mux
index b5832561..5fc4c06b 100644
--- a/PROTOCOL.mux
+++ b/PROTOCOL.mux
@@ -1,15 +1,52 @@
This document describes the multiplexing protocol used by ssh(1)'s
ControlMaster connection-sharing.
-Most messages from the client to the server contain a "request id" field.
-This field is returned in replies as "client request id" to facilitate
-matching of responses to requests.
+Multiplexing starts with a ssh(1) configured to act as a multiplexing
+master. This will cause ssh(1) to listen on a Unix domain socket for
+requests from clients. Clients communicate over this socket using a
+simple packetised protocol, where each message is proceeded with
+a length and message type in SSH uint32 wire format:
+
+ uint32 packet length
+ uint32 packet type
+ ... packet body
+
+Most messages from the client to the server contain a "request id"
+field. This field is returned in replies as "client request id" to
+facilitate matching of responses to requests.
+
+Many muliplexing (mux) client requests yield immediate responses from
+the mux process; requesting a forwarding, performing an alive check or
+requesting the master terminate itself fall in to this category.
+
+The most common use of multiplexing however is to maintain multiple
+concurrent sessions. These are supported via two separate modes:
+
+"Passenger" clients start by requesting a new session with a
+MUX_C_NEW_SESSION message and passing stdio file descriptors over the
+Unix domain control socket. The passenger client then waits until it is
+signaled or the mux server closes the session. This mode is so named as
+the client waits around while the mux server does all the driving.
+
+Stdio forwarding (requested using MUX_C_NEW_STDIO_FWD) is another
+example of passenger mode; the client passes the stdio file descriptors
+and passively waits for something to happen.
+
+"Proxy" clients, requested using MUX_C_PROXY, work quite differently. In
+this mode, the mux client/server connection socket will stop speaking
+the multiplexing protocol and start proxying SSH connection protocol
+messages between the client and server. The client therefore must
+speak a significant subset of the SSH protocol, but in return is able
+to access basically the full suite of connection protocol features.
+Moreover, as no file descriptor passing is required, the connection
+supporting a proxy client may itself be forwarded or relayed to another
+host if necessary.
1. Connection setup
When a multiplexing connection is made to a ssh(1) operating as a
-ControlMaster from a ssh(1) in multiplex slave mode, the first
-action of each is to exchange hello messages:
+ControlMaster from a client ssh(1), the first action of each is send
+a hello messages to its peer:
uint32 MUX_MSG_HELLO
uint32 protocol version
@@ -17,16 +54,16 @@ action of each is to exchange hello messages:
string extension value [optional]
...
-The current version of the mux protocol is 4. A slave should refuse
+The current version of the mux protocol is 4. A client should refuse
to connect to a master that speaks an unsupported protocol version.
-Following the version identifier are zero or more extensions
-represented as a name/value pair. No extensions are currently
-defined.
-2. Opening sessions
+Following the version identifier are zero or more extensions represented
+as a name/value pair. No extensions are currently defined.
-To open a new multiplexed session, a client may send the following
-request:
+2. Opening a passenger mode session
+
+To open a new multiplexed session in passenger mode, a client sends the
+following request:
uint32 MUX_C_NEW_SESSION
uint32 request id
@@ -80,7 +117,25 @@ return its local tty to "cooked" mode.
uint32 MUX_S_TTY_ALLOC_FAIL
uint32 session id
-3. Health checks
+3. Requesting passenger-mode stdio forwarding
+
+A client may request the master to establish a stdio forwarding:
+
+ uint32 MUX_C_NEW_STDIO_FWD
+ uint32 request id
+ string reserved
+ string connect host
+ string connect port
+
+The client then sends its standard input and output file descriptors
+(in that order) using Unix domain socket control messages.
+
+The contents of "reserved" are currently ignored.
+
+A server may reply with a MUX_S_SESSION_OPENED, a MUX_S_PERMISSION_DENIED
+or a MUX_S_FAILURE.
+
+4. Health checks
The client may request a health check/PID report from a server:
@@ -93,7 +148,7 @@ The server replies with:
uint32 client request id
uint32 server pid
-4. Remotely terminating a master
+5. Remotely terminating a master
A client may request that a master terminate immediately:
@@ -102,7 +157,7 @@ A client may request that a master terminate immediately:
The server will reply with one of MUX_S_OK or MUX_S_PERMISSION_DENIED.
-5. Requesting establishment of port forwards
+6. Requesting establishment of port forwards
A client may request the master to establish a port forward:
@@ -116,6 +171,12 @@ A client may request the master to establish a port forward:
forwarding type may be MUX_FWD_LOCAL, MUX_FWD_REMOTE, MUX_FWD_DYNAMIC.
+If listen port is (unsigned int) -2, then the listen host is treated as
+a unix socket path name.
+
+If connect port is (unsigned int) -2, then the connect host is treated
+as a unix socket path name.
+
A server may reply with a MUX_S_OK, a MUX_S_REMOTE_PORT, a
MUX_S_PERMISSION_DENIED or a MUX_S_FAILURE.
@@ -125,7 +186,7 @@ For dynamically allocated listen port the server replies with
uint32 client request id
uint32 allocated remote listen port
-6. Requesting closure of port forwards
+7. Requesting closure of port forwards
Note: currently unimplemented (server will always reply with MUX_S_FAILURE).
@@ -142,36 +203,45 @@ A client may request the master to close a port forward:
A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a
MUX_S_FAILURE.
-7. Requesting stdio forwarding
+8. Requesting shutdown of mux listener
-A client may request the master to establish a stdio forwarding:
+A client may request the master to stop accepting new multiplexing requests
+and remove its listener socket.
- uint32 MUX_C_NEW_STDIO_FWD
+ uint32 MUX_C_STOP_LISTENING
uint32 request id
- string reserved
- string connect host
- string connect port
-The client then sends its standard input and output file descriptors
-(in that order) using Unix domain socket control messages.
+A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a
+MUX_S_FAILURE.
-The contents of "reserved" are currently ignored.
+9. Requesting proxy mode
-A server may reply with a MUX_S_SESSION_OPENED, a MUX_S_PERMISSION_DENIED
-or a MUX_S_FAILURE.
+A client may request that the the control connection be placed in proxy
+mode:
-8. Requesting shutdown of mux listener
+ uint32 MUX_C_PROXY
+ uint32 request id
-A client may request the master to stop accepting new multiplexing requests
-and remove its listener socket.
+When a mux master receives this message, it will reply with a
+confirmation:
- uint32 MUX_C_STOP_LISTENING
+ uint32 MUX_S_PROXY
uint32 request id
-A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a
-MUX_S_FAILURE.
+And go into proxy mode. All subsequent data over the connection will
+be formatted as unencrypted, unpadded, SSH transport messages:
+
+ uint32 packet length
+ byte 0 (padding length)
+ byte packet type
+ byte[packet length - 2] ...
-9. Status messages
+The mux master will accept most connection messages and global requests,
+and will translate channel identifiers to ensure that the proxy client has
+globally unique channel numbers (i.e. a proxy client need not worry about
+collisions with other clients).
+
+10. Status messages
The MUX_S_OK message is empty:
@@ -188,7 +258,7 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason:
uint32 client request id
string reason
-10. Protocol numbers
+11. Protocol numbers
#define MUX_MSG_HELLO 0x00000001
#define MUX_C_NEW_SESSION 0x10000002
@@ -218,5 +288,11 @@ XXX watch in/out traffic (pre/post crypto)
XXX inject packet (what about replies)
XXX server->client error/warning notifications
XXX send signals via mux
-
-$OpenBSD: PROTOCOL.mux,v 1.9 2012/06/01 00:49:35 djm Exp $
+XXX ^Z support in passengers
+XXX extensions for multi-agent
+XXX extensions for multi-X11
+XXX session inspection via master
+XXX signals via mux request
+XXX list active connections via mux
+
+$OpenBSD: PROTOCOL.mux,v 1.12 2020/03/13 03:17:07 djm Exp $
diff --git a/PROTOCOL.sshsig b/PROTOCOL.sshsig
new file mode 100644
index 00000000..720e1f18
--- /dev/null
+++ b/PROTOCOL.sshsig
@@ -0,0 +1,99 @@
+This document describes a lightweight SSH Signature format
+that is compatible with SSH keys and wire formats.
+
+At present, only detached and armored signatures are supported.
+
+1. Armored format
+
+The Armored SSH signatures consist of a header, a base64
+encoded blob, and a footer.
+
+The header is the string "-----BEGIN SSH SIGNATURE-----"
+followed by a newline. The footer is the string
+"-----END SSH SIGNATURE-----" immediately after a newline.
+
+The header MUST be present at the start of every signature.
+Files containing the signature MUST start with the header.
+Likewise, the footer MUST be present at the end of every
+signature.
+
+The base64 encoded blob SHOULD be broken up by newlines
+every 76 characters.
+
+Example:
+
+-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgJKxoLBJBivUPNTUJUSslQTt2hD
+jozKvHarKeN8uYFqgAAAADZm9vAAAAAAAAAFMAAAALc3NoLWVkMjU1MTkAAABAKNC4IEbt
+Tq0Fb56xhtuE1/lK9H9RZJfON4o6hE9R4ZGFX98gy0+fFJ/1d2/RxnZky0Y7GojwrZkrHT
+FgCqVWAQ==
+-----END SSH SIGNATURE-----
+
+2. Blob format
+
+#define MAGIC_PREAMBLE "SSHSIG"
+#define SIG_VERSION 0x01
+
+ byte[6] MAGIC_PREAMBLE
+ uint32 SIG_VERSION
+ string publickey
+ string namespace
+ string reserved
+ string hash_algorithm
+ string signature
+
+The publickey field MUST contain the serialisation of the
+public key used to make the signature using the usual SSH
+encoding rules, i.e RFC4253, RFC5656,
+draft-ietf-curdle-ssh-ed25519-ed448, etc.
+
+Verifiers MUST reject signatures with versions greater than those
+they support.
+
+The purpose of the namespace value is to specify a unambiguous
+interpretation domain for the signature, e.g. file signing.
+This prevents cross-protocol attacks caused by signatures
+intended for one intended domain being accepted in another.
+The namespace value MUST NOT be the empty string.
+
+The reserved value is present to encode future information
+(e.g. tags) into the signature. Implementations should ignore
+the reserved field if it is not empty.
+
+Data to be signed is first hashed with the specified hash_algorithm.
+This is done to limit the amount of data presented to the signature
+operation, which may be of concern if the signing key is held in limited
+or slow hardware or on a remote ssh-agent. The supported hash algorithms
+are "sha256" and "sha512".
+
+The signature itself is made using the SSH signature algorithm and
+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
+rules and base64 encoded to form the middle part of the
+armored signature.
+
+
+3. Signed Data, of which the signature goes into the blob above
+
+#define MAGIC_PREAMBLE "SSHSIG"
+
+ byte[6] MAGIC_PREAMBLE
+ string namespace
+ string reserved
+ string hash_algorithm
+ string H(message)
+
+The preamble is the six-byte sequence "SSHSIG". It is included to
+ensure that manual signatures can never be confused with any message
+signed during SSH user or host authentication.
+
+The reserved value is present to encode future information
+(e.g. tags) into the signature. Implementations should ignore
+the reserved field if it is not empty.
+
+The data is concatenated and passed to the SSH signing
+function.
+
diff --git a/PROTOCOL.u2f b/PROTOCOL.u2f
new file mode 100644
index 00000000..917e669c
--- /dev/null
+++ b/PROTOCOL.u2f
@@ -0,0 +1,337 @@
+This document describes OpenSSH's support for U2F/FIDO security keys.
+
+Background
+----------
+
+U2F is an open standard for two-factor authentication hardware, widely
+used for user authentication to websites. U2F tokens are ubiquitous,
+available from a number of manufacturers and are currently by far the
+cheapest way for users to achieve hardware-backed credential storage.
+
+The U2F protocol however cannot be trivially used as an SSH protocol key
+type as both the inputs to the signature operation and the resultant
+signature differ from those specified for SSH. For similar reasons,
+integration of U2F devices cannot be achieved via the PKCS#11 API.
+
+U2F also offers a number of features that are attractive in the context
+of SSH authentication. They can be configured to require indication
+of "user presence" for each signature operation (typically achieved
+by requiring the user touch the key). They also offer an attestation
+mechanism at key enrollment time that can be used to prove that a
+given key is backed by hardware. Finally the signature format includes
+a monotonic signature counter that can be used (at scale) to detect
+concurrent use of a private key, should it be extracted from hardware.
+
+U2F private keys are generated through an enrollment operation,
+which takes an application ID - a URL-like string, typically "ssh:"
+in this case, but a HTTP origin for the case of web authentication,
+and a challenge string (typically randomly generated). The enrollment
+operation returns a public key, a key handle that must be used to invoke
+the hardware-backed private key, some flags and signed attestation
+information that may be used to verify that a private key is hosted on a
+particular hardware instance.
+
+It is common for U2F hardware to derive private keys from the key handle
+in conjunction with a small per-device secret that is unique to the
+hardware, thus requiring little on-device storage for an effectively
+unlimited number of supported keys. This drives the requirement that
+the key handle be supplied for each signature operation. U2F tokens
+primarily use ECDSA signatures in the NIST-P256 field, though the FIDO2
+standard specifies additional key types, including one based on Ed25519.
+
+SSH U2F Key formats
+-------------------
+
+OpenSSH integrates U2F as new key and corresponding certificate types:
+
+ sk-ecdsa-sha2-nistp256@openssh.com
+ sk-ecdsa-sha2-nistp256-cert-v01@openssh.com
+ sk-ssh-ed25519@openssh.com
+ sk-ssh-ed25519-cert-v01@openssh.com
+
+While each uses ecdsa-sha256-nistp256 as the underlying signature primitive,
+keys require extra information in the public and private keys, and in
+the signature object itself. As such they cannot be made compatible with
+the existing ecdsa-sha2-nistp* key types.
+
+The format of a sk-ecdsa-sha2-nistp256@openssh.com public key is:
+
+ string "sk-ecdsa-sha2-nistp256@openssh.com"
+ string curve name
+ ec_point Q
+ string application (user-specified, but typically "ssh:")
+
+The corresponding private key contains:
+
+ string "sk-ecdsa-sha2-nistp256@openssh.com"
+ string curve name
+ ec_point Q
+ string application (user-specified, but typically "ssh:")
+ uint8 flags
+ string key_handle
+ string reserved
+
+The format of a sk-ssh-ed25519@openssh.com public key is:
+
+ string "sk-ssh-ed25519@openssh.com"
+ string public key
+ string application (user-specified, but typically "ssh:")
+
+With a private half consisting of:
+
+ string "sk-ssh-ed25519@openssh.com"
+ string public key
+ string application (user-specified, but typically "ssh:")
+ uint8 flags
+ string key_handle
+ string reserved
+
+The certificate form for SSH U2F keys appends the usual certificate
+information to the public key:
+
+ string "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
+ string nonce
+ string curve name
+ ec_point Q
+ string application
+ uint64 serial
+ uint32 type
+ string key id
+ string valid principals
+ uint64 valid after
+ uint64 valid before
+ string critical options
+ string extensions
+ string reserved
+ string signature key
+ string signature
+
+and for security key ed25519 certificates:
+
+ string "sk-ssh-ed25519-cert-v01@openssh.com"
+ string nonce
+ string public key
+ string application
+ uint64 serial
+ uint32 type
+ string key id
+ string valid principals
+ uint64 valid after
+ uint64 valid before
+ string critical options
+ string extensions
+ string reserved
+ string signature key
+ string signature
+
+Both security key certificates use the following encoding for private keys:
+
+ string type (e.g. "sk-ssh-ed25519-cert-v01@openssh.com")
+ string pubkey (the above key/cert structure)
+ string application
+ uint8 flags
+ string key_handle
+ string reserved
+
+During key generation, the hardware also returns attestation information
+that may be used to cryptographically prove that a given key is
+hardware-backed. Unfortunately, the protocol required for this proof is
+not privacy-preserving and may be used to identify U2F tokens with at
+least manufacturer and batch number granularity. For this reason, we
+choose not to include this information in the public key or save it by
+default.
+
+Attestation information is useful for out-of-band key and certificate
+registration workflows, e.g. proving to a CA that a key is backed
+by trusted hardware before it will issue a certificate. To support this
+case, OpenSSH optionally allows retaining the attestation information
+at the time of key generation. It will take the following format:
+
+ string "ssh-sk-attest-v00"
+ string attestation certificate
+ string enrollment signature
+ uint32 reserved flags
+ string reserved string
+
+OpenSSH treats the attestation certificate and enrollment signatures as
+opaque objects and does no interpretation of them itself.
+
+SSH U2F signatures
+------------------
+
+In addition to the message to be signed, the U2F signature operation
+requires the key handle and a few additional parameters. The signature
+is signed over a blob that consists of:
+
+ byte[32] SHA256(application)
+ byte flags (including "user present", extensions present)
+ uint32 counter
+ byte[] extensions
+ byte[32] SHA256(message)
+
+No extensions are yet defined for SSH use. If any are defined in the future,
+it will be possible to infer their presence from the contents of the "flags"
+value.
+
+The signature returned from U2F hardware takes the following format:
+
+ byte flags (including "user present")
+ uint32 counter
+ byte[] ecdsa_signature (in X9.62 format).
+
+For use in the SSH protocol, we wish to avoid server-side parsing of ASN.1
+format data in the pre-authentication attack surface. Therefore, the
+signature format used on the wire in SSH2_USERAUTH_REQUEST packets will
+be reformatted to better match the existing signature encoding:
+
+ string "sk-ecdsa-sha2-nistp256@openssh.com"
+ string ecdsa_signature
+ byte flags
+ uint32 counter
+
+Where the "ecdsa_signature" field follows the RFC5656 ECDSA signature
+encoding:
+
+ mpint r
+ mpint s
+
+For Ed25519 keys the signature is encoded as:
+
+ string "sk-ssh-ed25519@openssh.com"
+ string signature
+ byte flags
+ uint32 counter
+
+ssh-agent protocol extensions
+-----------------------------
+
+ssh-agent requires a protocol extension to support U2F keys. At
+present the closest analogue to Security Keys in ssh-agent are PKCS#11
+tokens, insofar as they require a middleware library to communicate with
+the device that holds the keys. Unfortunately, the protocol message used
+to add PKCS#11 keys to ssh-agent does not include any way to send the
+key handle to the agent as U2F keys require.
+
+To avoid this, without having to add wholly new messages to the agent
+protocol, we will use the existing SSH2_AGENTC_ADD_ID_CONSTRAINED message
+with a new key constraint extension to encode a path to the middleware
+library for the key. The format of this constraint extension would be:
+
+ byte SSH_AGENT_CONSTRAIN_EXTENSION
+ string sk-provider@openssh.com
+ string middleware path
+
+This constraint-based approach does not present any compatibility
+problems.
+
+OpenSSH integration
+-------------------
+
+U2F tokens may be attached via a number of means, including USB and NFC.
+The USB interface is standardised around a HID protocol, but we want to
+be able to support other transports as well as dummy implementations for
+regress testing. For this reason, OpenSSH shall support a dynamically-
+loaded middleware libraries to communicate with security keys, but offer
+support for the common case of USB HID security keys internally.
+
+The middleware library need only expose a handful of functions:
+
+ #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
+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
+requested.
+
+At present the following options names are supported:
+
+ "device"
+
+ Specifies a specific FIDO device on which to perform the
+ operation. The value in this field is interpreted by the
+ middleware but it would be typical to specify a path to
+ a /dev node for the device in question.
+
+ "user"
+
+ Specifies the FIDO2 username used when enrolling a key,
+ overriding OpenSSH's default of using an all-zero username.
+
+In OpenSSH, the middleware will be invoked by using a similar mechanism to
+ssh-pkcs11-helper to provide address-space containment of the
+middleware from ssh-agent.
+
diff --git a/README b/README
index f1f7e7fc..cae4c28c 100644
--- a/README
+++ b/README
@@ -1,8 +1,8 @@
-See http://www.openssh.com/txt/release-6.8 for the release notes.
+See https://www.openssh.com/releasenotes.html#8.3p1 for the release notes.
-- A Japanese translation of this document and of the OpenSSH FAQ is
-- available at http://www.unixuser.org/~haruyama/security/openssh/index.html
-- Thanks to HARUYAMA Seigo <haruyama@unixuser.org>
+Please read https://www.openssh.com/report.html for bug reporting
+instructions and note that we do not use Github for bug reporting or
+patch/pull-request management.
This is the port of OpenBSD's excellent OpenSSH[0] to Linux and other
Unices.
@@ -12,13 +12,13 @@ implementation with all patent-encumbered algorithms removed (to
external libraries), all known security bugs fixed, new features
reintroduced and many other clean-ups. OpenSSH has been created by
Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt,
-and Dug Song. It has a homepage at http://www.openssh.com/
+and Dug Song. It has a homepage at https://www.openssh.com/
This port consists of the re-introduction of autoconf support, PAM
-support, EGD[1]/PRNGD[2] support and replacements for OpenBSD library
+support, EGD/PRNGD support and replacements for OpenBSD library
functions that are (regrettably) absent from other unices. This port
has been best tested on AIX, Cygwin, HP-UX, Linux, MacOS/X,
-NetBSD, OpenBSD, OpenServer, Solaris, Unicos, and UnixWare.
+FreeBSD, NetBSD, OpenBSD, OpenServer, Solaris and UnixWare.
This version actively tracks changes in the OpenBSD CVS repository.
@@ -26,40 +26,27 @@ The PAM support is now more functional than the popular packages of
commercial ssh-1.2.x. It checks "account" and "session" modules for
all logins, not just when using password authentication.
-OpenSSH depends on Zlib[3], OpenSSL[4] and optionally PAM[5].
-
There is now several mailing lists for this port of OpenSSH. Please
-refer to http://www.openssh.com/list.html for details on how to join.
+refer to https://www.openssh.com/list.html for details on how to join.
-Please send bug reports and patches to the mailing list
-openssh-unix-dev@mindrot.org. The list is open to posting by
-unsubscribed users.Code contribution are welcomed, but please follow the
-OpenBSD style guidelines[6].
+Please send bug reports and patches to https://bugzilla.mindrot.org or
+the mailing list openssh-unix-dev@mindrot.org. To mitigate spam, the
+list only allows posting from subscribed addresses. Code contribution
+are welcomed, but please follow the OpenBSD style guidelines[1].
-Please refer to the INSTALL document for information on how to install
-OpenSSH on your system. There are a number of differences between this
-port of OpenSSH and F-Secure SSH 1.x, please refer to the OpenSSH FAQ[7]
-for details and general tips.
+Please refer to the INSTALL document for information on dependencies and
+how to install OpenSSH on your system.
Damien Miller <djm@mindrot.org>
Miscellania -
-This version of OpenSSH is based upon code retrieved from the OpenBSD
-CVS repository which in turn was based on the last free sample
-implementation released by Tatu Ylonen.
+This version of OpenSSH is based upon code retrieved from the OpenBSD CVS
+repository which in turn was based on the last free sample implementation
+released by Tatu Ylonen.
References -
-[0] http://www.openssh.com/faq.html
-[1] http://www.lothar.com/tech/crypto/
-[2] http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/prngd.html
-[3] http://www.gzip.org/zlib/
-[4] http://www.openssl.org/
-[5] http://www.openpam.org
- http://www.kernel.org/pub/linux/libs/pam/
- (PAM also is standard on Solaris and HP-UX 11)
-[6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9
-[7] http://www.openssh.com/faq.html
+[0] https://www.openssh.com/
+[1] https://man.openbsd.org/style.9
-$Id: README,v 1.87 2014/08/10 01:35:06 djm Exp $
diff --git a/README.dns b/README.dns
index 97879183..29ecaee8 100644
--- a/README.dns
+++ b/README.dns
@@ -1,10 +1,10 @@
How to verify host keys using OpenSSH and DNS
---------------------------------------------
-OpenSSH contains support for verifying host keys using DNS as described in
-draft-ietf-secsh-dns-05.txt. The document contains very brief instructions
-on how to use this feature. Configuring DNS is out of the scope of this
-document.
+OpenSSH contains support for verifying host keys using DNS as described
+in https://tools.ietf.org/html/rfc4255. The document contains very brief
+instructions on how to use this feature. Configuring DNS is out of the
+scope of this document.
(1) Server: Generate and publish the DNS RR
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..28fb43d2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,79 @@
+# Portable OpenSSH
+
+[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/openssh.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:openssh)
+
+OpenSSH is a complete implementation of the SSH protocol (version 2) for secure remote login, command execution and file transfer. It includes a client ``ssh`` and server ``sshd``, file transfer utilities ``scp`` and ``sftp`` as well as tools for key generation (``ssh-keygen``), run-time key storage (``ssh-agent``) and a number of supporting programs.
+
+This is a port of OpenBSD's [OpenSSH](https://openssh.com) to most Unix-like operating systems, including Linux, OS X and Cygwin. Portable OpenSSH polyfills OpenBSD APIs that are not available elsewhere, adds sshd sandboxing for more operating systems and includes support for OS-native authentication and auditing (e.g. using PAM).
+
+## Documentation
+
+The official documentation for OpenSSH are the man pages for each tool:
+
+* [ssh(1)](https://man.openbsd.org/ssh.1)
+* [sshd(8)](https://man.openbsd.org/sshd.8)
+* [ssh-keygen(1)](https://man.openbsd.org/ssh-keygen.1)
+* [ssh-agent(1)](https://man.openbsd.org/ssh-agent.1)
+* [scp(1)](https://man.openbsd.org/scp.1)
+* [sftp(1)](https://man.openbsd.org/sftp.1)
+* [ssh-keyscan(8)](https://man.openbsd.org/ssh-keyscan.8)
+* [sftp-server(8)](https://man.openbsd.org/sftp-server.8)
+
+## Stable Releases
+
+Stable release tarballs are available from a number of [download mirrors](https://www.openssh.com/portable.html#downloads). We recommend the use of a stable release for most users. Please read the [release notes](https://www.openssh.com/releasenotes.html) for details of recent changes and potential incompatibilities.
+
+## Building Portable OpenSSH
+
+### Dependencies
+
+Portable OpenSSH is built using autoconf and make. It requires a working C compiler, standard library and headers, 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.
+
+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.
+
+### Building a release
+
+Releases include a pre-built copy of the ``configure`` script and may be built using:
+
+```
+tar zxvf openssh-X.YpZ.tar.gz
+cd openssh
+./configure # [options]
+make && make tests
+```
+
+See the [Build-time Customisation](#build-time-customisation) section below for configure options. If you plan on installing OpenSSH to your system, then you will usually want to specify destination paths.
+
+### Building from git
+
+If building from git, you'll need [autoconf](https://www.gnu.org/software/autoconf/) installed to build the ``configure`` script. The following commands will check out and build portable OpenSSH from git:
+
+```
+git clone https://github.com/openssh/openssh-portable # or https://anongit.mindrot.org/openssh.git
+cd openssh-portable
+autoreconf
+./configure
+make && make tests
+```
+
+### Build-time Customisation
+
+There are many build-time customisation options available. All Autoconf destination path flags (e.g. ``--prefix``) are supported (and are usually required if you want to install OpenSSH).
+
+For a full list of available flags, run ``configure --help`` but a few of the more frequently-used ones are described below. Some of these flags will require additional libraries and/or headers be installed.
+
+Flag | Meaning
+--- | ---
+``--with-pam`` | Enable [PAM](https://en.wikipedia.org/wiki/Pluggable_authentication_module) support. [OpenPAM](https://www.openpam.org/), [Linux PAM](http://www.linux-pam.org/) and Solaris PAM are supported.
+``--with-libedit`` | Enable [libedit](https://www.thrysoee.dk/editline/) support for sftp.
+``--with-kerberos5`` | Enable Kerberos/GSSAPI support. Both [Heimdal](https://www.h5l.org/) and [MIT](https://web.mit.edu/kerberos/) Kerberos implementations are supported.
+``--with-selinux`` | Enable [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux) support.
+``--with-security-key-builtin`` | Include built-in support for U2F/FIDO2 security keys. This requires [libfido2](https://github.com/Yubico/libfido2) be installed.
+
+## Development
+
+Portable OpenSSH development is discussed on the [openssh-unix-dev mailing list](https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev) ([archive mirror](https://marc.info/?l=openssh-unix-dev)). Bugs and feature requests are tracked on our [Bugzilla](https://bugzilla.mindrot.org/).
+
+## Reporting bugs
+
+_Non-security_ bugs may be reported to the developers via [Bugzilla](https://bugzilla.mindrot.org/) or via the mailing list above. Security bugs should be reported to [openssh@openssh.com](mailto:openssh.openssh.com).
diff --git a/README.platform b/README.platform
index d1982321..9210e07c 100644
--- a/README.platform
+++ b/README.platform
@@ -36,6 +36,9 @@ loginrestrictions() function, in particular that the user has the
"rlogin" attribute set. This check is not done for the root account,
instead the PermitRootLogin setting in sshd_config is used.
+If you are using the IBM compiler you probably want to use CC=xlc rather
+than the default of cc.
+
Cygwin
------
@@ -77,7 +80,7 @@ added to /etc/security/audit_event:
32800:AUE_openssh:OpenSSH login:lo
The BSM audit event range available for third party TCB applications is
-32768 - 65535. Event number 32800 has been choosen for AUE_openssh.
+32768 - 65535. Event number 32800 has been chosen for AUE_openssh.
There is no official registry of 3rd party event numbers, so if this
number is already in use on your system, you may change it at build time
by configure'ing --with-cflags=-DAUE_openssh=32801 then rebuilding.
@@ -91,6 +94,3 @@ added to sshd's session stack which will prevent users from starting shell
sessions. Alternatively, pam_nologin can be added to either the auth or
account stacks which will prevent authentication entirely, but will still
return the output from pam_nologin to the client.
-
-
-$Id: README.platform,v 1.10 2009/08/28 23:14:48 dtucker Exp $
diff --git a/README.privsep b/README.privsep
index f565e72d..d658c46d 100644
--- a/README.privsep
+++ b/README.privsep
@@ -5,17 +5,10 @@ escalation by containing corruption to an unprivileged process.
More information is available at:
http://www.citi.umich.edu/u/provos/ssh/privsep.html
-Privilege separation is now enabled by default; see the
-UsePrivilegeSeparation option in sshd_config(5).
-
-On systems which lack mmap or anonymous (MAP_ANON) memory mapping,
-compression must be disabled in order for privilege separation to
-function.
-
-When privsep is enabled, during the pre-authentication phase sshd will
-chroot(2) to "/var/empty" and change its privileges to the "sshd" user
-and its primary group. sshd is a pseudo-account that should not be
-used by other daemons, and must be locked and should contain a
+Privilege separation is now mandatory. During the pre-authentication
+phase sshd will chroot(2) to "/var/empty" and change its privileges to the
+"sshd" user and its primary group. sshd is a pseudo-account that should
+not be used by other daemons, and must be locked and should contain a
"nologin" or invalid shell.
You should do something like the following to prepare the privsep
@@ -35,14 +28,11 @@ privsep user and chroot directory:
--with-privsep-path=xxx Path for privilege separation chroot
--with-privsep-user=user Specify non-privileged user for privilege separation
-Privsep requires operating system support for file descriptor passing.
-Compression will be disabled on systems without a working mmap MAP_ANON.
-
PAM-enabled OpenSSH is known to function with privsep on AIX, FreeBSD,
HP-UX (including Trusted Mode), Linux, NetBSD and Solaris.
-On Cygwin, Tru64 Unix, OpenServer, and Unicos only the pre-authentication
-part of privsep is supported. Post-authentication privsep is disabled
+On Cygwin, Tru64 Unix and OpenServer only the pre-authentication part
+of privsep is supported. Post-authentication privsep is disabled
automatically (so you won't see the additional process mentioned below).
Note that for a normal interactive login with a shell, enabling privsep
@@ -59,5 +49,3 @@ Given the following process listing (from HP-UX):
process 1005 is the sshd process listening for new connections.
process 6917 is the privileged monitor process, 6919 is the user owned
sshd process and 6921 is the shell process.
-
-$Id: README.privsep,v 1.16 2005/06/04 23:21:41 djm Exp $
diff --git a/README.version b/README.version
index 3888416c..030d77da 100644
--- a/README.version
+++ b/README.version
@@ -1,4 +1,4 @@
-URL: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-6.8p1.tar.gz
-Version: 6.8p1
+URL: https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-8.3p1.tar.gz
+Version: 8.3p1
BugComponent: 180238
Owners: adelva, cloud-android-devs
diff --git a/TODO b/TODO
index e8aaa4b9..b76529c9 100644
--- a/TODO
+++ b/TODO
@@ -35,7 +35,7 @@ Programming:
- Use different PAM service name for kbdint vs regular auth (suggest from
Solar Designer)
- Ability to select which ChallengeResponseAuthentications may be used
- and order to try them in e.g. "ChallengeResponseAuthentication skey, pam"
+ and order to try them in e.g. "ChallengeResponseAuthentication pam"
- Complete Tru64 SIA support
- It looks like we could merge it into the password auth code to cut down
@@ -57,10 +57,10 @@ Clean up configure/makefiles:
- Replace the whole u_intXX_t evilness in acconfig.h with something better???
- Do it in configure.ac
-- Consider splitting the u_intXX_t test for sys/bitype.h into seperate test
+- Consider splitting the u_intXX_t test for sys/bitype.h into separate test
to allow people to (right/wrongfully) link against Bind directly.
-- Consider splitting configure.ac into seperate files which do logically
+- Consider splitting configure.ac into separate files which do logically
similar tests. E.g move all the type detection stuff into one file,
entropy related stuff into another.
@@ -69,10 +69,6 @@ Packaging:
(gilbert.r.loomis@saic.com)
PrivSep Issues:
-- mmap() issues.
- + /dev/zero solution (Solaris)
- + No/broken MAP_ANON (Irix)
- + broken /dev/zero parse (Linux)
- PAM
+ See above PAM notes
- AIX
@@ -82,5 +78,3 @@ PrivSep Issues:
+ SIA is broken
- Cygwin
+ Privsep for Pre-auth only (no fd passing)
-
-$Id: TODO,v 1.58 2004/12/06 11:40:11 dtucker Exp $
diff --git a/aclocal.m4 b/aclocal.m4
index 1640683e..25ecc49a 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,5 +1,3 @@
-dnl $Id: aclocal.m4,v 1.13 2014/01/22 10:30:12 djm Exp $
-dnl
dnl OpenSSH-specific autoconf macros
dnl
@@ -27,7 +25,7 @@ int main(int argc, char **argv) {
}
]])],
[
-if `grep -i "unrecognized option" conftest.err >/dev/null`
+if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
AC_MSG_RESULT([no])
CFLAGS="$saved_CFLAGS"
@@ -59,12 +57,13 @@ int main(int argc, char **argv) {
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);
+ long long int p = n * o;
+ printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p);
exit(0);
}
]])],
[
-if `grep -i "unrecognized option" conftest.err >/dev/null`
+if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
AC_MSG_RESULT([no])
CFLAGS="$saved_CFLAGS"
@@ -96,12 +95,20 @@ int main(int argc, char **argv) {
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);
+ long long p = n * o;
+ printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p);
exit(0);
}
]])],
- [ AC_MSG_RESULT([yes])
- LDFLAGS="$saved_LDFLAGS $_define_flag"],
+ [
+if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
+then
+ AC_MSG_RESULT([no])
+ LDFLAGS="$saved_LDFLAGS"
+else
+ AC_MSG_RESULT([yes])
+ LDFLAGS="$saved_LDFLAGS $_define_flag"
+fi ],
[ AC_MSG_RESULT([no])
LDFLAGS="$saved_LDFLAGS" ]
)
diff --git a/addrmatch.c b/addrmatch.c
index c4431463..5a402d06 100644
--- a/addrmatch.c
+++ b/addrmatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: addrmatch.c,v 1.9 2014/01/19 11:21:51 dtucker Exp $ */
+/* $OpenBSD: addrmatch.c,v 1.14 2018/07/31 03:07:24 djm Exp $ */
/*
* Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org>
@@ -31,7 +31,6 @@
#include "match.h"
#include "log.h"
-#include "xmalloc.h"
struct xaddr {
sa_family_t af;
@@ -206,25 +205,24 @@ addr_cmp(const struct xaddr *a, const struct xaddr *b)
static int
addr_pton(const char *p, struct xaddr *n)
{
- struct addrinfo hints, *ai;
+ 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)
- return -1;
-
+ goto out;
if (ai == NULL || ai->ai_addr == NULL)
- return -1;
-
- if (n != NULL &&
- addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, n) == -1) {
+ 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 -1;
- }
-
- freeaddrinfo(ai);
- return 0;
+ return ret;
}
/*
@@ -399,8 +397,8 @@ addr_match_list(const char *addr, const char *_list)
/* Prefer CIDR address matching */
r = addr_pton_cidr(cp, &match_addr, &masklen);
if (r == -2) {
- error("Inconsistent mask length for "
- "network \"%.100s\"", cp);
+ debug2("%s: inconsistent mask length for "
+ "match network \"%.100s\"", __func__, cp);
ret = -2;
break;
} else if (r == 0) {
diff --git a/atomicio.c b/atomicio.c
index b1ec234f..e00c9f0d 100644
--- a/atomicio.c
+++ b/atomicio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: atomicio.c,v 1.27 2015/01/16 06:40:12 deraadt Exp $ */
+/* $OpenBSD: atomicio.c,v 1.30 2019/01/24 02:42:23 dtucker Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
* Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
@@ -57,20 +57,25 @@ atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
ssize_t res;
struct pollfd pfd;
-#ifndef BROKEN_READ_COMPARISON
pfd.fd = fd;
+#ifndef BROKEN_READ_COMPARISON
pfd.events = f == read ? POLLIN : POLLOUT;
+#else
+ pfd.events = POLLIN|POLLOUT;
#endif
while (n > pos) {
res = (f) (fd, s + pos, n - pos);
switch (res) {
case -1:
- if (errno == EINTR)
+ if (errno == EINTR) {
+ /* possible SIGALARM, update callback */
+ if (cb != NULL && cb(cb_arg, 0) == -1) {
+ errno = EINTR;
+ return pos;
+ }
continue;
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
-#ifndef BROKEN_READ_COMPARISON
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
(void)poll(&pfd, 1, -1);
-#endif
continue;
}
return 0;
@@ -107,27 +112,32 @@ atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd,
struct iovec iov_array[IOV_MAX], *iov = iov_array;
struct pollfd pfd;
- if (iovcnt > IOV_MAX) {
+ if (iovcnt < 0 || iovcnt > IOV_MAX) {
errno = EINVAL;
return 0;
}
/* Make a copy of the iov array because we may modify it below */
- memcpy(iov, _iov, iovcnt * sizeof(*_iov));
+ memcpy(iov, _iov, (size_t)iovcnt * sizeof(*_iov));
-#ifndef BROKEN_READV_COMPARISON
pfd.fd = fd;
+#ifndef BROKEN_READV_COMPARISON
pfd.events = f == readv ? POLLIN : POLLOUT;
+#else
+ pfd.events = POLLIN|POLLOUT;
#endif
for (; iovcnt > 0 && iov[0].iov_len > 0;) {
res = (f) (fd, iov, iovcnt);
switch (res) {
case -1:
- if (errno == EINTR)
+ if (errno == EINTR) {
+ /* possible SIGALARM, update callback */
+ if (cb != NULL && cb(cb_arg, 0) == -1) {
+ errno = EINTR;
+ return pos;
+ }
continue;
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
-#ifndef BROKEN_READV_COMPARISON
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
(void)poll(&pfd, 1, -1);
-#endif
continue;
}
return 0;
diff --git a/atomicio.h b/atomicio.h
index 0d728ac8..8b3cc6e2 100644
--- a/atomicio.h
+++ b/atomicio.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: atomicio.h,v 1.11 2010/09/22 22:58:51 djm Exp $ */
+/* $OpenBSD: atomicio.h,v 1.12 2018/12/27 03:25:25 djm Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
@@ -29,6 +29,8 @@
#ifndef _ATOMICIO_H
#define _ATOMICIO_H
+struct iovec;
+
/*
* Ensure all of data on socket comes through. f==read || f==vwrite
*/
diff --git a/audit-bsm.c b/audit-bsm.c
index 61355914..0ba16c72 100644
--- a/audit-bsm.c
+++ b/audit-bsm.c
@@ -1,5 +1,3 @@
-/* $Id: audit-bsm.c,v 1.8 2012/02/23 23:40:43 dtucker Exp $ */
-
/*
* TODO
*
@@ -51,7 +49,6 @@
#include "ssh.h"
#include "log.h"
-#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "xmalloc.h"
@@ -394,7 +391,7 @@ audit_session_close(struct logininfo *li)
}
void
-audit_event(ssh_audit_event_t event)
+audit_event(struct ssh *ssh, ssh_audit_event_t event)
{
char textbuf[BSM_TEXTBUFSZ];
static int logged_in = 0;
diff --git a/audit-linux.c b/audit-linux.c
index b3ee2f4d..3fcbe5c5 100644
--- a/audit-linux.c
+++ b/audit-linux.c
@@ -1,5 +1,3 @@
-/* $Id: audit-linux.c,v 1.1 2011/01/17 10:15:30 dtucker Exp $ */
-
/*
* Copyright 2010 Red Hat, Inc. All rights reserved.
* Use is subject to license terms.
@@ -36,17 +34,17 @@
#include "log.h"
#include "audit.h"
#include "canohost.h"
+#include "packet.h"
-const char* audit_username(void);
+const char *audit_username(void);
int
-linux_audit_record_event(int uid, const char *username,
- const char *hostname, const char *ip, const char *ttyn, int success)
+linux_audit_record_event(int uid, const char *username, const char *hostname,
+ const char *ip, const char *ttyn, int success)
{
int audit_fd, rc, saved_errno;
- audit_fd = audit_open();
- if (audit_fd < 0) {
+ if ((audit_fd = audit_open()) < 0) {
if (errno == EINVAL || errno == EPROTONOSUPPORT ||
errno == EAFNOSUPPORT)
return 1; /* No audit support in kernel */
@@ -58,6 +56,7 @@ linux_audit_record_event(int uid, const char *username,
username == NULL ? uid : -1, hostname, ip, ttyn, success);
saved_errno = errno;
close(audit_fd);
+
/*
* Do not report error if the error is EPERM and sshd is run as non
* root user.
@@ -65,7 +64,8 @@ linux_audit_record_event(int uid, const char *username,
if ((rc == -EPERM) && (geteuid() != 0))
rc = 0;
errno = saved_errno;
- return (rc >= 0);
+
+ return rc >= 0;
}
/* Below is the sshd audit API code */
@@ -73,8 +73,8 @@ linux_audit_record_event(int uid, const char *username,
void
audit_connection_from(const char *host, int port)
{
-}
/* not implemented */
+}
void
audit_run_command(const char *command)
@@ -85,8 +85,8 @@ audit_run_command(const char *command)
void
audit_session_open(struct logininfo *li)
{
- if (linux_audit_record_event(li->uid, NULL, li->hostname,
- NULL, li->line, 1) == 0)
+ if (linux_audit_record_event(li->uid, NULL, li->hostname, NULL,
+ li->line, 1) == 0)
fatal("linux_audit_write_entry failed: %s", strerror(errno));
}
@@ -97,7 +97,7 @@ audit_session_close(struct logininfo *li)
}
void
-audit_event(ssh_audit_event_t event)
+audit_event(struct ssh *ssh, ssh_audit_event_t event)
{
switch(event) {
case SSH_AUTH_SUCCESS:
@@ -106,7 +106,6 @@ audit_event(ssh_audit_event_t event)
case SSH_LOGIN_EXCEED_MAXTRIES:
case SSH_LOGIN_ROOT_DENIED:
break;
-
case SSH_AUTH_FAIL_NONE:
case SSH_AUTH_FAIL_PASSWD:
case SSH_AUTH_FAIL_KBDINT:
@@ -115,12 +114,11 @@ audit_event(ssh_audit_event_t event)
case SSH_AUTH_FAIL_GSSAPI:
case SSH_INVALID_USER:
linux_audit_record_event(-1, audit_username(), NULL,
- get_remote_ipaddr(), "sshd", 0);
+ ssh_remote_ipaddr(ssh), "sshd", 0);
break;
-
default:
debug("%s: unhandled event %d", __func__, event);
+ break;
}
}
-
#endif /* USE_LINUX_AUDIT */
diff --git a/audit.c b/audit.c
index ced57fa6..dd2f0355 100644
--- a/audit.c
+++ b/audit.c
@@ -1,5 +1,3 @@
-/* $Id: audit.c,v 1.6 2011/01/17 10:15:30 dtucker Exp $ */
-
/*
* Copyright (c) 2004, 2005 Darren Tucker. All rights reserved.
*
@@ -28,12 +26,12 @@
#include <stdarg.h>
#include <string.h>
+#include <unistd.h>
#ifdef SSH_AUDIT_EVENTS
#include "audit.h"
#include "log.h"
-#include "key.h"
#include "hostfile.h"
#include "auth.h"
@@ -133,7 +131,7 @@ audit_connection_from(const char *host, int port)
* events and what they mean).
*/
void
-audit_event(ssh_audit_event_t event)
+audit_event(struct ssh *ssh, ssh_audit_event_t event)
{
debug("audit event euid %d user %s event %d (%s)", geteuid(),
audit_username(), event, audit_event_lookup(event));
diff --git a/audit.h b/audit.h
index 92ede5bc..38cb5ad3 100644
--- a/audit.h
+++ b/audit.h
@@ -1,5 +1,3 @@
-/* $Id: audit.h,v 1.4 2011/01/17 10:15:30 dtucker Exp $ */
-
/*
* Copyright (c) 2004, 2005 Darren Tucker. All rights reserved.
*
@@ -29,6 +27,8 @@
#include "loginrec.h"
+struct ssh;
+
enum ssh_audit_event_type {
SSH_LOGIN_EXCEED_MAXTRIES,
SSH_LOGIN_ROOT_DENIED,
@@ -48,7 +48,7 @@ enum ssh_audit_event_type {
typedef enum ssh_audit_event_type ssh_audit_event_t;
void audit_connection_from(const char *, int);
-void audit_event(ssh_audit_event_t);
+void audit_event(struct ssh *, ssh_audit_event_t);
void audit_session_open(struct logininfo *);
void audit_session_close(struct logininfo *);
void audit_run_command(const char *);
diff --git a/auth-bsdauth.c b/auth-bsdauth.c
index 37ff893e..d124e994 100644
--- a/auth-bsdauth.c
+++ b/auth-bsdauth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-bsdauth.c,v 1.13 2014/06/24 01:13:21 djm Exp $ */
+/* $OpenBSD: auth-bsdauth.c,v 1.15 2018/07/09 21:35:50 markus Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@@ -29,15 +29,13 @@
#include <stdarg.h>
#include <stdio.h>
-#include <stdarg.h>
-
#ifdef BSD_AUTH
#include "xmalloc.h"
-#include "key.h"
+#include "sshkey.h"
+#include "sshbuf.h"
#include "hostfile.h"
#include "auth.h"
#include "log.h"
-#include "buffer.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
@@ -103,7 +101,7 @@ bsdauth_respond(void *ctx, u_int numresponses, char **responses)
if (!authctxt->valid)
return -1;
- if (authctxt->as == 0)
+ if (authctxt->as == NULL)
error("bsdauth_respond: no bsd auth session");
if (numresponses != 1)
diff --git a/auth-chall.c b/auth-chall.c
deleted file mode 100644
index 5c26a403..00000000
--- a/auth-chall.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* $OpenBSD: auth-chall.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <stdarg.h>
-
-#include "xmalloc.h"
-#include "key.h"
-#include "hostfile.h"
-#include "auth.h"
-#include "log.h"
-#include "misc.h"
-#include "servconf.h"
-
-/* limited protocol v1 interface to kbd-interactive authentication */
-
-extern KbdintDevice *devices[];
-static KbdintDevice *device;
-extern ServerOptions options;
-
-char *
-get_challenge(Authctxt *authctxt)
-{
- char *challenge, *name, *info, **prompts;
- u_int i, numprompts;
- u_int *echo_on;
-
-#ifdef USE_PAM
- if (!options.use_pam)
- remove_kbdint_device("pam");
-#endif
-
- device = devices[0]; /* we always use the 1st device for protocol 1 */
- if (device == NULL)
- return NULL;
- if ((authctxt->kbdintctxt = device->init_ctx(authctxt)) == NULL)
- return NULL;
- if (device->query(authctxt->kbdintctxt, &name, &info,
- &numprompts, &prompts, &echo_on)) {
- device->free_ctx(authctxt->kbdintctxt);
- authctxt->kbdintctxt = NULL;
- return NULL;
- }
- if (numprompts < 1)
- fatal("get_challenge: numprompts < 1");
- challenge = xstrdup(prompts[0]);
- for (i = 0; i < numprompts; i++)
- free(prompts[i]);
- free(prompts);
- free(name);
- free(echo_on);
- free(info);
-
- return (challenge);
-}
-int
-verify_response(Authctxt *authctxt, const char *response)
-{
- char *resp[1], *name, *info, **prompts;
- u_int i, numprompts, *echo_on;
- int authenticated = 0;
-
- if (device == NULL)
- return 0;
- if (authctxt->kbdintctxt == NULL)
- return 0;
- resp[0] = (char *)response;
- switch (device->respond(authctxt->kbdintctxt, 1, resp)) {
- case 0: /* Success */
- authenticated = 1;
- break;
- case 1: /* Postponed - retry with empty query for PAM */
- if ((device->query(authctxt->kbdintctxt, &name, &info,
- &numprompts, &prompts, &echo_on)) != 0)
- break;
- if (numprompts == 0 &&
- device->respond(authctxt->kbdintctxt, 0, resp) == 0)
- authenticated = 1;
-
- for (i = 0; i < numprompts; i++)
- free(prompts[i]);
- free(prompts);
- free(name);
- free(echo_on);
- free(info);
- break;
- }
- device->free_ctx(authctxt->kbdintctxt);
- authctxt->kbdintctxt = NULL;
- return authenticated;
-}
-void
-abandon_challenge_response(Authctxt *authctxt)
-{
- if (authctxt->kbdintctxt != NULL) {
- device->free_ctx(authctxt->kbdintctxt);
- authctxt->kbdintctxt = NULL;
- }
-}
diff --git a/auth-krb5.c b/auth-krb5.c
index 0089b184..3096f1c8 100644
--- a/auth-krb5.c
+++ b/auth-krb5.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: auth-krb5.c,v 1.20 2013/07/20 01:55:13 djm Exp $ */
+/* $OpenBSD: auth-krb5.c,v 1.23 2018/07/09 21:35:50 markus Exp $ */
/*
* Kerberos v5 authentication and ticket-passing routines.
*
- * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $
+ * From: FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar
*/
/*
* Copyright (c) 2002 Daniel Kouril. All rights reserved.
@@ -36,14 +36,13 @@
#include "xmalloc.h"
#include "ssh.h"
-#include "ssh1.h"
#include "packet.h"
#include "log.h"
-#include "buffer.h"
+#include "sshbuf.h"
+#include "sshkey.h"
#include "misc.h"
#include "servconf.h"
#include "uidswap.h"
-#include "key.h"
#include "hostfile.h"
#include "auth.h"
diff --git a/auth-options.c b/auth-options.c
index 4f0da9c0..696ba6ac 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -1,441 +1,82 @@
-/* $OpenBSD: auth-options.c,v 1.65 2015/01/14 10:30:34 markus Exp $ */
+/* $OpenBSD: auth-options.c,v 1.92 2020/03/06 18:15:38 markus Exp $ */
/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
+ * Copyright (c) 2018 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 <stdlib.h>
#include <netdb.h>
#include <pwd.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
#include "openbsd-compat/sys-queue.h"
-#include "key.h" /* XXX for typedef */
-#include "buffer.h" /* XXX for typedef */
#include "xmalloc.h"
-#include "match.h"
#include "ssherr.h"
#include "log.h"
-#include "canohost.h"
#include "sshbuf.h"
#include "misc.h"
-#include "channels.h"
-#include "servconf.h"
#include "sshkey.h"
+#include "match.h"
+#include "ssh2.h"
#include "auth-options.h"
-#include "hostfile.h"
-#include "auth.h"
-
-/* Flags set authorized_keys flags */
-int no_port_forwarding_flag = 0;
-int no_agent_forwarding_flag = 0;
-int no_x11_forwarding_flag = 0;
-int no_pty_flag = 0;
-int no_user_rc = 0;
-int key_is_cert_authority = 0;
-
-/* "command=" option. */
-char *forced_command = NULL;
-
-/* "environment=" options. */
-struct envstring *custom_environment = NULL;
-
-/* "tunnel=" option. */
-int forced_tun_device = -1;
-
-/* "principals=" option. */
-char *authorized_principals = NULL;
-
-extern ServerOptions options;
-
-void
-auth_clear_options(void)
-{
- no_agent_forwarding_flag = 0;
- no_port_forwarding_flag = 0;
- no_pty_flag = 0;
- no_x11_forwarding_flag = 0;
- no_user_rc = 0;
- key_is_cert_authority = 0;
- while (custom_environment) {
- struct envstring *ce = custom_environment;
- custom_environment = ce->next;
- free(ce->s);
- free(ce);
- }
- if (forced_command) {
- free(forced_command);
- forced_command = NULL;
- }
- if (authorized_principals) {
- free(authorized_principals);
- authorized_principals = NULL;
- }
- forced_tun_device = -1;
- channel_clear_permitted_opens();
-}
-/*
- * return 1 if access is granted, 0 if not.
- * side effect: sets key option flags
- */
-int
-auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
+static int
+dup_strings(char ***dstp, size_t *ndstp, char **src, size_t nsrc)
{
- const char *cp;
- int i;
+ char **dst;
+ size_t i, j;
- /* reset options */
- auth_clear_options();
+ *dstp = NULL;
+ *ndstp = 0;
+ if (nsrc == 0)
+ return 0;
- if (!opts)
- return 1;
-
- while (*opts && *opts != ' ' && *opts != '\t') {
- cp = "cert-authority";
- if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- key_is_cert_authority = 1;
- opts += strlen(cp);
- goto next_option;
- }
- cp = "no-port-forwarding";
- if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- auth_debug_add("Port forwarding disabled.");
- no_port_forwarding_flag = 1;
- opts += strlen(cp);
- goto next_option;
- }
- cp = "no-agent-forwarding";
- if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- auth_debug_add("Agent forwarding disabled.");
- no_agent_forwarding_flag = 1;
- opts += strlen(cp);
- goto next_option;
- }
- cp = "no-X11-forwarding";
- if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- auth_debug_add("X11 forwarding disabled.");
- no_x11_forwarding_flag = 1;
- opts += strlen(cp);
- goto next_option;
- }
- cp = "no-pty";
- if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- auth_debug_add("Pty allocation disabled.");
- no_pty_flag = 1;
- opts += strlen(cp);
- goto next_option;
- }
- cp = "no-user-rc";
- if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- auth_debug_add("User rc file execution disabled.");
- no_user_rc = 1;
- opts += strlen(cp);
- goto next_option;
- }
- cp = "command=\"";
- if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- opts += strlen(cp);
- if (forced_command != NULL)
- free(forced_command);
- forced_command = xmalloc(strlen(opts) + 1);
- i = 0;
- while (*opts) {
- if (*opts == '"')
- break;
- if (*opts == '\\' && opts[1] == '"') {
- opts += 2;
- forced_command[i++] = '"';
- continue;
- }
- forced_command[i++] = *opts++;
- }
- if (!*opts) {
- debug("%.100s, line %lu: missing end quote",
- file, linenum);
- auth_debug_add("%.100s, line %lu: missing end quote",
- file, linenum);
- free(forced_command);
- forced_command = NULL;
- goto bad_option;
- }
- forced_command[i] = '\0';
- auth_debug_add("Forced command.");
- opts++;
- goto next_option;
- }
- cp = "principals=\"";
- if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- opts += strlen(cp);
- if (authorized_principals != NULL)
- free(authorized_principals);
- authorized_principals = xmalloc(strlen(opts) + 1);
- i = 0;
- while (*opts) {
- if (*opts == '"')
- break;
- if (*opts == '\\' && opts[1] == '"') {
- opts += 2;
- authorized_principals[i++] = '"';
- continue;
- }
- authorized_principals[i++] = *opts++;
- }
- if (!*opts) {
- debug("%.100s, line %lu: missing end quote",
- file, linenum);
- auth_debug_add("%.100s, line %lu: missing end quote",
- file, linenum);
- free(authorized_principals);
- authorized_principals = NULL;
- goto bad_option;
- }
- authorized_principals[i] = '\0';
- auth_debug_add("principals: %.900s",
- authorized_principals);
- opts++;
- goto next_option;
- }
- cp = "environment=\"";
- if (options.permit_user_env &&
- strncasecmp(opts, cp, strlen(cp)) == 0) {
- char *s;
- struct envstring *new_envstring;
-
- opts += strlen(cp);
- s = xmalloc(strlen(opts) + 1);
- i = 0;
- while (*opts) {
- if (*opts == '"')
- break;
- if (*opts == '\\' && opts[1] == '"') {
- opts += 2;
- s[i++] = '"';
- continue;
- }
- s[i++] = *opts++;
- }
- if (!*opts) {
- debug("%.100s, line %lu: missing end quote",
- file, linenum);
- auth_debug_add("%.100s, line %lu: missing end quote",
- file, linenum);
- free(s);
- goto bad_option;
- }
- s[i] = '\0';
- auth_debug_add("Adding to environment: %.900s", s);
- debug("Adding to environment: %.900s", s);
- opts++;
- new_envstring = xcalloc(1, sizeof(struct envstring));
- new_envstring->s = s;
- new_envstring->next = custom_environment;
- custom_environment = new_envstring;
- goto next_option;
- }
- cp = "from=\"";
- if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- const char *remote_ip = get_remote_ipaddr();
- const char *remote_host = get_canonical_hostname(
- options.use_dns);
- char *patterns = xmalloc(strlen(opts) + 1);
-
- opts += strlen(cp);
- i = 0;
- while (*opts) {
- if (*opts == '"')
- break;
- if (*opts == '\\' && opts[1] == '"') {
- opts += 2;
- patterns[i++] = '"';
- continue;
- }
- patterns[i++] = *opts++;
- }
- if (!*opts) {
- debug("%.100s, line %lu: missing end quote",
- file, linenum);
- auth_debug_add("%.100s, line %lu: missing end quote",
- file, linenum);
- free(patterns);
- goto bad_option;
- }
- patterns[i] = '\0';
- opts++;
- switch (match_host_and_ip(remote_host, remote_ip,
- patterns)) {
- case 1:
- free(patterns);
- /* Host name matches. */
- goto next_option;
- case -1:
- debug("%.100s, line %lu: invalid criteria",
- file, linenum);
- auth_debug_add("%.100s, line %lu: "
- "invalid criteria", file, linenum);
- /* FALLTHROUGH */
- case 0:
- free(patterns);
- logit("Authentication tried for %.100s with "
- "correct key but not from a permitted "
- "host (host=%.200s, ip=%.200s).",
- pw->pw_name, remote_host, remote_ip);
- auth_debug_add("Your host '%.200s' is not "
- "permitted to use this key for login.",
- remote_host);
- break;
- }
- /* deny access */
- return 0;
- }
- cp = "permitopen=\"";
- if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- char *host, *p;
- int port;
- char *patterns = xmalloc(strlen(opts) + 1);
-
- opts += strlen(cp);
- i = 0;
- while (*opts) {
- if (*opts == '"')
- break;
- if (*opts == '\\' && opts[1] == '"') {
- opts += 2;
- patterns[i++] = '"';
- continue;
- }
- patterns[i++] = *opts++;
- }
- if (!*opts) {
- debug("%.100s, line %lu: missing end quote",
- file, linenum);
- auth_debug_add("%.100s, line %lu: missing "
- "end quote", file, linenum);
- free(patterns);
- goto bad_option;
- }
- patterns[i] = '\0';
- opts++;
- p = patterns;
- /* XXX - add streamlocal support */
- host = hpdelim(&p);
- if (host == NULL || strlen(host) >= NI_MAXHOST) {
- debug("%.100s, line %lu: Bad permitopen "
- "specification <%.100s>", file, linenum,
- patterns);
- auth_debug_add("%.100s, line %lu: "
- "Bad permitopen specification", file,
- linenum);
- free(patterns);
- goto bad_option;
- }
- host = cleanhostname(host);
- if (p == NULL || (port = permitopen_port(p)) < 0) {
- debug("%.100s, line %lu: Bad permitopen port "
- "<%.100s>", file, linenum, p ? p : "");
- auth_debug_add("%.100s, line %lu: "
- "Bad permitopen port", file, linenum);
- free(patterns);
- goto bad_option;
- }
- if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0)
- channel_add_permitted_opens(host, port);
- free(patterns);
- goto next_option;
- }
- cp = "tunnel=\"";
- if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- char *tun = NULL;
- opts += strlen(cp);
- tun = xmalloc(strlen(opts) + 1);
- i = 0;
- while (*opts) {
- if (*opts == '"')
- break;
- tun[i++] = *opts++;
- }
- if (!*opts) {
- debug("%.100s, line %lu: missing end quote",
- file, linenum);
- auth_debug_add("%.100s, line %lu: missing end quote",
- file, linenum);
- free(tun);
- forced_tun_device = -1;
- goto bad_option;
- }
- tun[i] = '\0';
- forced_tun_device = a2tun(tun, NULL);
- free(tun);
- if (forced_tun_device == SSH_TUNID_ERR) {
- debug("%.100s, line %lu: invalid tun device",
- file, linenum);
- auth_debug_add("%.100s, line %lu: invalid tun device",
- file, linenum);
- forced_tun_device = -1;
- goto bad_option;
- }
- auth_debug_add("Forced tun device: %d", forced_tun_device);
- opts++;
- goto next_option;
+ if ((dst = calloc(nsrc, sizeof(*src))) == NULL)
+ return -1;
+ for (i = 0; i < nsrc; i++) {
+ if ((dst[i] = strdup(src[i])) == NULL) {
+ for (j = 0; j < i; j++)
+ free(dst[j]);
+ free(dst);
+ return -1;
}
-next_option:
- /*
- * Skip the comma, and move to the next option
- * (or break out if there are no more).
- */
- if (!*opts)
- fatal("Bugs in auth-options.c option processing.");
- if (*opts == ' ' || *opts == '\t')
- break; /* End of options. */
- if (*opts != ',')
- goto bad_option;
- opts++;
- /* Process the next option. */
}
-
- /* grant access */
- return 1;
-
-bad_option:
- logit("Bad options in %.100s file, line %lu: %.50s",
- file, linenum, opts);
- auth_debug_add("Bad options in %.100s file, line %lu: %.50s",
- file, linenum, opts);
-
- /* deny access */
+ /* success */
+ *dstp = dst;
+ *ndstp = nsrc;
return 0;
}
#define OPTIONS_CRITICAL 1
#define OPTIONS_EXTENSIONS 2
static int
-parse_option_list(struct sshbuf *oblob, struct passwd *pw,
- u_int which, int crit,
- int *cert_no_port_forwarding_flag,
- int *cert_no_agent_forwarding_flag,
- int *cert_no_x11_forwarding_flag,
- int *cert_no_pty_flag,
- int *cert_no_user_rc,
- char **cert_forced_command,
- int *cert_source_address_done)
+cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob,
+ u_int which, int crit)
{
char *command, *allowed;
- const char *remote_ip;
char *name = NULL;
struct sshbuf *c = NULL, *data = NULL;
- int r, ret = -1, result, found;
+ int r, ret = -1, found;
if ((c = sshbuf_fromb(oblob)) == NULL) {
error("%s: sshbuf_fromb failed", __func__);
@@ -455,22 +96,25 @@ parse_option_list(struct sshbuf *oblob, struct passwd *pw,
name, sshbuf_len(data));
found = 0;
if ((which & OPTIONS_EXTENSIONS) != 0) {
- if (strcmp(name, "permit-X11-forwarding") == 0) {
- *cert_no_x11_forwarding_flag = 0;
+ if (strcmp(name, "no-touch-required") == 0) {
+ opts->no_require_user_presence = 1;
+ found = 1;
+ } else if (strcmp(name, "permit-X11-forwarding") == 0) {
+ opts->permit_x11_forwarding_flag = 1;
found = 1;
} else if (strcmp(name,
"permit-agent-forwarding") == 0) {
- *cert_no_agent_forwarding_flag = 0;
+ opts->permit_agent_forwarding_flag = 1;
found = 1;
} else if (strcmp(name,
"permit-port-forwarding") == 0) {
- *cert_no_port_forwarding_flag = 0;
+ opts->permit_port_forwarding_flag = 1;
found = 1;
} else if (strcmp(name, "permit-pty") == 0) {
- *cert_no_pty_flag = 0;
+ opts->permit_pty_flag = 1;
found = 1;
} else if (strcmp(name, "permit-user-rc") == 0) {
- *cert_no_user_rc = 0;
+ opts->permit_user_rc = 1;
found = 1;
}
}
@@ -482,13 +126,13 @@ parse_option_list(struct sshbuf *oblob, struct passwd *pw,
"section: %s", name, ssh_err(r));
goto out;
}
- if (*cert_forced_command != NULL) {
+ if (opts->force_command != NULL) {
error("Certificate has multiple "
"force-command options");
free(command);
goto out;
}
- *cert_forced_command = command;
+ opts->force_command = command;
found = 1;
}
if (strcmp(name, "source-address") == 0) {
@@ -498,38 +142,19 @@ parse_option_list(struct sshbuf *oblob, struct passwd *pw,
"section: %s", name, ssh_err(r));
goto out;
}
- if ((*cert_source_address_done)++) {
+ if (opts->required_from_host_cert != NULL) {
error("Certificate has multiple "
"source-address options");
free(allowed);
goto out;
}
- remote_ip = get_remote_ipaddr();
- result = addr_match_cidr_list(remote_ip,
- allowed);
- free(allowed);
- switch (result) {
- case 1:
- /* accepted */
- break;
- case 0:
- /* no match */
- logit("Authentication tried for %.100s "
- "with valid certificate but not "
- "from a permitted host "
- "(ip=%.200s).", pw->pw_name,
- remote_ip);
- auth_debug_add("Your address '%.200s' "
- "is not permitted to use this "
- "certificate for login.",
- remote_ip);
- goto out;
- case -1:
- default:
+ /* Check syntax */
+ if (addr_match_cidr_list(NULL, allowed) == -1) {
error("Certificate source-address "
"contents invalid");
goto out;
}
+ opts->required_from_host_cert = allowed;
found = 1;
}
}
@@ -555,75 +180,704 @@ parse_option_list(struct sshbuf *oblob, struct passwd *pw,
ret = 0;
out:
- if (ret != 0 &&
- cert_forced_command != NULL &&
- *cert_forced_command != NULL) {
- free(*cert_forced_command);
- *cert_forced_command = NULL;
- }
- if (name != NULL)
- free(name);
+ free(name);
sshbuf_free(data);
sshbuf_free(c);
return ret;
}
+struct sshauthopt *
+sshauthopt_new(void)
+{
+ struct sshauthopt *ret;
+
+ if ((ret = calloc(1, sizeof(*ret))) == NULL)
+ return NULL;
+ ret->force_tun_device = -1;
+ return ret;
+}
+
+void
+sshauthopt_free(struct sshauthopt *opts)
+{
+ size_t i;
+
+ if (opts == NULL)
+ return;
+
+ free(opts->cert_principals);
+ free(opts->force_command);
+ free(opts->required_from_host_cert);
+ free(opts->required_from_host_keys);
+
+ for (i = 0; i < opts->nenv; i++)
+ free(opts->env[i]);
+ free(opts->env);
+
+ for (i = 0; i < opts->npermitopen; i++)
+ free(opts->permitopen[i]);
+ free(opts->permitopen);
+
+ for (i = 0; i < opts->npermitlisten; i++)
+ free(opts->permitlisten[i]);
+ free(opts->permitlisten);
+
+ freezero(opts, sizeof(*opts));
+}
+
+struct sshauthopt *
+sshauthopt_new_with_keys_defaults(void)
+{
+ struct sshauthopt *ret = NULL;
+
+ if ((ret = sshauthopt_new()) == NULL)
+ return NULL;
+
+ /* Defaults for authorized_keys flags */
+ ret->permit_port_forwarding_flag = 1;
+ ret->permit_agent_forwarding_flag = 1;
+ ret->permit_x11_forwarding_flag = 1;
+ ret->permit_pty_flag = 1;
+ ret->permit_user_rc = 1;
+ return ret;
+}
+
/*
- * Set options from critical certificate options. These supersede user key
- * options so this must be called after auth_parse_options().
+ * Parse and record a permitopen/permitlisten directive.
+ * Return 0 on success. Return -1 on failure and sets *errstrp to error reason.
*/
-int
-auth_cert_options(struct sshkey *k, struct passwd *pw)
+static int
+handle_permit(const char **optsp, int allow_bare_port,
+ char ***permitsp, size_t *npermitsp, const char **errstrp)
{
- int cert_no_port_forwarding_flag = 1;
- int cert_no_agent_forwarding_flag = 1;
- int cert_no_x11_forwarding_flag = 1;
- int cert_no_pty_flag = 1;
- int cert_no_user_rc = 1;
- char *cert_forced_command = NULL;
- int cert_source_address_done = 0;
-
- if (sshkey_cert_is_legacy(k)) {
- /* All options are in the one field for v00 certs */
- if (parse_option_list(k->cert->critical, pw,
- OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1,
- &cert_no_port_forwarding_flag,
- &cert_no_agent_forwarding_flag,
- &cert_no_x11_forwarding_flag,
- &cert_no_pty_flag,
- &cert_no_user_rc,
- &cert_forced_command,
- &cert_source_address_done) == -1)
- return -1;
- } else {
- /* Separate options and extensions for v01 certs */
- if (parse_option_list(k->cert->critical, pw,
- OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
- &cert_forced_command,
- &cert_source_address_done) == -1)
- return -1;
- if (parse_option_list(k->cert->extensions, pw,
- OPTIONS_EXTENSIONS, 1,
- &cert_no_port_forwarding_flag,
- &cert_no_agent_forwarding_flag,
- &cert_no_x11_forwarding_flag,
- &cert_no_pty_flag,
- &cert_no_user_rc,
- NULL, NULL) == -1)
+ char *opt, *tmp, *cp, *host, **permits = *permitsp;
+ size_t npermits = *npermitsp;
+ const char *errstr = "unknown error";
+
+ if (npermits > SSH_AUTHOPT_PERMIT_MAX) {
+ *errstrp = "too many permission directives";
+ return -1;
+ }
+ if ((opt = opt_dequote(optsp, &errstr)) == NULL) {
+ return -1;
+ }
+ if (allow_bare_port && strchr(opt, ':') == NULL) {
+ /*
+ * Allow a bare port number in permitlisten to indicate a
+ * listen_host wildcard.
+ */
+ if (asprintf(&tmp, "*:%s", opt) == -1) {
+ free(opt);
+ *errstrp = "memory allocation failed";
return -1;
+ }
+ free(opt);
+ opt = tmp;
+ }
+ if ((tmp = strdup(opt)) == NULL) {
+ free(opt);
+ *errstrp = "memory allocation failed";
+ return -1;
+ }
+ cp = tmp;
+ /* validate syntax before recording it. */
+ host = hpdelim(&cp);
+ if (host == NULL || strlen(host) >= NI_MAXHOST) {
+ free(tmp);
+ free(opt);
+ *errstrp = "invalid permission hostname";
+ return -1;
+ }
+ /*
+ * don't want to use permitopen_port to avoid
+ * dependency on channels.[ch] here.
+ */
+ if (cp == NULL ||
+ (strcmp(cp, "*") != 0 && a2port(cp) <= 0)) {
+ free(tmp);
+ free(opt);
+ *errstrp = "invalid permission port";
+ return -1;
+ }
+ /* XXX - add streamlocal support */
+ free(tmp);
+ /* Record it */
+ if ((permits = recallocarray(permits, npermits, npermits + 1,
+ sizeof(*permits))) == NULL) {
+ free(opt);
+ /* NB. don't update *permitsp if alloc fails */
+ *errstrp = "memory allocation failed";
+ return -1;
+ }
+ permits[npermits++] = opt;
+ *permitsp = permits;
+ *npermitsp = npermits;
+ return 0;
+}
+
+struct sshauthopt *
+sshauthopt_parse(const char *opts, const char **errstrp)
+{
+ char **oarray, *opt, *cp, *tmp;
+ int r;
+ struct sshauthopt *ret = NULL;
+ const char *errstr = "unknown error";
+ uint64_t valid_before;
+
+ if (errstrp != NULL)
+ *errstrp = NULL;
+ if ((ret = sshauthopt_new_with_keys_defaults()) == NULL)
+ goto alloc_fail;
+
+ if (opts == NULL)
+ return ret;
+
+ while (*opts && *opts != ' ' && *opts != '\t') {
+ /* flag options */
+ if ((r = opt_flag("restrict", 0, &opts)) != -1) {
+ ret->restricted = 1;
+ ret->permit_port_forwarding_flag = 0;
+ ret->permit_agent_forwarding_flag = 0;
+ ret->permit_x11_forwarding_flag = 0;
+ ret->permit_pty_flag = 0;
+ ret->permit_user_rc = 0;
+ } else if ((r = opt_flag("cert-authority", 0, &opts)) != -1) {
+ ret->cert_authority = r;
+ } else if ((r = opt_flag("port-forwarding", 1, &opts)) != -1) {
+ ret->permit_port_forwarding_flag = r == 1;
+ } else if ((r = opt_flag("agent-forwarding", 1, &opts)) != -1) {
+ ret->permit_agent_forwarding_flag = r == 1;
+ } else if ((r = opt_flag("x11-forwarding", 1, &opts)) != -1) {
+ ret->permit_x11_forwarding_flag = r == 1;
+ } else if ((r = opt_flag("touch-required", 1, &opts)) != -1) {
+ ret->no_require_user_presence = r != 1; /* NB. flip */
+ } else if ((r = opt_flag("pty", 1, &opts)) != -1) {
+ ret->permit_pty_flag = r == 1;
+ } else if ((r = opt_flag("user-rc", 1, &opts)) != -1) {
+ ret->permit_user_rc = r == 1;
+ } else if (opt_match(&opts, "command")) {
+ if (ret->force_command != NULL) {
+ errstr = "multiple \"command\" clauses";
+ goto fail;
+ }
+ ret->force_command = opt_dequote(&opts, &errstr);
+ if (ret->force_command == NULL)
+ goto fail;
+ } else if (opt_match(&opts, "principals")) {
+ if (ret->cert_principals != NULL) {
+ errstr = "multiple \"principals\" clauses";
+ goto fail;
+ }
+ ret->cert_principals = opt_dequote(&opts, &errstr);
+ if (ret->cert_principals == NULL)
+ goto fail;
+ } else if (opt_match(&opts, "from")) {
+ if (ret->required_from_host_keys != NULL) {
+ errstr = "multiple \"from\" clauses";
+ goto fail;
+ }
+ ret->required_from_host_keys = opt_dequote(&opts,
+ &errstr);
+ if (ret->required_from_host_keys == NULL)
+ goto fail;
+ } else if (opt_match(&opts, "expiry-time")) {
+ if ((opt = opt_dequote(&opts, &errstr)) == NULL)
+ goto fail;
+ if (parse_absolute_time(opt, &valid_before) != 0 ||
+ valid_before == 0) {
+ free(opt);
+ errstr = "invalid expires time";
+ goto fail;
+ }
+ free(opt);
+ if (ret->valid_before == 0 ||
+ valid_before < ret->valid_before)
+ ret->valid_before = valid_before;
+ } else if (opt_match(&opts, "environment")) {
+ if (ret->nenv > INT_MAX) {
+ errstr = "too many environment strings";
+ goto fail;
+ }
+ if ((opt = opt_dequote(&opts, &errstr)) == NULL)
+ goto fail;
+ /* env name must be alphanumeric and followed by '=' */
+ if ((tmp = strchr(opt, '=')) == NULL) {
+ free(opt);
+ errstr = "invalid environment string";
+ goto fail;
+ }
+ if ((cp = strdup(opt)) == NULL)
+ goto alloc_fail;
+ cp[tmp - opt] = '\0'; /* truncate at '=' */
+ if (!valid_env_name(cp)) {
+ free(cp);
+ free(opt);
+ errstr = "invalid environment string";
+ goto fail;
+ }
+ 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;
+ }
+ ret->env[ret->nenv++] = opt;
+ } else if (opt_match(&opts, "permitopen")) {
+ if (handle_permit(&opts, 0, &ret->permitopen,
+ &ret->npermitopen, &errstr) != 0)
+ goto fail;
+ } else if (opt_match(&opts, "permitlisten")) {
+ if (handle_permit(&opts, 1, &ret->permitlisten,
+ &ret->npermitlisten, &errstr) != 0)
+ goto fail;
+ } else if (opt_match(&opts, "tunnel")) {
+ if ((opt = opt_dequote(&opts, &errstr)) == NULL)
+ goto fail;
+ ret->force_tun_device = a2tun(opt, NULL);
+ free(opt);
+ if (ret->force_tun_device == SSH_TUNID_ERR) {
+ errstr = "invalid tun device";
+ goto fail;
+ }
+ }
+ /*
+ * Skip the comma, and move to the next option
+ * (or break out if there are no more).
+ */
+ if (*opts == '\0' || *opts == ' ' || *opts == '\t')
+ break; /* End of options. */
+ /* Anything other than a comma is an unknown option */
+ if (*opts != ',') {
+ errstr = "unknown key option";
+ goto fail;
+ }
+ opts++;
+ if (*opts == '\0') {
+ errstr = "unexpected end-of-options";
+ goto fail;
+ }
+ }
+
+ /* success */
+ if (errstrp != NULL)
+ *errstrp = NULL;
+ return ret;
+
+alloc_fail:
+ errstr = "memory allocation failed";
+fail:
+ sshauthopt_free(ret);
+ if (errstrp != NULL)
+ *errstrp = errstr;
+ return NULL;
+}
+
+struct sshauthopt *
+sshauthopt_from_cert(struct sshkey *k)
+{
+ struct sshauthopt *ret;
+
+ if (k == NULL || !sshkey_type_is_cert(k->type) || k->cert == NULL ||
+ k->cert->type != SSH2_CERT_TYPE_USER)
+ return NULL;
+
+ if ((ret = sshauthopt_new()) == NULL)
+ return NULL;
+
+ /* Handle options and critical extensions separately */
+ if (cert_option_list(ret, k->cert->critical,
+ OPTIONS_CRITICAL, 1) == -1) {
+ sshauthopt_free(ret);
+ return NULL;
+ }
+ if (cert_option_list(ret, k->cert->extensions,
+ OPTIONS_EXTENSIONS, 0) == -1) {
+ sshauthopt_free(ret);
+ return NULL;
+ }
+ /* success */
+ return ret;
+}
+
+/*
+ * Merges "additional" options to "primary" and returns the result.
+ * NB. Some options from primary have primacy.
+ */
+struct sshauthopt *
+sshauthopt_merge(const struct sshauthopt *primary,
+ const struct sshauthopt *additional, const char **errstrp)
+{
+ struct sshauthopt *ret;
+ const char *errstr = "internal error";
+ const char *tmp;
+
+ if (errstrp != NULL)
+ *errstrp = NULL;
+
+ if ((ret = sshauthopt_new()) == NULL)
+ goto alloc_fail;
+
+ /* cert_authority and cert_principals are cleared in result */
+
+ /* Prefer access lists from primary. */
+ /* XXX err is both set and mismatch? */
+ tmp = primary->required_from_host_cert;
+ if (tmp == NULL)
+ tmp = additional->required_from_host_cert;
+ if (tmp != NULL && (ret->required_from_host_cert = strdup(tmp)) == NULL)
+ goto alloc_fail;
+ tmp = primary->required_from_host_keys;
+ if (tmp == NULL)
+ tmp = additional->required_from_host_keys;
+ if (tmp != NULL && (ret->required_from_host_keys = strdup(tmp)) == NULL)
+ goto alloc_fail;
+
+ /*
+ * force_tun_device, permitopen/permitlisten and environment all
+ * prefer the primary.
+ */
+ ret->force_tun_device = primary->force_tun_device;
+ if (ret->force_tun_device == -1)
+ ret->force_tun_device = additional->force_tun_device;
+ if (primary->nenv > 0) {
+ if (dup_strings(&ret->env, &ret->nenv,
+ primary->env, primary->nenv) != 0)
+ goto alloc_fail;
+ } else if (additional->nenv) {
+ if (dup_strings(&ret->env, &ret->nenv,
+ additional->env, additional->nenv) != 0)
+ goto alloc_fail;
+ }
+ if (primary->npermitopen > 0) {
+ if (dup_strings(&ret->permitopen, &ret->npermitopen,
+ primary->permitopen, primary->npermitopen) != 0)
+ goto alloc_fail;
+ } else if (additional->npermitopen > 0) {
+ if (dup_strings(&ret->permitopen, &ret->npermitopen,
+ additional->permitopen, additional->npermitopen) != 0)
+ goto alloc_fail;
+ }
+
+ if (primary->npermitlisten > 0) {
+ if (dup_strings(&ret->permitlisten, &ret->npermitlisten,
+ primary->permitlisten, primary->npermitlisten) != 0)
+ goto alloc_fail;
+ } else if (additional->npermitlisten > 0) {
+ if (dup_strings(&ret->permitlisten, &ret->npermitlisten,
+ additional->permitlisten, additional->npermitlisten) != 0)
+ goto alloc_fail;
+ }
+
+#define OPTFLAG_AND(x) ret->x = (primary->x == 1) && (additional->x == 1)
+ /* Permissive flags are logical-AND (i.e. must be set in both) */
+ OPTFLAG_AND(permit_port_forwarding_flag);
+ OPTFLAG_AND(permit_agent_forwarding_flag);
+ OPTFLAG_AND(permit_x11_forwarding_flag);
+ OPTFLAG_AND(permit_pty_flag);
+ OPTFLAG_AND(permit_user_rc);
+ OPTFLAG_AND(no_require_user_presence);
+#undef OPTFLAG_AND
+
+ /* Earliest expiry time should win */
+ if (primary->valid_before != 0)
+ ret->valid_before = primary->valid_before;
+ if (additional->valid_before != 0 &&
+ additional->valid_before < ret->valid_before)
+ ret->valid_before = additional->valid_before;
+
+ /*
+ * When both multiple forced-command are specified, only
+ * proceed if they are identical, otherwise fail.
+ */
+ if (primary->force_command != NULL &&
+ additional->force_command != NULL) {
+ if (strcmp(primary->force_command,
+ additional->force_command) == 0) {
+ /* ok */
+ ret->force_command = strdup(primary->force_command);
+ if (ret->force_command == NULL)
+ goto alloc_fail;
+ } else {
+ errstr = "forced command options do not match";
+ goto fail;
+ }
+ } else if (primary->force_command != NULL) {
+ if ((ret->force_command = strdup(
+ primary->force_command)) == NULL)
+ goto alloc_fail;
+ } else if (additional->force_command != NULL) {
+ if ((ret->force_command = strdup(
+ additional->force_command)) == NULL)
+ goto alloc_fail;
+ }
+ /* success */
+ if (errstrp != NULL)
+ *errstrp = NULL;
+ return ret;
+
+ alloc_fail:
+ errstr = "memory allocation failed";
+ fail:
+ if (errstrp != NULL)
+ *errstrp = errstr;
+ sshauthopt_free(ret);
+ return NULL;
+}
+
+/*
+ * Copy options
+ */
+struct sshauthopt *
+sshauthopt_copy(const struct sshauthopt *orig)
+{
+ struct sshauthopt *ret;
+
+ if ((ret = sshauthopt_new()) == NULL)
+ return NULL;
+
+#define OPTSCALAR(x) ret->x = orig->x
+ OPTSCALAR(permit_port_forwarding_flag);
+ OPTSCALAR(permit_agent_forwarding_flag);
+ OPTSCALAR(permit_x11_forwarding_flag);
+ OPTSCALAR(permit_pty_flag);
+ OPTSCALAR(permit_user_rc);
+ OPTSCALAR(restricted);
+ OPTSCALAR(cert_authority);
+ OPTSCALAR(force_tun_device);
+ OPTSCALAR(valid_before);
+ OPTSCALAR(no_require_user_presence);
+#undef OPTSCALAR
+#define OPTSTRING(x) \
+ do { \
+ if (orig->x != NULL && (ret->x = strdup(orig->x)) == NULL) { \
+ sshauthopt_free(ret); \
+ return NULL; \
+ } \
+ } while (0)
+ OPTSTRING(cert_principals);
+ OPTSTRING(force_command);
+ OPTSTRING(required_from_host_cert);
+ OPTSTRING(required_from_host_keys);
+#undef OPTSTRING
+
+ if (dup_strings(&ret->env, &ret->nenv, orig->env, orig->nenv) != 0 ||
+ dup_strings(&ret->permitopen, &ret->npermitopen,
+ orig->permitopen, orig->npermitopen) != 0 ||
+ dup_strings(&ret->permitlisten, &ret->npermitlisten,
+ orig->permitlisten, orig->npermitlisten) != 0) {
+ sshauthopt_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+static int
+serialise_array(struct sshbuf *m, char **a, size_t n)
+{
+ struct sshbuf *b;
+ size_t i;
+ int r;
+
+ if (n > INT_MAX)
+ return SSH_ERR_INTERNAL_ERROR;
+
+ if ((b = sshbuf_new()) == NULL) {
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ for (i = 0; i < n; i++) {
+ if ((r = sshbuf_put_cstring(b, a[i])) != 0) {
+ sshbuf_free(b);
+ return r;
+ }
+ }
+ if ((r = sshbuf_put_u32(m, n)) != 0 ||
+ (r = sshbuf_put_stringb(m, b)) != 0) {
+ sshbuf_free(b);
+ return r;
}
+ /* success */
+ return 0;
+}
- no_port_forwarding_flag |= cert_no_port_forwarding_flag;
- no_agent_forwarding_flag |= cert_no_agent_forwarding_flag;
- no_x11_forwarding_flag |= cert_no_x11_forwarding_flag;
- no_pty_flag |= cert_no_pty_flag;
- no_user_rc |= cert_no_user_rc;
- /* CA-specified forced command supersedes key option */
- if (cert_forced_command != NULL) {
- if (forced_command != NULL)
- free(forced_command);
- forced_command = cert_forced_command;
+static int
+deserialise_array(struct sshbuf *m, char ***ap, size_t *np)
+{
+ char **a = NULL;
+ size_t i, n = 0;
+ struct sshbuf *b = NULL;
+ u_int tmp;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if ((r = sshbuf_get_u32(m, &tmp)) != 0 ||
+ (r = sshbuf_froms(m, &b)) != 0)
+ goto out;
+ if (tmp > INT_MAX) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
}
+ n = tmp;
+ if (n > 0 && (a = calloc(n, sizeof(*a))) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ for (i = 0; i < n; i++) {
+ if ((r = sshbuf_get_cstring(b, &a[i], NULL)) != 0)
+ goto out;
+ }
+ /* success */
+ r = 0;
+ *ap = a;
+ a = NULL;
+ *np = n;
+ n = 0;
+ out:
+ if (a != NULL) {
+ for (i = 0; i < n; i++)
+ free(a[i]);
+ free(a);
+ }
+ sshbuf_free(b);
+ return r;
+}
+
+static int
+serialise_nullable_string(struct sshbuf *m, const char *s)
+{
+ int r;
+
+ if ((r = sshbuf_put_u8(m, s == NULL)) != 0 ||
+ (r = sshbuf_put_cstring(m, s)) != 0)
+ return r;
+ return 0;
+}
+
+static int
+deserialise_nullable_string(struct sshbuf *m, char **sp)
+{
+ int r;
+ u_char flag;
+
+ *sp = NULL;
+ if ((r = sshbuf_get_u8(m, &flag)) != 0 ||
+ (r = sshbuf_get_cstring(m, flag ? NULL : sp, NULL)) != 0)
+ return r;
return 0;
}
+int
+sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m,
+ int untrusted)
+{
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ /* Flag options */
+ if ((r = sshbuf_put_u8(m, opts->permit_port_forwarding_flag)) != 0 ||
+ (r = sshbuf_put_u8(m, opts->permit_agent_forwarding_flag)) != 0 ||
+ (r = sshbuf_put_u8(m, opts->permit_x11_forwarding_flag)) != 0 ||
+ (r = sshbuf_put_u8(m, opts->permit_pty_flag)) != 0 ||
+ (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)
+ return r;
+
+ /* Simple integer options */
+ if ((r = sshbuf_put_u64(m, opts->valid_before)) != 0)
+ return r;
+
+ /* tunnel number can be negative to indicate "unset" */
+ if ((r = sshbuf_put_u8(m, opts->force_tun_device == -1)) != 0 ||
+ (r = sshbuf_put_u32(m, (opts->force_tun_device < 0) ?
+ 0 : (u_int)opts->force_tun_device)) != 0)
+ return r;
+
+ /* String options; these may be NULL */
+ if ((r = serialise_nullable_string(m,
+ untrusted ? "yes" : opts->cert_principals)) != 0 ||
+ (r = serialise_nullable_string(m,
+ untrusted ? "true" : opts->force_command)) != 0 ||
+ (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)
+ return r;
+
+ /* Array options */
+ if ((r = serialise_array(m, opts->env,
+ untrusted ? 0 : opts->nenv)) != 0 ||
+ (r = serialise_array(m, opts->permitopen,
+ untrusted ? 0 : opts->npermitopen)) != 0 ||
+ (r = serialise_array(m, opts->permitlisten,
+ untrusted ? 0 : opts->npermitlisten)) != 0)
+ return r;
+
+ /* success */
+ return 0;
+}
+
+int
+sshauthopt_deserialise(struct sshbuf *m, struct sshauthopt **optsp)
+{
+ struct sshauthopt *opts = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ u_char f;
+ u_int tmp;
+
+ if ((opts = calloc(1, sizeof(*opts))) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+
+ /* Flag options */
+#define OPT_FLAG(x) \
+ do { \
+ if ((r = sshbuf_get_u8(m, &f)) != 0) \
+ goto out; \
+ opts->x = f; \
+ } while (0)
+ OPT_FLAG(permit_port_forwarding_flag);
+ OPT_FLAG(permit_agent_forwarding_flag);
+ OPT_FLAG(permit_x11_forwarding_flag);
+ OPT_FLAG(permit_pty_flag);
+ OPT_FLAG(permit_user_rc);
+ OPT_FLAG(restricted);
+ OPT_FLAG(cert_authority);
+ OPT_FLAG(no_require_user_presence);
+#undef OPT_FLAG
+
+ /* Simple integer options */
+ if ((r = sshbuf_get_u64(m, &opts->valid_before)) != 0)
+ goto out;
+
+ /* tunnel number can be negative to indicate "unset" */
+ if ((r = sshbuf_get_u8(m, &f)) != 0 ||
+ (r = sshbuf_get_u32(m, &tmp)) != 0)
+ goto out;
+ opts->force_tun_device = f ? -1 : (int)tmp;
+
+ /* String options may be NULL */
+ if ((r = deserialise_nullable_string(m, &opts->cert_principals)) != 0 ||
+ (r = deserialise_nullable_string(m, &opts->force_command)) != 0 ||
+ (r = deserialise_nullable_string(m,
+ &opts->required_from_host_cert)) != 0 ||
+ (r = deserialise_nullable_string(m,
+ &opts->required_from_host_keys)) != 0)
+ goto out;
+
+ /* Array options */
+ if ((r = deserialise_array(m, &opts->env, &opts->nenv)) != 0 ||
+ (r = deserialise_array(m,
+ &opts->permitopen, &opts->npermitopen)) != 0 ||
+ (r = deserialise_array(m,
+ &opts->permitlisten, &opts->npermitlisten)) != 0)
+ goto out;
+
+ /* success */
+ r = 0;
+ *optsp = opts;
+ opts = NULL;
+ out:
+ sshauthopt_free(opts);
+ return r;
+}
diff --git a/auth-options.h b/auth-options.h
index 34852e5c..d96ffede 100644
--- a/auth-options.h
+++ b/auth-options.h
@@ -1,40 +1,101 @@
-/* $OpenBSD: auth-options.h,v 1.21 2015/01/14 10:30:34 markus Exp $ */
+/* $OpenBSD: auth-options.h,v 1.29 2019/11/25 00:54:23 djm Exp $ */
/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
+ * Copyright (c) 2018 Damien Miller <djm@mindrot.org>
*
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef AUTH_OPTIONS_H
#define AUTH_OPTIONS_H
-/* Linked list of custom environment strings */
-struct envstring {
- struct envstring *next;
- char *s;
+struct passwd;
+struct sshkey;
+
+/* Maximum number of permitopen/permitlisten directives to accept */
+#define SSH_AUTHOPT_PERMIT_MAX 4096
+
+/*
+ * sshauthopt represents key options parsed from authorized_keys or
+ * from certificate extensions/options.
+ */
+struct sshauthopt {
+ /* Feature flags */
+ int permit_port_forwarding_flag;
+ int permit_agent_forwarding_flag;
+ int permit_x11_forwarding_flag;
+ int permit_pty_flag;
+ int permit_user_rc;
+
+ /* "restrict" keyword was invoked */
+ int restricted;
+
+ /* key/principal expiry date */
+ uint64_t valid_before;
+
+ /* Certificate-related options */
+ int cert_authority;
+ char *cert_principals;
+
+ int force_tun_device;
+ char *force_command;
+
+ /* Custom environment */
+ size_t nenv;
+ char **env;
+
+ /* Permitted port forwardings */
+ size_t npermitopen;
+ char **permitopen;
+
+ /* Permitted listens (remote forwarding) */
+ size_t npermitlisten;
+ char **permitlisten;
+
+ /*
+ * Permitted host/addresses (comma-separated)
+ * Caller must check source address matches both lists (if present).
+ */
+ char *required_from_host_cert;
+ char *required_from_host_keys;
+
+ /* Key requires user presence asserted */
+ int no_require_user_presence;
};
-/* Flags that may be set in authorized_keys options. */
-extern int no_port_forwarding_flag;
-extern int no_agent_forwarding_flag;
-extern int no_x11_forwarding_flag;
-extern int no_pty_flag;
-extern int no_user_rc;
-extern char *forced_command;
-extern struct envstring *custom_environment;
-extern int forced_tun_device;
-extern int key_is_cert_authority;
-extern char *authorized_principals;
-
-int auth_parse_options(struct passwd *, char *, char *, u_long);
-void auth_clear_options(void);
-int auth_cert_options(struct sshkey *, struct passwd *);
+struct sshauthopt *sshauthopt_new(void);
+struct sshauthopt *sshauthopt_new_with_keys_defaults(void);
+void sshauthopt_free(struct sshauthopt *opts);
+struct sshauthopt *sshauthopt_copy(const struct sshauthopt *orig);
+int sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m, int);
+int sshauthopt_deserialise(struct sshbuf *m, struct sshauthopt **opts);
+
+/*
+ * Parse authorized_keys options. Returns an options structure on success
+ * or NULL on failure. Will set errstr on failure.
+ */
+struct sshauthopt *sshauthopt_parse(const char *s, const char **errstr);
+
+/*
+ * Parse certification options to a struct sshauthopt.
+ * Returns options on success or NULL on failure.
+ */
+struct sshauthopt *sshauthopt_from_cert(struct sshkey *k);
+
+/*
+ * Merge key options.
+ */
+struct sshauthopt *sshauthopt_merge(const struct sshauthopt *primary,
+ const struct sshauthopt *additional, const char **errstrp);
#endif
diff --git a/auth-pam.c b/auth-pam.c
index d789bad7..5a3ba09b 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -45,7 +45,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* Based on $FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */
+/* Based on FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des */
+
#include "includes.h"
#include <sys/types.h>
@@ -55,6 +56,7 @@
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -65,11 +67,16 @@
#include <pam/pam_appl.h>
#endif
+#if !defined(SSHD_PAM_SERVICE)
+extern char *__progname;
+# define SSHD_PAM_SERVICE __progname
+#endif
+
/* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */
#ifdef PAM_SUN_CODEBASE
-# define sshpam_const /* Solaris, HP-UX, AIX */
+# define sshpam_const /* Solaris, HP-UX, SunOS */
#else
-# define sshpam_const const /* LinuxPAM, OpenPAM */
+# define sshpam_const const /* LinuxPAM, OpenPAM, AIX */
#endif
/* Ambiguity in spec: is it an array of pointers or a pointer to an array? */
@@ -80,8 +87,8 @@
#endif
#include "xmalloc.h"
-#include "buffer.h"
-#include "key.h"
+#include "sshbuf.h"
+#include "ssherr.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-pam.h"
@@ -93,14 +100,14 @@
#include "servconf.h"
#include "ssh2.h"
#include "auth-options.h"
+#include "misc.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
extern ServerOptions options;
-extern Buffer loginmsg;
-extern int compat20;
+extern struct sshbuf *loginmsg;
extern u_int utmp_len;
/* so we don't silently change behaviour */
@@ -123,6 +130,10 @@ extern u_int utmp_len;
typedef pthread_t sp_pthread_t;
#else
typedef pid_t sp_pthread_t;
+#define pthread_exit fake_pthread_exit
+#define pthread_create fake_pthread_create
+#define pthread_cancel fake_pthread_cancel
+#define pthread_join fake_pthread_join
#endif
struct pam_ctxt {
@@ -141,21 +152,24 @@ static struct pam_ctxt *cleanup_ctxt;
*/
static int sshpam_thread_status = -1;
-static mysig_t sshpam_oldsig;
+static sshsig_t sshpam_oldsig;
static void
sshpam_sigchld_handler(int sig)
{
- signal(SIGCHLD, SIG_DFL);
+ ssh_signal(SIGCHLD, SIG_DFL);
if (cleanup_ctxt == NULL)
return; /* handler called after PAM cleanup, shouldn't happen */
if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG)
<= 0) {
/* PAM thread has not exitted, privsep slave must have */
kill(cleanup_ctxt->pam_thread, SIGTERM);
- if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0)
- <= 0)
- return; /* could not wait */
+ while (waitpid(cleanup_ctxt->pam_thread,
+ &sshpam_thread_status, 0) == -1) {
+ if (errno == EINTR)
+ continue;
+ return;
+ }
}
if (WIFSIGNALED(sshpam_thread_status) &&
WTERMSIG(sshpam_thread_status) == SIGTERM)
@@ -185,7 +199,7 @@ pthread_create(sp_pthread_t *thread, const void *attr,
switch ((pid = fork())) {
case -1:
error("fork(): %s", strerror(errno));
- return (-1);
+ return errno;
case 0:
close(ctx->pam_psock);
ctx->pam_psock = -1;
@@ -195,7 +209,7 @@ pthread_create(sp_pthread_t *thread, const void *attr,
*thread = pid;
close(ctx->pam_csock);
ctx->pam_csock = -1;
- sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler);
+ sshpam_oldsig = ssh_signal(SIGCHLD, sshpam_sigchld_handler);
return (0);
}
}
@@ -203,7 +217,7 @@ pthread_create(sp_pthread_t *thread, const void *attr,
static int
pthread_cancel(sp_pthread_t thread)
{
- signal(SIGCHLD, sshpam_oldsig);
+ ssh_signal(SIGCHLD, sshpam_oldsig);
return (kill(thread, SIGTERM));
}
@@ -215,8 +229,12 @@ pthread_join(sp_pthread_t thread, void **value)
if (sshpam_thread_status != -1)
return (sshpam_thread_status);
- signal(SIGCHLD, sshpam_oldsig);
- waitpid(thread, &status, 0);
+ ssh_signal(SIGCHLD, sshpam_oldsig);
+ while (waitpid(thread, &status, 0) == -1) {
+ if (errno == EINTR)
+ continue;
+ fatal("%s: waitpid: %s", __func__, strerror(errno));
+ }
return (status);
}
#endif
@@ -228,10 +246,13 @@ static int sshpam_authenticated = 0;
static int sshpam_session_open = 0;
static int sshpam_cred_established = 0;
static int sshpam_account_status = -1;
+static int sshpam_maxtries_reached = 0;
static char **sshpam_env = NULL;
static Authctxt *sshpam_authctxt = NULL;
static const char *sshpam_password = NULL;
-static char badpw[] = "\b\n\r\177INCORRECT";
+static char *sshpam_rhost = NULL;
+static char *sshpam_laddr = NULL;
+static char *sshpam_conninfo = NULL;
/* Some PAM implementations don't implement this */
#ifndef HAVE_PAM_GETENVLIST
@@ -239,7 +260,7 @@ static char **
pam_getenvlist(pam_handle_t *pamh)
{
/*
- * XXX - If necessary, we can still support envrionment passing
+ * XXX - If necessary, we can still support environment passing
* for platforms without pam_getenvlist by searching for known
* env vars (e.g. KRB5CCNAME) from the PAM environment.
*/
@@ -247,6 +268,14 @@ pam_getenvlist(pam_handle_t *pamh)
}
#endif
+#ifndef HAVE_PAM_PUTENV
+static int
+pam_putenv(pam_handle_t *pamh, const char *name_value)
+{
+ return PAM_SUCCESS;
+}
+#endif /* HAVE_PAM_PUTENV */
+
/*
* Some platforms, notably Solaris, do not enforce password complexity
* rules during pam_chauthtok() if the real uid of the calling process
@@ -272,64 +301,81 @@ sshpam_chauthtok_ruid(pam_handle_t *pamh, int flags)
# define pam_chauthtok(a,b) (sshpam_chauthtok_ruid((a), (b)))
#endif
-void
+static void
sshpam_password_change_required(int reqd)
{
+ extern struct sshauthopt *auth_opts;
+ static int saved_port, saved_agent, saved_x11;
+
debug3("%s %d", __func__, reqd);
if (sshpam_authctxt == NULL)
fatal("%s: PAM authctxt not initialized", __func__);
sshpam_authctxt->force_pwchange = reqd;
if (reqd) {
- no_port_forwarding_flag |= 2;
- no_agent_forwarding_flag |= 2;
- no_x11_forwarding_flag |= 2;
+ saved_port = auth_opts->permit_port_forwarding_flag;
+ saved_agent = auth_opts->permit_agent_forwarding_flag;
+ saved_x11 = auth_opts->permit_x11_forwarding_flag;
+ auth_opts->permit_port_forwarding_flag = 0;
+ auth_opts->permit_agent_forwarding_flag = 0;
+ auth_opts->permit_x11_forwarding_flag = 0;
} else {
- no_port_forwarding_flag &= ~2;
- no_agent_forwarding_flag &= ~2;
- no_x11_forwarding_flag &= ~2;
+ if (saved_port)
+ auth_opts->permit_port_forwarding_flag = saved_port;
+ if (saved_agent)
+ auth_opts->permit_agent_forwarding_flag = saved_agent;
+ if (saved_x11)
+ auth_opts->permit_x11_forwarding_flag = saved_x11;
}
}
/* Import regular and PAM environment from subprocess */
static void
-import_environments(Buffer *b)
+import_environments(struct sshbuf *b)
{
char *env;
- u_int i, num_env;
- int err;
+ u_int n, i, num_env;
+ int r;
debug3("PAM: %s entering", __func__);
#ifndef UNSUPPORTED_POSIX_THREADS_HACK
/* Import variables set by do_pam_account */
- sshpam_account_status = buffer_get_int(b);
- sshpam_password_change_required(buffer_get_int(b));
+ if ((r = sshbuf_get_u32(b, &n)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (n > INT_MAX)
+ fatal("%s: invalid PAM account status %u", __func__, n);
+ sshpam_account_status = (int)n;
+ if ((r = sshbuf_get_u32(b, &n)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ sshpam_password_change_required(n != 0);
/* Import environment from subprocess */
- num_env = buffer_get_int(b);
+ if ((r = sshbuf_get_u32(b, &num_env)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (num_env > 1024)
fatal("%s: received %u environment variables, expected <= 1024",
__func__, num_env);
sshpam_env = xcalloc(num_env + 1, sizeof(*sshpam_env));
debug3("PAM: num env strings %d", num_env);
- for(i = 0; i < num_env; i++)
- sshpam_env[i] = buffer_get_string(b, NULL);
-
+ for(i = 0; i < num_env; i++) {
+ if ((r = sshbuf_get_cstring(b, &(sshpam_env[i]), NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ }
sshpam_env[num_env] = NULL;
/* Import PAM environment from subprocess */
- num_env = buffer_get_int(b);
+ if ((r = sshbuf_get_u32(b, &num_env)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug("PAM: num PAM env strings %d", num_env);
- for(i = 0; i < num_env; i++) {
- env = buffer_get_string(b, NULL);
-
-#ifdef HAVE_PAM_PUTENV
+ for (i = 0; i < num_env; i++) {
+ if ((r = sshbuf_get_cstring(b, &env, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* Errors are not fatal here */
- if ((err = pam_putenv(sshpam_handle, env)) != PAM_SUCCESS) {
+ if ((r = pam_putenv(sshpam_handle, env)) != PAM_SUCCESS) {
error("PAM: pam_putenv: %s",
- pam_strerror(sshpam_handle, sshpam_err));
+ pam_strerror(sshpam_handle, r));
}
-#endif
+ /* XXX leak env? */
}
#endif
}
@@ -341,10 +387,11 @@ static int
sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
- Buffer buffer;
+ struct sshbuf *buffer;
struct pam_ctxt *ctxt;
struct pam_response *reply;
- int i;
+ int r, i;
+ u_char status;
debug3("PAM: %s entering, %d messages", __func__, n);
*resp = NULL;
@@ -358,55 +405,52 @@ sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
return (PAM_CONV_ERR);
if ((reply = calloc(n, sizeof(*reply))) == NULL)
- return (PAM_CONV_ERR);
+ return PAM_CONV_ERR;
+ if ((buffer = sshbuf_new()) == NULL) {
+ free(reply);
+ return PAM_CONV_ERR;
+ }
- buffer_init(&buffer);
for (i = 0; i < n; ++i) {
switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
case PAM_PROMPT_ECHO_OFF:
- buffer_put_cstring(&buffer,
- PAM_MSG_MEMBER(msg, i, msg));
- if (ssh_msg_send(ctxt->pam_csock,
- PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
- goto fail;
- if (ssh_msg_recv(ctxt->pam_csock, &buffer) == -1)
- goto fail;
- if (buffer_get_char(&buffer) != PAM_AUTHTOK)
- goto fail;
- reply[i].resp = buffer_get_string(&buffer, NULL);
- break;
case PAM_PROMPT_ECHO_ON:
- buffer_put_cstring(&buffer,
- PAM_MSG_MEMBER(msg, i, msg));
+ if ((r = sshbuf_put_cstring(buffer,
+ PAM_MSG_MEMBER(msg, i, msg))) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
if (ssh_msg_send(ctxt->pam_csock,
- PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
+ PAM_MSG_MEMBER(msg, i, msg_style), buffer) == -1)
goto fail;
- if (ssh_msg_recv(ctxt->pam_csock, &buffer) == -1)
+
+ if (ssh_msg_recv(ctxt->pam_csock, buffer) == -1)
goto fail;
- if (buffer_get_char(&buffer) != PAM_AUTHTOK)
+ if ((r = sshbuf_get_u8(buffer, &status)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
+ if (status != PAM_AUTHTOK)
goto fail;
- reply[i].resp = buffer_get_string(&buffer, NULL);
+ if ((r = sshbuf_get_cstring(buffer,
+ &reply[i].resp, NULL)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
break;
case PAM_ERROR_MSG:
- buffer_put_cstring(&buffer,
- PAM_MSG_MEMBER(msg, i, msg));
- if (ssh_msg_send(ctxt->pam_csock,
- PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
- goto fail;
- break;
case PAM_TEXT_INFO:
- buffer_put_cstring(&buffer,
- PAM_MSG_MEMBER(msg, i, msg));
+ if ((r = sshbuf_put_cstring(buffer,
+ PAM_MSG_MEMBER(msg, i, msg))) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
if (ssh_msg_send(ctxt->pam_csock,
- PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
+ PAM_MSG_MEMBER(msg, i, msg_style), buffer) == -1)
goto fail;
break;
default:
goto fail;
}
- buffer_clear(&buffer);
+ sshbuf_reset(buffer);
}
- buffer_free(&buffer);
+ sshbuf_free(buffer);
*resp = reply;
return (PAM_SUCCESS);
@@ -415,7 +459,7 @@ sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
free(reply[i].resp);
}
free(reply);
- buffer_free(&buffer);
+ sshbuf_free(buffer);
return (PAM_CONV_ERR);
}
@@ -426,9 +470,9 @@ static void *
sshpam_thread(void *ctxtp)
{
struct pam_ctxt *ctxt = ctxtp;
- Buffer buffer;
+ struct sshbuf *buffer = NULL;
struct pam_conv sshpam_conv;
- int flags = (options.permit_empty_passwd == 0 ?
+ int r, flags = (options.permit_empty_passwd == 0 ?
PAM_DISALLOW_NULL_AUTHTOK : 0);
#ifndef UNSUPPORTED_POSIX_THREADS_HACK
extern char **environ;
@@ -461,66 +505,84 @@ sshpam_thread(void *ctxtp)
if (sshpam_authctxt == NULL)
fatal("%s: PAM authctxt not initialized", __func__);
- buffer_init(&buffer);
+ if ((buffer = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
(const void *)&sshpam_conv);
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
sshpam_err = pam_authenticate(sshpam_handle, flags);
+ if (sshpam_err == PAM_MAXTRIES)
+ sshpam_set_maxtries_reached(1);
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
- if (compat20) {
- if (!do_pam_account()) {
- sshpam_err = PAM_ACCT_EXPIRED;
+ if (!do_pam_account()) {
+ sshpam_err = PAM_ACCT_EXPIRED;
+ goto auth_fail;
+ }
+ if (sshpam_authctxt->force_pwchange) {
+ sshpam_err = pam_chauthtok(sshpam_handle,
+ PAM_CHANGE_EXPIRED_AUTHTOK);
+ if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
- }
- if (sshpam_authctxt->force_pwchange) {
- sshpam_err = pam_chauthtok(sshpam_handle,
- PAM_CHANGE_EXPIRED_AUTHTOK);
- if (sshpam_err != PAM_SUCCESS)
- goto auth_fail;
- sshpam_password_change_required(0);
- }
+ sshpam_password_change_required(0);
}
- buffer_put_cstring(&buffer, "OK");
+ if ((r = sshbuf_put_cstring(buffer, "OK")) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
#ifndef UNSUPPORTED_POSIX_THREADS_HACK
/* Export variables set by do_pam_account */
- buffer_put_int(&buffer, sshpam_account_status);
- buffer_put_int(&buffer, sshpam_authctxt->force_pwchange);
+ if ((r = sshbuf_put_u32(buffer, sshpam_account_status)) != 0 ||
+ (r = sshbuf_put_u32(buffer, sshpam_authctxt->force_pwchange)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* Export any environment strings set in child */
- for(i = 0; environ[i] != NULL; i++)
- ; /* Count */
- buffer_put_int(&buffer, i);
- for(i = 0; environ[i] != NULL; i++)
- buffer_put_cstring(&buffer, environ[i]);
-
+ for (i = 0; environ[i] != NULL; i++) {
+ /* Count */
+ if (i > INT_MAX)
+ fatal("%s: too many environment strings", __func__);
+ }
+ if ((r = sshbuf_put_u32(buffer, i)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ for (i = 0; environ[i] != NULL; i++) {
+ if ((r = sshbuf_put_cstring(buffer, environ[i])) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ }
/* Export any environment strings set by PAM in child */
env_from_pam = pam_getenvlist(sshpam_handle);
- for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++)
- ; /* Count */
- buffer_put_int(&buffer, i);
- for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++)
- buffer_put_cstring(&buffer, env_from_pam[i]);
+ for (i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) {
+ /* Count */
+ if (i > INT_MAX)
+ fatal("%s: too many PAM environment strings", __func__);
+ }
+ if ((r = sshbuf_put_u32(buffer, i)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ for (i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) {
+ if ((r = sshbuf_put_cstring(buffer, env_from_pam[i])) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ }
#endif /* UNSUPPORTED_POSIX_THREADS_HACK */
/* XXX - can't do much about an error here */
- ssh_msg_send(ctxt->pam_csock, sshpam_err, &buffer);
- buffer_free(&buffer);
+ ssh_msg_send(ctxt->pam_csock, sshpam_err, buffer);
+ sshbuf_free(buffer);
pthread_exit(NULL);
auth_fail:
- buffer_put_cstring(&buffer,
- pam_strerror(sshpam_handle, sshpam_err));
+ if ((r = sshbuf_put_cstring(buffer,
+ pam_strerror(sshpam_handle, sshpam_err))) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* XXX - can't do much about an error here */
if (sshpam_err == PAM_ACCT_EXPIRED)
- ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, &buffer);
+ ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, buffer);
+ else if (sshpam_maxtries_reached)
+ ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, buffer);
else
- ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer);
- buffer_free(&buffer);
+ ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, buffer);
+ sshbuf_free(buffer);
pthread_exit(NULL);
return (NULL); /* Avoid warning for non-pthread case */
@@ -557,8 +619,7 @@ sshpam_store_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
struct pam_response *reply;
- int i;
- size_t len;
+ int r, i;
debug3("PAM: %s called with %d messages", __func__, n);
*resp = NULL;
@@ -573,9 +634,10 @@ sshpam_store_conv(int n, sshpam_const struct pam_message **msg,
switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
- len = strlen(PAM_MSG_MEMBER(msg, i, msg));
- buffer_append(&loginmsg, PAM_MSG_MEMBER(msg, i, msg), len);
- buffer_append(&loginmsg, "\n", 1 );
+ if ((r = sshbuf_putf(loginmsg, "%s\n",
+ PAM_MSG_MEMBER(msg, i, msg))) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
reply[i].resp_retcode = PAM_SUCCESS;
break;
default:
@@ -618,13 +680,17 @@ sshpam_cleanup(void)
}
static int
-sshpam_init(Authctxt *authctxt)
+sshpam_init(struct ssh *ssh, Authctxt *authctxt)
{
- extern char *__progname;
- const char *pam_rhost, *pam_user, *user = authctxt->user;
+ const char *pam_user, *user = authctxt->user;
const char **ptr_pam_user = &pam_user;
- if (sshpam_handle != NULL) {
+ if (sshpam_handle == NULL) {
+ if (ssh == NULL) {
+ fatal("%s: called initially with no "
+ "packet context", __func__);
+ }
+ } if (sshpam_handle != NULL) {
/* We already have a PAM context; check if the user matches */
sshpam_err = pam_get_item(sshpam_handle,
PAM_USER, (sshpam_const void **)ptr_pam_user);
@@ -643,14 +709,33 @@ sshpam_init(Authctxt *authctxt)
sshpam_handle = NULL;
return (-1);
}
- pam_rhost = get_remote_name_or_ip(utmp_len, options.use_dns);
- debug("PAM: setting PAM_RHOST to \"%s\"", pam_rhost);
- sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);
- if (sshpam_err != PAM_SUCCESS) {
- pam_end(sshpam_handle, sshpam_err);
- sshpam_handle = NULL;
- return (-1);
+
+ if (ssh != NULL && sshpam_rhost == NULL) {
+ /*
+ * We need to cache these as we don't have packet context
+ * during the kbdint flow.
+ */
+ sshpam_rhost = xstrdup(auth_get_canonical_hostname(ssh,
+ options.use_dns));
+ sshpam_laddr = get_local_ipaddr(
+ ssh_packet_get_connection_in(ssh));
+ xasprintf(&sshpam_conninfo, "SSH_CONNECTION=%.50s %d %.50s %d",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+ sshpam_laddr, ssh_local_port(ssh));
}
+ if (sshpam_rhost != NULL) {
+ debug("PAM: setting PAM_RHOST to \"%s\"", sshpam_rhost);
+ sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST,
+ sshpam_rhost);
+ if (sshpam_err != PAM_SUCCESS) {
+ pam_end(sshpam_handle, sshpam_err);
+ sshpam_handle = NULL;
+ return (-1);
+ }
+ /* Put SSH_CONNECTION in the PAM environment too */
+ pam_putenv(sshpam_handle, sshpam_conninfo);
+ }
+
#ifdef PAM_TTY_KLUDGE
/*
* Some silly PAM modules (e.g. pam_time) require a TTY to operate.
@@ -668,11 +753,32 @@ sshpam_init(Authctxt *authctxt)
return (0);
}
+static void
+expose_authinfo(const char *caller)
+{
+ char *auth_info;
+
+ /*
+ * Expose authentication information to PAM.
+ * The environment variable is versioned. Please increment the
+ * version suffix if the format of session_info changes.
+ */
+ if (sshpam_authctxt->session_info == NULL)
+ auth_info = xstrdup("");
+ else if ((auth_info = sshbuf_dup_string(
+ sshpam_authctxt->session_info)) == NULL)
+ fatal("%s: sshbuf_dup_string failed", __func__);
+
+ debug2("%s: auth information in SSH_AUTH_INFO_0", caller);
+ do_pam_putenv("SSH_AUTH_INFO_0", auth_info);
+ free(auth_info);
+}
+
static void *
sshpam_init_ctx(Authctxt *authctxt)
{
struct pam_ctxt *ctxt;
- int socks[2];
+ int result, socks[2];
debug3("PAM: %s entering", __func__);
/*
@@ -683,11 +789,12 @@ sshpam_init_ctx(Authctxt *authctxt)
return NULL;
/* Initialize PAM */
- if (sshpam_init(authctxt) == -1) {
+ if (sshpam_init(NULL, authctxt) == -1) {
error("PAM: initialization failed");
return (NULL);
}
+ expose_authinfo(__func__);
ctxt = xcalloc(1, sizeof *ctxt);
/* Start the authentication thread */
@@ -698,9 +805,10 @@ sshpam_init_ctx(Authctxt *authctxt)
}
ctxt->pam_psock = socks[0];
ctxt->pam_csock = socks[1];
- if (pthread_create(&ctxt->pam_thread, NULL, sshpam_thread, ctxt) == -1) {
+ result = pthread_create(&ctxt->pam_thread, NULL, sshpam_thread, ctxt);
+ if (result != 0) {
error("PAM: failed to start authentication thread: %s",
- strerror(errno));
+ strerror(result));
close(socks[0]);
close(socks[1]);
free(ctxt);
@@ -714,41 +822,44 @@ static int
sshpam_query(void *ctx, char **name, char **info,
u_int *num, char ***prompts, u_int **echo_on)
{
- Buffer buffer;
+ struct sshbuf *buffer;
struct pam_ctxt *ctxt = ctx;
size_t plen;
u_char type;
char *msg;
size_t len, mlen;
+ int r;
debug3("PAM: %s entering", __func__);
- buffer_init(&buffer);
+ if ((buffer = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
*name = xstrdup("");
*info = xstrdup("");
*prompts = xmalloc(sizeof(char *));
**prompts = NULL;
plen = 0;
*echo_on = xmalloc(sizeof(u_int));
- while (ssh_msg_recv(ctxt->pam_psock, &buffer) == 0) {
- type = buffer_get_char(&buffer);
- msg = buffer_get_string(&buffer, NULL);
- mlen = strlen(msg);
+ while (ssh_msg_recv(ctxt->pam_psock, buffer) == 0) {
+ if ((r = sshbuf_get_u8(buffer, &type)) != 0 ||
+ (r = sshbuf_get_cstring(buffer, &msg, &mlen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
switch (type) {
case PAM_PROMPT_ECHO_ON:
case PAM_PROMPT_ECHO_OFF:
*num = 1;
len = plen + mlen + 1;
- **prompts = xrealloc(**prompts, 1, len);
+ **prompts = xreallocarray(**prompts, 1, len);
strlcpy(**prompts + plen, msg, len - plen);
plen += mlen;
**echo_on = (type == PAM_PROMPT_ECHO_ON);
free(msg);
+ sshbuf_free(buffer);
return (0);
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
/* accumulate messages */
len = plen + mlen + 2;
- **prompts = xrealloc(**prompts, 1, len);
+ **prompts = xreallocarray(**prompts, 1, len);
strlcpy(**prompts + plen, msg, len - plen);
plen += mlen;
strlcat(**prompts + plen, "\n", len - plen);
@@ -756,7 +867,11 @@ sshpam_query(void *ctx, char **name, char **info,
free(msg);
break;
case PAM_ACCT_EXPIRED:
- sshpam_account_status = 0;
+ case PAM_MAXTRIES:
+ if (type == PAM_ACCT_EXPIRED)
+ sshpam_account_status = 0;
+ if (type == PAM_MAXTRIES)
+ sshpam_set_maxtries_reached(1);
/* FALLTHROUGH */
case PAM_AUTH_ERR:
debug3("PAM: %s", pam_strerror(sshpam_handle, type));
@@ -767,6 +882,7 @@ sshpam_query(void *ctx, char **name, char **info,
**echo_on = 0;
ctxt->pam_done = -1;
free(msg);
+ sshbuf_free(buffer);
return 0;
}
/* FALLTHROUGH */
@@ -774,8 +890,10 @@ sshpam_query(void *ctx, char **name, char **info,
if (**prompts != NULL) {
/* drain any accumulated messages */
debug("PAM: %s", **prompts);
- buffer_append(&loginmsg, **prompts,
- strlen(**prompts));
+ if ((r = sshbuf_put(loginmsg, **prompts,
+ strlen(**prompts))) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
free(**prompts);
**prompts = NULL;
}
@@ -786,35 +904,63 @@ sshpam_query(void *ctx, char **name, char **info,
fatal("Internal error: PAM auth "
"succeeded when it should have "
"failed");
- import_environments(&buffer);
+ import_environments(buffer);
*num = 0;
**echo_on = 0;
ctxt->pam_done = 1;
free(msg);
+ sshbuf_free(buffer);
return (0);
}
error("PAM: %s for %s%.100s from %.100s", msg,
sshpam_authctxt->valid ? "" : "illegal user ",
- sshpam_authctxt->user,
- get_remote_name_or_ip(utmp_len, options.use_dns));
+ sshpam_authctxt->user, sshpam_rhost);
/* FALLTHROUGH */
default:
*num = 0;
**echo_on = 0;
free(msg);
ctxt->pam_done = -1;
+ sshbuf_free(buffer);
return (-1);
}
}
+ sshbuf_free(buffer);
return (-1);
}
+/*
+ * Returns a junk password of identical length to that the user supplied.
+ * Used to mitigate timing attacks against crypt(3)/PAM stacks that
+ * vary processing time in proportion to password length.
+ */
+static char *
+fake_password(const char *wire_password)
+{
+ const char junk[] = "\b\n\r\177INCORRECT";
+ char *ret = NULL;
+ size_t i, l = wire_password != NULL ? strlen(wire_password) : 0;
+
+ if (l >= INT_MAX)
+ fatal("%s: password length too long: %zu", __func__, l);
+
+ ret = malloc(l + 1);
+ if (ret == NULL)
+ return NULL;
+ for (i = 0; i < l; i++)
+ ret[i] = junk[i % (sizeof(junk) - 1)];
+ ret[i] = '\0';
+ return ret;
+}
+
/* XXX - see also comment in auth-chall.c:verify_response */
static int
sshpam_respond(void *ctx, u_int num, char **resp)
{
- Buffer buffer;
+ struct sshbuf *buffer;
struct pam_ctxt *ctxt = ctx;
+ char *fake;
+ int r;
debug2("PAM: %s entering, %u responses", __func__, num);
switch (ctxt->pam_done) {
@@ -830,18 +976,24 @@ sshpam_respond(void *ctx, u_int num, char **resp)
error("PAM: expected one response, got %u", num);
return (-1);
}
- buffer_init(&buffer);
+ if ((buffer = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
if (sshpam_authctxt->valid &&
(sshpam_authctxt->pw->pw_uid != 0 ||
- options.permit_root_login == PERMIT_YES))
- buffer_put_cstring(&buffer, *resp);
- else
- buffer_put_cstring(&buffer, badpw);
- if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) {
- buffer_free(&buffer);
+ options.permit_root_login == PERMIT_YES)) {
+ if ((r = sshbuf_put_cstring(buffer, *resp)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ } else {
+ fake = fake_password(*resp);
+ if ((r = sshbuf_put_cstring(buffer, fake)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ free(fake);
+ }
+ if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, buffer) == -1) {
+ sshbuf_free(buffer);
return (-1);
}
- buffer_free(&buffer);
+ sshbuf_free(buffer);
return (1);
}
@@ -881,12 +1033,14 @@ KbdintDevice mm_sshpam_device = {
* This replaces auth-pam.c
*/
void
-start_pam(Authctxt *authctxt)
+start_pam(struct ssh *ssh)
{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+
if (!options.use_pam)
fatal("PAM: initialisation requested when UsePAM=no");
- if (sshpam_init(authctxt) == -1)
+ if (sshpam_init(ssh, authctxt) == -1)
fatal("PAM: initialisation failed");
}
@@ -896,6 +1050,7 @@ finish_pam(void)
sshpam_cleanup();
}
+
u_int
do_pam_account(void)
{
@@ -903,6 +1058,8 @@ do_pam_account(void)
if (sshpam_account_status != -1)
return (sshpam_account_status);
+ expose_authinfo(__func__);
+
sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
pam_strerror(sshpam_handle, sshpam_err));
@@ -920,18 +1077,6 @@ do_pam_account(void)
}
void
-do_pam_set_tty(const char *tty)
-{
- if (tty != NULL) {
- debug("PAM: setting PAM_TTY to \"%s\"", tty);
- sshpam_err = pam_set_item(sshpam_handle, PAM_TTY, tty);
- if (sshpam_err != PAM_SUCCESS)
- fatal("PAM: failed to set PAM_TTY: %s",
- pam_strerror(sshpam_handle, sshpam_err));
- }
-}
-
-void
do_pam_setcred(int init)
{
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
@@ -1036,9 +1181,12 @@ do_pam_chauthtok(void)
}
void
-do_pam_session(void)
+do_pam_session(struct ssh *ssh)
{
debug3("PAM: opening session");
+
+ expose_authinfo(__func__);
+
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
(const void *)&store_conv);
if (sshpam_err != PAM_SUCCESS)
@@ -1049,7 +1197,7 @@ do_pam_session(void)
sshpam_session_open = 1;
else {
sshpam_session_open = 0;
- disable_forwarding();
+ auth_restrict_session(ssh);
error("PAM: pam_open_session(): %s",
pam_strerror(sshpam_handle, sshpam_err));
}
@@ -1071,7 +1219,6 @@ int
do_pam_putenv(char *name, char *value)
{
int ret = 1;
-#ifdef HAVE_PAM_PUTENV
char *compound;
size_t len;
@@ -1081,7 +1228,6 @@ do_pam_putenv(char *name, char *value)
snprintf(compound, len, "%s=%s", name, value);
ret = pam_putenv(sshpam_handle, compound);
free(compound);
-#endif
return (ret);
}
@@ -1121,7 +1267,7 @@ sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
struct pam_response *reply;
- int i;
+ int r, i;
size_t len;
debug3("PAM: %s called with %d messages", __func__, n);
@@ -1147,9 +1293,10 @@ sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg,
case PAM_TEXT_INFO:
len = strlen(PAM_MSG_MEMBER(msg, i, msg));
if (len > 0) {
- buffer_append(&loginmsg,
- PAM_MSG_MEMBER(msg, i, msg), len);
- buffer_append(&loginmsg, "\n", 1);
+ if ((r = sshbuf_putf(loginmsg, "%s\n",
+ PAM_MSG_MEMBER(msg, i, msg))) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
}
if ((reply[i].resp = strdup("")) == NULL)
goto fail;
@@ -1180,6 +1327,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
{
int flags = (options.permit_empty_passwd == 0 ?
PAM_DISALLOW_NULL_AUTHTOK : 0);
+ char *fake = NULL;
if (!options.use_pam || sshpam_handle == NULL)
fatal("PAM: %s called when PAM disabled or failed to "
@@ -1195,7 +1343,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
*/
if (!authctxt->valid || (authctxt->pw->pw_uid == 0 &&
options.permit_root_login != PERMIT_YES))
- sshpam_password = badpw;
+ sshpam_password = fake = fake_password(password);
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
(const void *)&passwd_conv);
@@ -1205,6 +1353,9 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
sshpam_err = pam_authenticate(sshpam_handle, flags);
sshpam_password = NULL;
+ free(fake);
+ if (sshpam_err == PAM_MAXTRIES)
+ sshpam_set_maxtries_reached(1);
if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
debug("PAM: password authentication accepted for %.100s",
authctxt->user);
@@ -1216,4 +1367,21 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
return 0;
}
}
+
+int
+sshpam_get_maxtries_reached(void)
+{
+ return sshpam_maxtries_reached;
+}
+
+void
+sshpam_set_maxtries_reached(int reached)
+{
+ if (reached == 0 || sshpam_maxtries_reached)
+ return;
+ sshpam_maxtries_reached = 1;
+ options.password_authentication = 0;
+ options.kbd_interactive_authentication = 0;
+ options.challenge_response_authentication = 0;
+}
#endif /* USE_PAM */
diff --git a/auth-pam.h b/auth-pam.h
index a1a2b52d..9fcea270 100644
--- a/auth-pam.h
+++ b/auth-pam.h
@@ -1,5 +1,3 @@
-/* $Id: auth-pam.h,v 1.27 2004/09/11 12:17:26 dtucker Exp $ */
-
/*
* Copyright (c) 2000 Damien Miller. All rights reserved.
*
@@ -27,15 +25,12 @@
#include "includes.h"
#ifdef USE_PAM
-#if !defined(SSHD_PAM_SERVICE)
-# define SSHD_PAM_SERVICE __progname
-#endif
+struct ssh;
-void start_pam(Authctxt *);
+void start_pam(struct ssh *);
void finish_pam(void);
u_int do_pam_account(void);
-void do_pam_session(void);
-void do_pam_set_tty(const char *);
+void do_pam_session(struct ssh *);
void do_pam_setcred(int );
void do_pam_chauthtok(void);
int do_pam_putenv(char *, char *);
@@ -45,6 +40,8 @@ void free_pam_environment(char **);
void sshpam_thread_cleanup(void);
void sshpam_cleanup(void);
int sshpam_auth_passwd(Authctxt *, const char *);
+int sshpam_get_maxtries_reached(void);
+void sshpam_set_maxtries_reached(int);
int is_pam_session_open(void);
#endif /* USE_PAM */
diff --git a/auth-passwd.c b/auth-passwd.c
index 63ccf3ca..24fcb67b 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-passwd.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: auth-passwd.c,v 1.47 2018/07/09 21:26:02 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -46,16 +46,17 @@
#include <stdarg.h>
#include "packet.h"
-#include "buffer.h"
+#include "sshbuf.h"
+#include "ssherr.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-options.h"
-extern Buffer loginmsg;
+extern struct sshbuf *loginmsg;
extern ServerOptions options;
#ifdef HAVE_LOGIN_CAP
@@ -66,27 +67,25 @@ extern login_cap_t *lc;
#define DAY (24L * 60 * 60) /* 1 day in seconds */
#define TWO_WEEKS (2L * 7 * DAY) /* 2 weeks in seconds */
-void
-disable_forwarding(void)
-{
- no_port_forwarding_flag = 1;
- no_agent_forwarding_flag = 1;
- no_x11_forwarding_flag = 1;
-}
+#define MAX_PASSWORD_LEN 1024
/*
* Tries to authenticate the user using password. Returns true if
* authentication succeeds.
*/
int
-auth_password(Authctxt *authctxt, const char *password)
+auth_password(struct ssh *ssh, const char *password)
{
- struct passwd * pw = authctxt->pw;
+ Authctxt *authctxt = ssh->authctxt;
+ struct passwd *pw = authctxt->pw;
int result, ok = authctxt->valid;
#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
static int expire_checked = 0;
#endif
+ if (strlen(password) > MAX_PASSWORD_LEN)
+ return 0;
+
#ifndef HAVE_CYGWIN
if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)
ok = 0;
@@ -123,9 +122,9 @@ auth_password(Authctxt *authctxt, const char *password)
authctxt->force_pwchange = 1;
}
#endif
- result = sys_auth_passwd(authctxt, password);
+ result = sys_auth_passwd(ssh, password);
if (authctxt->force_pwchange)
- disable_forwarding();
+ auth_restrict_session(ssh);
return (result && ok);
}
@@ -133,7 +132,7 @@ auth_password(Authctxt *authctxt, const char *password)
static void
warn_expiry(Authctxt *authctxt, auth_session_t *as)
{
- char buf[256];
+ int r;
quad_t pwtimeleft, actimeleft, daysleft, pwwarntime, acwarntime;
pwwarntime = acwarntime = TWO_WEEKS;
@@ -150,34 +149,34 @@ warn_expiry(Authctxt *authctxt, auth_session_t *as)
#endif
if (pwtimeleft != 0 && pwtimeleft < pwwarntime) {
daysleft = pwtimeleft / DAY + 1;
- snprintf(buf, sizeof(buf),
+ if ((r = sshbuf_putf(loginmsg,
"Your password will expire in %lld day%s.\n",
- daysleft, daysleft == 1 ? "" : "s");
- buffer_append(&loginmsg, buf, strlen(buf));
+ daysleft, daysleft == 1 ? "" : "s")) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
if (actimeleft != 0 && actimeleft < acwarntime) {
daysleft = actimeleft / DAY + 1;
- snprintf(buf, sizeof(buf),
+ if ((r = sshbuf_putf(loginmsg,
"Your account will expire in %lld day%s.\n",
- daysleft, daysleft == 1 ? "" : "s");
- buffer_append(&loginmsg, buf, strlen(buf));
+ daysleft, daysleft == 1 ? "" : "s")) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
}
int
-sys_auth_passwd(Authctxt *authctxt, const char *password)
+sys_auth_passwd(struct ssh *ssh, const char *password)
{
- struct passwd *pw = authctxt->pw;
+ Authctxt *authctxt = ssh->authctxt;
auth_session_t *as;
static int expire_checked = 0;
- as = auth_usercheck(pw->pw_name, authctxt->style, "auth-ssh",
+ as = auth_usercheck(authctxt->pw->pw_name, authctxt->style, "auth-ssh",
(char *)password);
if (as == NULL)
return (0);
if (auth_getstate(as) & AUTH_PWEXPIRED) {
auth_close(as);
- disable_forwarding();
+ auth_restrict_session(ssh);
authctxt->force_pwchange = 1;
return (1);
} else {
@@ -190,21 +189,29 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
}
#elif !defined(CUSTOM_SYS_AUTH_PASSWD)
int
-sys_auth_passwd(Authctxt *authctxt, const char *password)
+sys_auth_passwd(struct ssh *ssh, const char *password)
{
+ Authctxt *authctxt = ssh->authctxt;
struct passwd *pw = authctxt->pw;
- char *encrypted_password;
+ char *encrypted_password, *salt = NULL;
/* Just use the supplied fake password if authctxt is invalid */
char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd;
+ if (pw_password == NULL)
+ return 0;
+
/* Check for users with no password. */
if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0)
return (1);
- /* Encrypt the candidate password using the proper salt. */
- encrypted_password = xcrypt(password,
- (pw_password[0] && pw_password[1]) ? pw_password : "xx");
+ /*
+ * Encrypt the candidate password using the proper salt, or pass a
+ * NULL and let xcrypt pick one.
+ */
+ if (authctxt->valid && pw_password[0] && pw_password[1])
+ salt = pw_password;
+ encrypted_password = xcrypt(password, salt);
/*
* Authentication is accepted if the encrypted passwords
diff --git a/auth-rh-rsa.c b/auth-rh-rsa.c
deleted file mode 100644
index 2e20396e..00000000
--- a/auth-rh-rsa.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* $OpenBSD: auth-rh-rsa.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Rhosts or /etc/hosts.equiv authentication combined with RSA host
- * authentication.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-
-#include "includes.h"
-
-#ifdef WITH_SSH1
-
-#include <sys/types.h>
-
-#include <pwd.h>
-#include <stdarg.h>
-
-#include "packet.h"
-#include "uidswap.h"
-#include "log.h"
-#include "buffer.h"
-#include "misc.h"
-#include "servconf.h"
-#include "key.h"
-#include "hostfile.h"
-#include "pathnames.h"
-#include "auth.h"
-#include "canohost.h"
-#ifdef GSSAPI
-#include "ssh-gss.h"
-#endif
-#include "monitor_wrap.h"
-
-/* import */
-extern ServerOptions options;
-
-int
-auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
- Key *client_host_key)
-{
- HostStatus host_status;
-
- if (auth_key_is_revoked(client_host_key))
- return 0;
-
- /* Check if we would accept it using rhosts authentication. */
- if (!auth_rhosts(pw, cuser))
- return 0;
-
- host_status = check_key_in_hostfiles(pw, client_host_key,
- chost, _PATH_SSH_SYSTEM_HOSTFILE,
- options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
-
- return (host_status == HOST_OK);
-}
-
-/*
- * Tries to authenticate the user using the .rhosts file and the host using
- * its host key. Returns true if authentication succeeds.
- */
-int
-auth_rhosts_rsa(Authctxt *authctxt, char *cuser, Key *client_host_key)
-{
- char *chost;
- struct passwd *pw = authctxt->pw;
-
- debug("Trying rhosts with RSA host authentication for client user %.100s",
- cuser);
-
- if (!authctxt->valid || client_host_key == NULL ||
- client_host_key->rsa == NULL)
- return 0;
-
- chost = (char *)get_canonical_hostname(options.use_dns);
- debug("Rhosts RSA authentication: canonical host %.900s", chost);
-
- if (!PRIVSEP(auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key))) {
- debug("Rhosts with RSA host authentication denied: unknown or invalid host key");
- packet_send_debug("Your host key cannot be verified: unknown or invalid host key.");
- return 0;
- }
- /* A matching host key was found and is known. */
-
- /* Perform the challenge-response dialog with the client for the host key. */
- if (!auth_rsa_challenge_dialog(client_host_key)) {
- logit("Client on %.800s failed to respond correctly to host authentication.",
- chost);
- return 0;
- }
- /*
- * We have authenticated the user using .rhosts or /etc/hosts.equiv,
- * and the host using RSA. We accept the authentication.
- */
-
- verbose("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.",
- pw->pw_name, cuser, chost);
- packet_send_debug("Rhosts with RSA host authentication accepted.");
- return 1;
-}
-
-#endif /* WITH_SSH1 */
diff --git a/auth-rhosts.c b/auth-rhosts.c
index ee9e827a..e81321b4 100644
--- a/auth-rhosts.c
+++ b/auth-rhosts.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-rhosts.c,v 1.46 2014/12/23 22:42:48 djm Exp $ */
+/* $OpenBSD: auth-rhosts.c,v 1.52 2020/04/17 03:30:05 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -30,14 +30,14 @@
#include <unistd.h>
#include "packet.h"
-#include "buffer.h"
#include "uidswap.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
+#include "sshbuf.h"
+#include "sshkey.h"
#include "servconf.h"
#include "canohost.h"
-#include "key.h"
#include "hostfile.h"
#include "auth.h"
@@ -185,19 +185,8 @@ check_rhosts_file(const char *filename, const char *hostname,
* true if authentication succeeds. If ignore_rhosts is true, only
* /etc/hosts.equiv will be considered (.rhosts and .shosts are ignored).
*/
-
int
-auth_rhosts(struct passwd *pw, const char *client_user)
-{
- const char *hostname, *ipaddr;
-
- hostname = get_canonical_hostname(options.use_dns);
- ipaddr = get_remote_ipaddr();
- return auth_rhosts2(pw, client_user, hostname, ipaddr);
-}
-
-static int
-auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostname,
+auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
const char *ipaddr)
{
char buf[1024];
@@ -232,8 +221,8 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam
* are no system-wide files.
*/
if (!rhosts_files[rhosts_file_index] &&
- stat(_PATH_RHOSTS_EQUIV, &st) < 0 &&
- stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0) {
+ stat(_PATH_RHOSTS_EQUIV, &st) == -1 &&
+ stat(_PATH_SSH_HOSTS_EQUIV, &st) == -1) {
debug3("%s: no hosts access files exist", __func__);
return 0;
}
@@ -263,7 +252,7 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam
* Check that the home directory is owned by root or the user, and is
* not group or world writable.
*/
- if (stat(pw->pw_dir, &st) < 0) {
+ if (stat(pw->pw_dir, &st) == -1) {
logit("Rhosts authentication refused for %.100s: "
"no home directory %.200s", pw->pw_name, pw->pw_dir);
auth_debug_add("Rhosts authentication refused for %.100s: "
@@ -288,7 +277,7 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam
/* Check users .rhosts or .shosts. */
snprintf(buf, sizeof buf, "%.500s/%.100s",
pw->pw_dir, rhosts_files[rhosts_file_index]);
- if (stat(buf, &st) < 0)
+ if (stat(buf, &st) == -1)
continue;
/*
@@ -309,7 +298,9 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam
* Check if we have been configured to ignore .rhosts
* and .shosts files.
*/
- if (options.ignore_rhosts) {
+ if (options.ignore_rhosts == IGNORE_RHOSTS_YES ||
+ (options.ignore_rhosts == IGNORE_RHOSTS_SHOSTS &&
+ strcmp(rhosts_files[rhosts_file_index], ".shosts") != 0)) {
auth_debug_add("Server has been configured to "
"ignore %.100s.", rhosts_files[rhosts_file_index]);
continue;
@@ -332,10 +323,3 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam
restore_uid();
return 0;
}
-
-int
-auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
- const char *ipaddr)
-{
- return auth_rhosts2_raw(pw, client_user, hostname, ipaddr);
-}
diff --git a/auth-rsa.c b/auth-rsa.c
deleted file mode 100644
index cbd971be..00000000
--- a/auth-rsa.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/* $OpenBSD: auth-rsa.c,v 1.90 2015/01/28 22:36:00 djm Exp $ */
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * RSA-based authentication. This code determines whether to admit a login
- * based on RSA authentication. This file also contains functions to check
- * validity of the host key.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-
-#include "includes.h"
-
-#ifdef WITH_SSH1
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <openssl/rsa.h>
-
-#include <pwd.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include "xmalloc.h"
-#include "rsa.h"
-#include "packet.h"
-#include "ssh1.h"
-#include "uidswap.h"
-#include "match.h"
-#include "buffer.h"
-#include "pathnames.h"
-#include "log.h"
-#include "misc.h"
-#include "servconf.h"
-#include "key.h"
-#include "auth-options.h"
-#include "hostfile.h"
-#include "auth.h"
-#ifdef GSSAPI
-#include "ssh-gss.h"
-#endif
-#include "monitor_wrap.h"
-#include "ssh.h"
-
-#include "digest.h"
-
-/* import */
-extern ServerOptions options;
-
-/*
- * Session identifier that is used to bind key exchange and authentication
- * responses to a particular session.
- */
-extern u_char session_id[16];
-
-/*
- * The .ssh/authorized_keys file contains public keys, one per line, in the
- * following format:
- * options bits e n comment
- * where bits, e and n are decimal numbers,
- * and comment is any string of characters up to newline. The maximum
- * length of a line is SSH_MAX_PUBKEY_BYTES characters. See sshd(8) for a
- * description of the options.
- */
-
-BIGNUM *
-auth_rsa_generate_challenge(Key *key)
-{
- BIGNUM *challenge;
- BN_CTX *ctx;
-
- if ((challenge = BN_new()) == NULL)
- fatal("auth_rsa_generate_challenge: BN_new() failed");
- /* Generate a random challenge. */
- if (BN_rand(challenge, 256, 0, 0) == 0)
- fatal("auth_rsa_generate_challenge: BN_rand failed");
- if ((ctx = BN_CTX_new()) == NULL)
- fatal("auth_rsa_generate_challenge: BN_CTX_new failed");
- if (BN_mod(challenge, challenge, key->rsa->n, ctx) == 0)
- fatal("auth_rsa_generate_challenge: BN_mod failed");
- BN_CTX_free(ctx);
-
- return challenge;
-}
-
-int
-auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
-{
- u_char buf[32], mdbuf[16];
- struct ssh_digest_ctx *md;
- int len;
-
- /* don't allow short keys */
- if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
- error("%s: RSA modulus too small: %d < minimum %d bits",
- __func__,
- BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
- return (0);
- }
-
- /* The response is MD5 of decrypted challenge plus session id. */
- len = BN_num_bytes(challenge);
- if (len <= 0 || len > 32)
- fatal("%s: bad challenge length %d", __func__, len);
- memset(buf, 0, 32);
- BN_bn2bin(challenge, buf + 32 - len);
- if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
- ssh_digest_update(md, buf, 32) < 0 ||
- ssh_digest_update(md, session_id, 16) < 0 ||
- ssh_digest_final(md, mdbuf, sizeof(mdbuf)) < 0)
- fatal("%s: md5 failed", __func__);
- ssh_digest_free(md);
-
- /* Verify that the response is the original challenge. */
- if (timingsafe_bcmp(response, mdbuf, 16) != 0) {
- /* Wrong answer. */
- return (0);
- }
- /* Correct answer. */
- return (1);
-}
-
-/*
- * Performs the RSA authentication challenge-response dialog with the client,
- * and returns true (non-zero) if the client gave the correct answer to
- * our challenge; returns zero if the client gives a wrong answer.
- */
-
-int
-auth_rsa_challenge_dialog(Key *key)
-{
- BIGNUM *challenge, *encrypted_challenge;
- u_char response[16];
- int i, success;
-
- if ((encrypted_challenge = BN_new()) == NULL)
- fatal("auth_rsa_challenge_dialog: BN_new() failed");
-
- challenge = PRIVSEP(auth_rsa_generate_challenge(key));
-
- /* Encrypt the challenge with the public key. */
- if (rsa_public_encrypt(encrypted_challenge, challenge, key->rsa) != 0)
- fatal("%s: rsa_public_encrypt failed", __func__);
-
- /* Send the encrypted challenge to the client. */
- packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
- packet_put_bignum(encrypted_challenge);
- packet_send();
- BN_clear_free(encrypted_challenge);
- packet_write_wait();
-
- /* Wait for a response. */
- packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE);
- for (i = 0; i < 16; i++)
- response[i] = (u_char)packet_get_char();
- packet_check_eom();
-
- success = PRIVSEP(auth_rsa_verify_response(key, challenge, response));
- BN_clear_free(challenge);
- return (success);
-}
-
-static int
-rsa_key_allowed_in_file(struct passwd *pw, char *file,
- const BIGNUM *client_n, Key **rkey)
-{
- char *fp, line[SSH_MAX_PUBKEY_BYTES];
- int allowed = 0, bits;
- FILE *f;
- u_long linenum = 0;
- Key *key;
-
- debug("trying public RSA key file %s", file);
- if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL)
- return 0;
-
- /*
- * Go though the accepted keys, looking for the current key. If
- * found, perform a challenge-response dialog to verify that the
- * user really has the corresponding private key.
- */
- key = key_new(KEY_RSA1);
- while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
- char *cp;
- char *key_options;
- int keybits;
-
- /* Skip leading whitespace, empty and comment lines. */
- for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
- ;
- if (!*cp || *cp == '\n' || *cp == '#')
- continue;
-
- /*
- * Check if there are options for this key, and if so,
- * save their starting address and skip the option part
- * for now. If there are no options, set the starting
- * address to NULL.
- */
- if (*cp < '0' || *cp > '9') {
- int quoted = 0;
- key_options = cp;
- for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
- if (*cp == '\\' && cp[1] == '"')
- cp++; /* Skip both */
- else if (*cp == '"')
- quoted = !quoted;
- }
- } else
- key_options = NULL;
-
- /* Parse the key from the line. */
- if (hostfile_read_key(&cp, &bits, key) == 0) {
- debug("%.100s, line %lu: non ssh1 key syntax",
- file, linenum);
- continue;
- }
- /* cp now points to the comment part. */
-
- /*
- * Check if the we have found the desired key (identified
- * by its modulus).
- */
- if (BN_cmp(key->rsa->n, client_n) != 0)
- continue;
-
- /* check the real bits */
- keybits = BN_num_bits(key->rsa->n);
- if (keybits < 0 || bits != keybits)
- logit("Warning: %s, line %lu: keysize mismatch: "
- "actual %d vs. announced %d.",
- file, linenum, BN_num_bits(key->rsa->n), bits);
-
- if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
- SSH_FP_DEFAULT)) == NULL)
- continue;
- debug("matching key found: file %s, line %lu %s %s",
- file, linenum, key_type(key), fp);
- free(fp);
-
- /* Never accept a revoked key */
- if (auth_key_is_revoked(key))
- break;
-
- /* We have found the desired key. */
- /*
- * If our options do not allow this key to be used,
- * do not send challenge.
- */
- if (!auth_parse_options(pw, key_options, file, linenum))
- continue;
- if (key_is_cert_authority)
- continue;
- /* break out, this key is allowed */
- allowed = 1;
- break;
- }
-
- /* Close the file. */
- fclose(f);
-
- /* return key if allowed */
- if (allowed && rkey != NULL)
- *rkey = key;
- else
- key_free(key);
-
- return allowed;
-}
-
-/*
- * check if there's user key matching client_n,
- * return key if login is allowed, NULL otherwise
- */
-
-int
-auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
-{
- char *file;
- u_int i, allowed = 0;
-
- temporarily_use_uid(pw);
-
- for (i = 0; !allowed && i < options.num_authkeys_files; i++) {
- if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
- continue;
- file = expand_authorized_keys(
- options.authorized_keys_files[i], pw);
- allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey);
- free(file);
- }
-
- restore_uid();
-
- return allowed;
-}
-
-/*
- * Performs the RSA authentication dialog with the client. This returns
- * 0 if the client could not be authenticated, and 1 if authentication was
- * successful. This may exit if there is a serious protocol violation.
- */
-int
-auth_rsa(Authctxt *authctxt, BIGNUM *client_n)
-{
- Key *key;
- struct passwd *pw = authctxt->pw;
-
- /* no user given */
- if (!authctxt->valid)
- return 0;
-
- if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) {
- auth_clear_options();
- return (0);
- }
-
- /* Perform the challenge-response dialog for this key. */
- if (!auth_rsa_challenge_dialog(key)) {
- /* Wrong response. */
- verbose("Wrong response to RSA authentication challenge.");
- packet_send_debug("Wrong response to RSA authentication challenge.");
- /*
- * Break out of the loop. Otherwise we might send
- * another challenge and break the protocol.
- */
- key_free(key);
- return (0);
- }
- /*
- * Correct response. The client has been successfully
- * authenticated. Note that we have not yet processed the
- * options; this will be reset if the options cause the
- * authentication to be rejected.
- */
- pubkey_auth_info(authctxt, key, NULL);
-
- packet_send_debug("RSA authentication accepted.");
- return (1);
-}
-
-#endif /* WITH_SSH1 */
diff --git a/auth-shadow.c b/auth-shadow.c
index 21909167..c77ee8da 100644
--- a/auth-shadow.c
+++ b/auth-shadow.c
@@ -30,10 +30,10 @@
#include <string.h>
#include <time.h>
-#include "key.h"
#include "hostfile.h"
#include "auth.h"
-#include "buffer.h"
+#include "sshbuf.h"
+#include "ssherr.h"
#include "log.h"
#ifdef DAY
@@ -41,7 +41,7 @@
#endif
#define DAY (24L * 60 * 60) /* 1 day in seconds */
-extern Buffer loginmsg;
+extern struct sshbuf *loginmsg;
/*
* For the account and password expiration functions, we assume the expiry
@@ -57,7 +57,7 @@ auth_shadow_acctexpired(struct spwd *spw)
{
time_t today;
int daysleft;
- char buf[256];
+ int r;
today = time(NULL) / DAY;
daysleft = spw->sp_expire - today;
@@ -71,10 +71,10 @@ auth_shadow_acctexpired(struct spwd *spw)
return 1;
} else if (daysleft <= spw->sp_warn) {
debug3("account will expire in %d days", daysleft);
- snprintf(buf, sizeof(buf),
+ if ((r = sshbuf_putf(loginmsg,
"Your account will expire in %d day%s.\n", daysleft,
- daysleft == 1 ? "" : "s");
- buffer_append(&loginmsg, buf, strlen(buf));
+ daysleft == 1 ? "" : "s")) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
return 0;
@@ -89,9 +89,8 @@ auth_shadow_pwexpired(Authctxt *ctxt)
{
struct spwd *spw = NULL;
const char *user = ctxt->pw->pw_name;
- char buf[256];
time_t today;
- int daysleft, disabled = 0;
+ int r, daysleft, disabled = 0;
if ((spw = getspnam((char *)user)) == NULL) {
error("Could not get shadow information for %.100s", user);
@@ -131,10 +130,10 @@ auth_shadow_pwexpired(Authctxt *ctxt)
return 1;
} else if (daysleft <= spw->sp_warn) {
debug3("password will expire in %d days", daysleft);
- snprintf(buf, sizeof(buf),
+ if ((r = sshbuf_putf(loginmsg,
"Your password will expire in %d day%s.\n", daysleft,
- daysleft == 1 ? "" : "s");
- buffer_append(&loginmsg, buf, strlen(buf));
+ daysleft == 1 ? "" : "s")) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
return 0;
diff --git a/auth-sia.c b/auth-sia.c
index a9e1c258..ebe9d8d1 100644
--- a/auth-sia.c
+++ b/auth-sia.c
@@ -36,7 +36,7 @@
#include <string.h>
#include "ssh.h"
-#include "key.h"
+#include "ssh_api.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-sia.h"
@@ -50,11 +50,12 @@ extern int saved_argc;
extern char **saved_argv;
int
-sys_auth_passwd(Authctxt *authctxt, const char *pass)
+sys_auth_passwd(struct ssh *ssh, const char *pass)
{
int ret;
SIAENTITY *ent = NULL;
const char *host;
+ Authctxt *authctxt = ssh->authctxt;
host = get_canonical_hostname(options.use_dns);
diff --git a/auth-skey.c b/auth-skey.c
deleted file mode 100644
index 3536ec8f..00000000
--- a/auth-skey.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* $OpenBSD: auth-skey.c,v 1.27 2007/01/21 01:41:54 stevesk Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#ifdef SKEY
-
-#include <sys/types.h>
-
-#include <pwd.h>
-#include <stdio.h>
-
-#include <skey.h>
-
-#include "xmalloc.h"
-#include "key.h"
-#include "hostfile.h"
-#include "auth.h"
-#include "ssh-gss.h"
-#include "log.h"
-#include "monitor_wrap.h"
-
-static void *
-skey_init_ctx(Authctxt *authctxt)
-{
- return authctxt;
-}
-
-int
-skey_query(void *ctx, char **name, char **infotxt,
- u_int* numprompts, char ***prompts, u_int **echo_on)
-{
- Authctxt *authctxt = ctx;
- char challenge[1024];
- struct skey skey;
-
- if (_compat_skeychallenge(&skey, authctxt->user, challenge,
- sizeof(challenge)) == -1)
- return -1;
-
- *name = xstrdup("");
- *infotxt = xstrdup("");
- *numprompts = 1;
- *prompts = xcalloc(*numprompts, sizeof(char *));
- *echo_on = xcalloc(*numprompts, sizeof(u_int));
-
- xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT);
-
- return 0;
-}
-
-int
-skey_respond(void *ctx, u_int numresponses, char **responses)
-{
- Authctxt *authctxt = ctx;
-
- if (authctxt->valid &&
- numresponses == 1 &&
- skey_haskey(authctxt->pw->pw_name) == 0 &&
- skey_passcheck(authctxt->pw->pw_name, responses[0]) != -1)
- return 0;
- return -1;
-}
-
-static void
-skey_free_ctx(void *ctx)
-{
- /* we don't have a special context */
-}
-
-KbdintDevice skey_device = {
- "skey",
- skey_init_ctx,
- skey_query,
- skey_respond,
- skey_free_ctx
-};
-
-KbdintDevice mm_skey_device = {
- "skey",
- skey_init_ctx,
- mm_skey_query,
- mm_skey_respond,
- skey_free_ctx
-};
-#endif /* SKEY */
diff --git a/auth.c b/auth.c
index 0fefead0..7aabc8e8 100644
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.c,v 1.110 2015/02/25 17:29:38 djm Exp $ */
+/* $OpenBSD: auth.c,v 1.146 2020/01/31 22:42:45 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -27,9 +27,12 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
#include <netinet/in.h>
+#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_PATHS_H
@@ -42,23 +45,22 @@
#ifdef USE_SHADOW
#include <shadow.h>
#endif
-#ifdef HAVE_LIBGEN_H
-#include <libgen.h>
-#endif
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
+#include <netdb.h>
+#include <time.h>
#include "xmalloc.h"
#include "match.h"
#include "groupaccess.h"
#include "log.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "misc.h"
#include "servconf.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-options.h"
@@ -71,19 +73,20 @@
#endif
#include "authfile.h"
#include "monitor_wrap.h"
-#include "authfile.h"
#include "ssherr.h"
#include "compat.h"
+#include "channels.h"
/* import */
extern ServerOptions options;
+extern struct include_list includes;
extern int use_privsep;
-extern Buffer loginmsg;
+extern struct sshbuf *loginmsg;
extern struct passwd *privsep_pw;
+extern struct sshauthopt *auth_opts;
/* Debugging messages */
-Buffer auth_debug;
-int auth_debug_init;
+static struct sshbuf *auth_debug;
/*
* Check if the user is allowed to log in via ssh. If user is listed
@@ -95,11 +98,12 @@ int auth_debug_init;
* Otherwise true is returned.
*/
int
-allowed_user(struct passwd * pw)
+allowed_user(struct ssh *ssh, struct passwd * pw)
{
struct stat st;
const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
u_int i;
+ int r;
#ifdef USE_SHADOW
struct spwd *spw = NULL;
#endif
@@ -164,7 +168,7 @@ allowed_user(struct passwd * pw)
char *shell = xstrdup((pw->pw_shell[0] == '\0') ?
_PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */
- if (stat(shell, &st) != 0) {
+ if (stat(shell, &st) == -1) {
logit("User %.100s not allowed because shell %.100s "
"does not exist", pw->pw_name, shell);
free(shell);
@@ -182,27 +186,37 @@ allowed_user(struct passwd * pw)
if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
options.num_deny_groups > 0 || options.num_allow_groups > 0) {
- hostname = get_canonical_hostname(options.use_dns);
- ipaddr = get_remote_ipaddr();
+ hostname = auth_get_canonical_hostname(ssh, options.use_dns);
+ ipaddr = ssh_remote_ipaddr(ssh);
}
/* Return false if user is listed in DenyUsers */
if (options.num_deny_users > 0) {
- for (i = 0; i < options.num_deny_users; i++)
- if (match_user(pw->pw_name, hostname, ipaddr,
- options.deny_users[i])) {
+ for (i = 0; i < options.num_deny_users; i++) {
+ r = match_user(pw->pw_name, hostname, ipaddr,
+ options.deny_users[i]);
+ if (r < 0) {
+ fatal("Invalid DenyUsers pattern \"%.100s\"",
+ options.deny_users[i]);
+ } else if (r != 0) {
logit("User %.100s from %.100s not allowed "
"because listed in DenyUsers",
pw->pw_name, hostname);
return 0;
}
+ }
}
/* Return false if AllowUsers isn't empty and user isn't listed there */
if (options.num_allow_users > 0) {
- for (i = 0; i < options.num_allow_users; i++)
- if (match_user(pw->pw_name, hostname, ipaddr,
- options.allow_users[i]))
+ for (i = 0; i < options.num_allow_users; i++) {
+ r = match_user(pw->pw_name, hostname, ipaddr,
+ options.allow_users[i]);
+ if (r < 0) {
+ fatal("Invalid AllowUsers pattern \"%.100s\"",
+ options.allow_users[i]);
+ } else if (r == 1)
break;
+ }
/* i < options.num_allow_users iff we break for loop */
if (i >= options.num_allow_users) {
logit("User %.100s from %.100s not allowed because "
@@ -245,7 +259,7 @@ allowed_user(struct passwd * pw)
}
#ifdef CUSTOM_SYS_AUTH_ALLOWED_USER
- if (!sys_auth_allowed_user(pw, &loginmsg))
+ if (!sys_auth_allowed_user(pw, loginmsg))
return 0;
#endif
@@ -253,29 +267,55 @@ allowed_user(struct passwd * pw)
return 1;
}
-void
-auth_info(Authctxt *authctxt, const char *fmt, ...)
+/*
+ * Formats any key left in authctxt->auth_method_key for inclusion in
+ * auth_log()'s message. Also includes authxtct->auth_method_info if present.
+ */
+static char *
+format_method_key(Authctxt *authctxt)
{
- va_list ap;
- int i;
-
- free(authctxt->info);
- authctxt->info = NULL;
+ const struct sshkey *key = authctxt->auth_method_key;
+ const char *methinfo = authctxt->auth_method_info;
+ char *fp, *cafp, *ret = NULL;
- va_start(ap, fmt);
- i = vasprintf(&authctxt->info, fmt, ap);
- va_end(ap);
+ if (key == NULL)
+ return NULL;
- if (i < 0 || authctxt->info == NULL)
- fatal("vasprintf failed");
+ if (sshkey_is_cert(key)) {
+ fp = sshkey_fingerprint(key,
+ options.fingerprint_hash, SSH_FP_DEFAULT);
+ cafp = sshkey_fingerprint(key->cert->signature_key,
+ options.fingerprint_hash, SSH_FP_DEFAULT);
+ xasprintf(&ret, "%s %s ID %s (serial %llu) CA %s %s%s%s",
+ sshkey_type(key), fp == NULL ? "(null)" : fp,
+ key->cert->key_id,
+ (unsigned long long)key->cert->serial,
+ sshkey_type(key->cert->signature_key),
+ cafp == NULL ? "(null)" : cafp,
+ methinfo == NULL ? "" : ", ",
+ methinfo == NULL ? "" : methinfo);
+ free(fp);
+ free(cafp);
+ } else {
+ fp = sshkey_fingerprint(key, options.fingerprint_hash,
+ SSH_FP_DEFAULT);
+ xasprintf(&ret, "%s %s%s%s", sshkey_type(key),
+ fp == NULL ? "(null)" : fp,
+ methinfo == NULL ? "" : ", ",
+ methinfo == NULL ? "" : methinfo);
+ free(fp);
+ }
+ return ret;
}
void
-auth_log(Authctxt *authctxt, int authenticated, int partial,
+auth_log(struct ssh *ssh, int authenticated, int partial,
const char *method, const char *submethod)
{
- void (*authlog) (const char *fmt,...) = verbose;
- char *authmsg;
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+ int level = SYSLOG_LEVEL_VERBOSE;
+ const char *authmsg;
+ char *extra = NULL;
if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
return;
@@ -285,7 +325,7 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
!authctxt->valid ||
authctxt->failures >= options.max_authtries / 2 ||
strcmp(method, "password") == 0)
- authlog = logit;
+ level = SYSLOG_LEVEL_INFO;
if (authctxt->postponed)
authmsg = "Postponed";
@@ -294,51 +334,57 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
else
authmsg = authenticated ? "Accepted" : "Failed";
- authlog("%s %s%s%s for %s%.100s from %.200s port %d %s%s%s",
+ if ((extra = format_method_key(authctxt)) == NULL) {
+ if (authctxt->auth_method_info != NULL)
+ extra = xstrdup(authctxt->auth_method_info);
+ }
+
+ do_log2(level, "%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s",
authmsg,
method,
submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
authctxt->valid ? "" : "invalid user ",
authctxt->user,
- get_remote_ipaddr(),
- get_remote_port(),
- compat20 ? "ssh2" : "ssh1",
- authctxt->info != NULL ? ": " : "",
- authctxt->info != NULL ? authctxt->info : "");
- free(authctxt->info);
- authctxt->info = NULL;
+ ssh_remote_ipaddr(ssh),
+ ssh_remote_port(ssh),
+ extra != NULL ? ": " : "",
+ extra != NULL ? extra : "");
+
+ free(extra);
#ifdef CUSTOM_FAILED_LOGIN
if (authenticated == 0 && !authctxt->postponed &&
(strcmp(method, "password") == 0 ||
strncmp(method, "keyboard-interactive", 20) == 0 ||
strcmp(method, "challenge-response") == 0))
- record_failed_login(authctxt->user,
- get_canonical_hostname(options.use_dns), "ssh");
+ record_failed_login(ssh, authctxt->user,
+ auth_get_canonical_hostname(ssh, options.use_dns), "ssh");
# ifdef WITH_AIXAUTHENTICATE
if (authenticated)
sys_auth_record_login(authctxt->user,
- get_canonical_hostname(options.use_dns), "ssh", &loginmsg);
+ auth_get_canonical_hostname(ssh, options.use_dns), "ssh",
+ loginmsg);
# endif
#endif
#ifdef SSH_AUDIT_EVENTS
if (authenticated == 0 && !authctxt->postponed)
- audit_event(audit_classify_auth(method));
+ audit_event(ssh, audit_classify_auth(method));
#endif
}
void
-auth_maxtries_exceeded(Authctxt *authctxt)
+auth_maxtries_exceeded(struct ssh *ssh)
{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+
error("maximum authentication attempts exceeded for "
- "%s%.100s from %.200s port %d %s",
+ "%s%.100s from %.200s port %d ssh2",
authctxt->valid ? "" : "invalid user ",
authctxt->user,
- get_remote_ipaddr(),
- get_remote_port(),
- compat20 ? "ssh2" : "ssh1");
- packet_disconnect("Too many authentication failures");
+ ssh_remote_ipaddr(ssh),
+ ssh_remote_port(ssh));
+ ssh_packet_disconnect(ssh, "Too many authentication failures");
/* NOTREACHED */
}
@@ -346,23 +392,26 @@ auth_maxtries_exceeded(Authctxt *authctxt)
* Check whether root logins are disallowed.
*/
int
-auth_root_allowed(const char *method)
+auth_root_allowed(struct ssh *ssh, const char *method)
{
switch (options.permit_root_login) {
case PERMIT_YES:
return 1;
case PERMIT_NO_PASSWD:
- if (strcmp(method, "password") != 0)
+ if (strcmp(method, "publickey") == 0 ||
+ strcmp(method, "hostbased") == 0 ||
+ strcmp(method, "gssapi-with-mic") == 0)
return 1;
break;
case PERMIT_FORCED_ONLY:
- if (forced_command) {
+ if (auth_opts->force_command != NULL) {
logit("Root login accepted for forced command.");
return 1;
}
break;
}
- logit("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
+ logit("ROOT LOGIN REFUSED FROM %.200s port %d",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
return 0;
}
@@ -377,17 +426,19 @@ auth_root_allowed(const char *method)
char *
expand_authorized_keys(const char *filename, struct passwd *pw)
{
- char *file, ret[PATH_MAX];
+ char *file, uidstr[32], ret[PATH_MAX];
int i;
+ snprintf(uidstr, sizeof(uidstr), "%llu",
+ (unsigned long long)pw->pw_uid);
file = percent_expand(filename, "h", pw->pw_dir,
- "u", pw->pw_name, (char *)NULL);
+ "u", pw->pw_name, "U", uidstr, (char *)NULL);
/*
* Ensure that filename starts anchored. If not, be backward
* compatible and prepend the '%h/'
*/
- if (*file == '/')
+ if (path_absolute(file))
return (file);
i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
@@ -400,15 +451,14 @@ expand_authorized_keys(const char *filename, struct passwd *pw)
char *
authorized_principals_file(struct passwd *pw)
{
- if (options.authorized_principals_file == NULL ||
- strcasecmp(options.authorized_principals_file, "none") == 0)
+ if (options.authorized_principals_file == NULL)
return NULL;
return expand_authorized_keys(options.authorized_principals_file, pw);
}
/* return ok if key exists in sysfile or userfile */
HostStatus
-check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
+check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host,
const char *sysfile, const char *userfile)
{
char *user_hostfile;
@@ -440,7 +490,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
host_status = check_key_in_hostkeys(hostkeys, key, &found);
if (host_status == HOST_REVOKED)
error("WARNING: revoked key for %s attempted authentication",
- found->host);
+ host);
else if (host_status == HOST_OK)
debug("%s: key for %s found at %s:%ld", __func__,
found->host, found->file, found->line);
@@ -452,107 +502,6 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
return host_status;
}
-/*
- * Check a given path for security. This is defined as all components
- * of the path to the file must be owned by either the owner of
- * of the file or root and no directories must be group or world writable.
- *
- * XXX Should any specific check be done for sym links ?
- *
- * Takes a file name, its stat information (preferably from fstat() to
- * avoid races), the uid of the expected owner, their home directory and an
- * error buffer plus max size as arguments.
- *
- * Returns 0 on success and -1 on failure
- */
-int
-auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
- uid_t uid, char *err, size_t errlen)
-{
- char buf[PATH_MAX], homedir[PATH_MAX];
- char *cp;
- int comparehome = 0;
- struct stat st;
-
- if (realpath(name, buf) == NULL) {
- snprintf(err, errlen, "realpath %s failed: %s", name,
- strerror(errno));
- return -1;
- }
- if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
- comparehome = 1;
-
- if (!S_ISREG(stp->st_mode)) {
- snprintf(err, errlen, "%s is not a regular file", buf);
- return -1;
- }
- if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
- (stp->st_mode & 022) != 0) {
-#if defined(ANDROID)
- /* needed to allow root login on Android. */
- if (getuid() != 0)
-#endif
- {
- snprintf(err, errlen, "bad ownership or modes for file %s",
- buf);
- return -1;
- }
- }
-
- /* for each component of the canonical path, walking upwards */
- for (;;) {
- if ((cp = dirname(buf)) == NULL) {
- snprintf(err, errlen, "dirname() failed");
- return -1;
- }
- strlcpy(buf, cp, sizeof(buf));
-
-#if !defined(ANDROID)
- /* /data is owned by system user, which causes this check to fail */
- if (stat(buf, &st) < 0 ||
- (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
- (st.st_mode & 022) != 0) {
- snprintf(err, errlen,
- "bad ownership or modes for directory %s", buf);
- return -1;
- }
-#endif
-
- /* If are past the homedir then we can stop */
- if (comparehome && strcmp(homedir, buf) == 0)
- break;
-
- /*
- * dirname should always complete with a "/" path,
- * but we can be paranoid and check for "." too
- */
- if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
- break;
- }
- return 0;
-}
-
-/*
- * Version of secure_path() that accepts an open file descriptor to
- * avoid races.
- *
- * Returns 0 on success and -1 on failure
- */
-static int
-secure_filename(FILE *f, const char *file, struct passwd *pw,
- char *err, size_t errlen)
-{
- struct stat st;
-
- /* check the open file to avoid races */
- if (fstat(fileno(f), &st) < 0) {
- snprintf(err, errlen, "cannot stat file %s: %s",
- file, strerror(errno));
- return -1;
- }
- return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
-}
-
static FILE *
auth_openfile(const char *file, struct passwd *pw, int strict_modes,
int log_missing, char *file_type)
@@ -569,7 +518,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
return NULL;
}
- if (fstat(fd, &st) < 0) {
+ if (fstat(fd, &st) == -1) {
close(fd);
return NULL;
}
@@ -585,7 +534,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
return NULL;
}
if (strict_modes &&
- secure_filename(f, file, pw, line, sizeof(line)) != 0) {
+ safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) {
fclose(f);
logit("Authentication refused: %s", line);
auth_debug_add("Ignored %s: %s", file_type, line);
@@ -610,7 +559,7 @@ auth_openprincipals(const char *file, struct passwd *pw, int strict_modes)
}
struct passwd *
-getpwnamallow(const char *user)
+getpwnamallow(struct ssh *ssh, const char *user)
{
#ifdef HAVE_LOGIN_CAP
extern login_cap_t *lc;
@@ -619,16 +568,19 @@ getpwnamallow(const char *user)
#endif
#endif
struct passwd *pw;
- struct connection_info *ci = get_connection_info(1, options.use_dns);
+ struct connection_info *ci;
+ ci = get_connection_info(ssh, 1, options.use_dns);
ci->user = user;
- parse_server_match_config(&options, ci);
+ parse_server_match_config(&options, &includes, ci);
+ log_change_level(options.log_level);
+ process_permitopen(ssh, &options);
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
aix_setauthdb(user);
#endif
-#ifdef ANDROID_GCE
+#if defined(ANDROID)
// Android has a fixed set of users. Any incoming user that we can't
// identify should be authenticated as the shell user.
if (strcmp(user, "root") && strcmp(user, "shell")) {
@@ -641,32 +593,19 @@ getpwnamallow(const char *user)
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
aix_restoreauthdb();
#endif
-#ifdef HAVE_CYGWIN
- /*
- * Windows usernames are case-insensitive. To avoid later problems
- * when trying to match the username, the user is only allowed to
- * login if the username is given in the same case as stored in the
- * user database.
- */
- if (pw != NULL && strcmp(user, pw->pw_name) != 0) {
- logit("Login name %.100s does not match stored username %.100s",
- user, pw->pw_name);
- pw = NULL;
- }
-#endif
if (pw == NULL) {
- logit("Invalid user %.100s from %.100s",
- user, get_remote_ipaddr());
+ logit("Invalid user %.100s from %.100s port %d",
+ user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
#ifdef CUSTOM_FAILED_LOGIN
- record_failed_login(user,
- get_canonical_hostname(options.use_dns), "ssh");
+ record_failed_login(ssh, user,
+ auth_get_canonical_hostname(ssh, options.use_dns), "ssh");
#endif
#ifdef SSH_AUDIT_EVENTS
- audit_event(SSH_INVALID_USER);
+ audit_event(ssh, SSH_INVALID_USER);
#endif /* SSH_AUDIT_EVENTS */
return (NULL);
}
- if (!allowed_user(pw))
+ if (!allowed_user(ssh, pw))
return (NULL);
#ifdef HAVE_LOGIN_CAP
if ((lc = login_getclass(pw->pw_class)) == NULL) {
@@ -690,7 +629,7 @@ getpwnamallow(const char *user)
/* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
int
-auth_key_is_revoked(Key *key)
+auth_key_is_revoked(struct sshkey *key)
{
char *fp = NULL;
int r;
@@ -732,26 +671,31 @@ auth_debug_add(const char *fmt,...)
{
char buf[1024];
va_list args;
+ int r;
- if (!auth_debug_init)
+ if (auth_debug == NULL)
return;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
- buffer_put_cstring(&auth_debug, buf);
+ if ((r = sshbuf_put_cstring(auth_debug, buf)) != 0)
+ fatal("%s: sshbuf_put_cstring: %s", __func__, ssh_err(r));
}
void
-auth_debug_send(void)
+auth_debug_send(struct ssh *ssh)
{
char *msg;
+ int r;
- if (!auth_debug_init)
+ if (auth_debug == NULL)
return;
- while (buffer_len(&auth_debug)) {
- msg = buffer_get_string(&auth_debug, NULL);
- packet_send_debug("%s", msg);
+ while (sshbuf_len(auth_debug) != 0) {
+ if ((r = sshbuf_get_cstring(auth_debug, &msg, NULL)) != 0)
+ fatal("%s: sshbuf_get_cstring: %s",
+ __func__, ssh_err(r));
+ ssh_packet_send_debug(ssh, "%s", msg);
free(msg);
}
}
@@ -759,12 +703,10 @@ auth_debug_send(void)
void
auth_debug_reset(void)
{
- if (auth_debug_init)
- buffer_clear(&auth_debug);
- else {
- buffer_init(&auth_debug);
- auth_debug_init = 1;
- }
+ if (auth_debug != NULL)
+ sshbuf_reset(auth_debug);
+ else if ((auth_debug = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
}
struct passwd *
@@ -789,3 +731,468 @@ fakepw(void)
return (&fake);
}
+
+/*
+ * Returns the remote DNS hostname as a string. The returned string must not
+ * be freed. NB. this will usually trigger a DNS query the first time it is
+ * called.
+ * This function does additional checks on the hostname to mitigate some
+ * attacks on legacy rhosts-style authentication.
+ * XXX is RhostsRSAAuthentication vulnerable to these?
+ * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
+ */
+
+static char *
+remote_hostname(struct ssh *ssh)
+{
+ struct sockaddr_storage from;
+ socklen_t fromlen;
+ struct addrinfo hints, *ai, *aitop;
+ char name[NI_MAXHOST], ntop2[NI_MAXHOST];
+ const char *ntop = ssh_remote_ipaddr(ssh);
+
+ /* Get IP address of client. */
+ fromlen = sizeof(from);
+ memset(&from, 0, sizeof(from));
+ if (getpeername(ssh_packet_get_connection_in(ssh),
+ (struct sockaddr *)&from, &fromlen) == -1) {
+ debug("getpeername failed: %.100s", strerror(errno));
+ return xstrdup(ntop);
+ }
+
+ ipv64_normalise_mapped(&from, &fromlen);
+ if (from.ss_family == AF_INET6)
+ fromlen = sizeof(struct sockaddr_in6);
+
+ debug3("Trying to reverse map address %.100s.", ntop);
+ /* Map the IP address to a host name. */
+ if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
+ NULL, 0, NI_NAMEREQD) != 0) {
+ /* Host name not found. Use ip address. */
+ return xstrdup(ntop);
+ }
+
+ /*
+ * if reverse lookup result looks like a numeric hostname,
+ * someone is trying to trick us by PTR record like following:
+ * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
+ */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
+ logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
+ name, ntop);
+ freeaddrinfo(ai);
+ return xstrdup(ntop);
+ }
+
+ /* Names are stored in lowercase. */
+ lowercase(name);
+
+ /*
+ * Map it back to an IP address and check that the given
+ * address actually is an address of this host. This is
+ * necessary because anyone with access to a name server can
+ * define arbitrary names for an IP address. Mapping from
+ * name to IP address can be trusted better (but can still be
+ * fooled if the intruder has access to the name server of
+ * the domain).
+ */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = from.ss_family;
+ hints.ai_socktype = SOCK_STREAM;
+ if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
+ logit("reverse mapping checking getaddrinfo for %.700s "
+ "[%s] failed.", name, ntop);
+ return xstrdup(ntop);
+ }
+ /* Look for the address from the list of addresses. */
+ for (ai = aitop; ai; ai = ai->ai_next) {
+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
+ sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
+ (strcmp(ntop, ntop2) == 0))
+ break;
+ }
+ freeaddrinfo(aitop);
+ /* If we reached the end of the list, the address was not there. */
+ if (ai == NULL) {
+ /* Address not found for the host name. */
+ logit("Address %.100s maps to %.600s, but this does not "
+ "map back to the address.", ntop, name);
+ return xstrdup(ntop);
+ }
+ return xstrdup(name);
+}
+
+/*
+ * Return the canonical name of the host in the other side of the current
+ * connection. The host name is cached, so it is efficient to call this
+ * several times.
+ */
+
+const char *
+auth_get_canonical_hostname(struct ssh *ssh, int use_dns)
+{
+ static char *dnsname;
+
+ if (!use_dns)
+ return ssh_remote_ipaddr(ssh);
+ else if (dnsname != NULL)
+ return dnsname;
+ else {
+ dnsname = remote_hostname(ssh);
+ return dnsname;
+ }
+}
+
+/*
+ * Runs command in a subprocess with a minimal environment.
+ * Returns pid on success, 0 on failure.
+ * The child stdout and stderr maybe captured, left attached or sent to
+ * /dev/null depending on the contents of flags.
+ * "tag" is prepended to log messages.
+ * NB. "command" is only used for logging; the actual command executed is
+ * av[0].
+ */
+pid_t
+subprocess(const char *tag, struct passwd *pw, const char *command,
+ int ac, char **av, FILE **child, u_int flags)
+{
+ FILE *f = NULL;
+ struct stat st;
+ int fd, devnull, p[2], i;
+ pid_t pid;
+ char *cp, errmsg[512];
+ u_int envsize;
+ char **child_env;
+
+ if (child != NULL)
+ *child = NULL;
+
+ debug3("%s: %s command \"%s\" running as %s (flags 0x%x)", __func__,
+ tag, command, pw->pw_name, flags);
+
+ /* Check consistency */
+ if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 &&
+ (flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) {
+ error("%s: inconsistent flags", __func__);
+ return 0;
+ }
+ if (((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) != (child == NULL)) {
+ error("%s: inconsistent flags/output", __func__);
+ return 0;
+ }
+
+ /*
+ * If executing an explicit binary, then verify the it exists
+ * and appears safe-ish to execute
+ */
+ if (!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 */
+void
+auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote)
+{
+ int do_env = options.permit_user_env && opts->nenv > 0;
+ int do_permitopen = opts->npermitopen > 0 &&
+ (options.allow_tcp_forwarding & FORWARD_LOCAL) != 0;
+ int do_permitlisten = opts->npermitlisten > 0 &&
+ (options.allow_tcp_forwarding & FORWARD_REMOTE) != 0;
+ size_t i;
+ char msg[1024], buf[64];
+
+ snprintf(buf, sizeof(buf), "%d", opts->force_tun_device);
+ /* Try to keep this alphabetically sorted */
+ snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ opts->permit_agent_forwarding_flag ? " agent-forwarding" : "",
+ opts->force_command == NULL ? "" : " command",
+ do_env ? " environment" : "",
+ opts->valid_before == 0 ? "" : "expires",
+ do_permitopen ? " permitopen" : "",
+ do_permitlisten ? " permitlisten" : "",
+ opts->permit_port_forwarding_flag ? " port-forwarding" : "",
+ opts->cert_principals == NULL ? "" : " principals",
+ opts->permit_pty_flag ? " pty" : "",
+ opts->force_tun_device == -1 ? "" : " tun=",
+ opts->force_tun_device == -1 ? "" : buf,
+ opts->permit_user_rc ? " user-rc" : "",
+ opts->permit_x11_forwarding_flag ? " x11-forwarding" : "",
+ opts->no_require_user_presence ? " no-touch-required" : "");
+
+ debug("%s: %s", loc, msg);
+ if (do_remote)
+ auth_debug_add("%s: %s", loc, msg);
+
+ if (options.permit_user_env) {
+ for (i = 0; i < opts->nenv; i++) {
+ debug("%s: environment: %s", loc, opts->env[i]);
+ if (do_remote) {
+ auth_debug_add("%s: environment: %s",
+ loc, opts->env[i]);
+ }
+ }
+ }
+
+ /* Go into a little more details for the local logs. */
+ if (opts->valid_before != 0) {
+ format_absolute_time(opts->valid_before, buf, sizeof(buf));
+ debug("%s: expires at %s", loc, buf);
+ }
+ if (opts->cert_principals != NULL) {
+ debug("%s: authorized principals: \"%s\"",
+ loc, opts->cert_principals);
+ }
+ if (opts->force_command != NULL)
+ debug("%s: forced command: \"%s\"", loc, opts->force_command);
+ if (do_permitopen) {
+ for (i = 0; i < opts->npermitopen; i++) {
+ debug("%s: permitted open: %s",
+ loc, opts->permitopen[i]);
+ }
+ }
+ if (do_permitlisten) {
+ for (i = 0; i < opts->npermitlisten; i++) {
+ debug("%s: permitted listen: %s",
+ loc, opts->permitlisten[i]);
+ }
+ }
+}
+
+/* Activate a new set of key/cert options; merging with what is there. */
+int
+auth_activate_options(struct ssh *ssh, struct sshauthopt *opts)
+{
+ struct sshauthopt *old = auth_opts;
+ const char *emsg = NULL;
+
+ debug("%s: setting new authentication options", __func__);
+ if ((auth_opts = sshauthopt_merge(old, opts, &emsg)) == NULL) {
+ error("Inconsistent authentication options: %s", emsg);
+ return -1;
+ }
+ return 0;
+}
+
+/* Disable forwarding, etc for the session */
+void
+auth_restrict_session(struct ssh *ssh)
+{
+ struct sshauthopt *restricted;
+
+ debug("%s: restricting session", __func__);
+
+ /* A blank sshauthopt defaults to permitting nothing */
+ restricted = sshauthopt_new();
+ restricted->permit_pty_flag = 1;
+ restricted->restricted = 1;
+
+ if (auth_activate_options(ssh, restricted) != 0)
+ fatal("%s: failed to restrict session", __func__);
+ sshauthopt_free(restricted);
+}
+
+int
+auth_authorise_keyopts(struct ssh *ssh, struct passwd *pw,
+ struct sshauthopt *opts, int allow_cert_authority, const char *loc)
+{
+ const char *remote_ip = ssh_remote_ipaddr(ssh);
+ const char *remote_host = auth_get_canonical_hostname(ssh,
+ options.use_dns);
+ time_t now = time(NULL);
+ char buf[64];
+
+ /*
+ * Check keys/principals file expiry time.
+ * NB. validity interval in certificate is handled elsewhere.
+ */
+ if (opts->valid_before && now > 0 &&
+ opts->valid_before < (uint64_t)now) {
+ format_absolute_time(opts->valid_before, buf, sizeof(buf));
+ debug("%s: entry expired at %s", loc, buf);
+ auth_debug_add("%s: entry expired at %s", loc, buf);
+ return -1;
+ }
+ /* Consistency checks */
+ if (opts->cert_principals != NULL && !opts->cert_authority) {
+ debug("%s: principals on non-CA key", loc);
+ auth_debug_add("%s: principals on non-CA key", loc);
+ /* deny access */
+ return -1;
+ }
+ /* cert-authority flag isn't valid in authorized_principals files */
+ if (!allow_cert_authority && opts->cert_authority) {
+ debug("%s: cert-authority flag invalid here", loc);
+ auth_debug_add("%s: cert-authority flag invalid here", loc);
+ /* deny access */
+ return -1;
+ }
+
+ /* Perform from= checks */
+ if (opts->required_from_host_keys != NULL) {
+ switch (match_host_and_ip(remote_host, remote_ip,
+ opts->required_from_host_keys )) {
+ case 1:
+ /* Host name matches. */
+ break;
+ case -1:
+ default:
+ debug("%s: invalid from criteria", loc);
+ auth_debug_add("%s: invalid from criteria", loc);
+ /* FALLTHROUGH */
+ case 0:
+ logit("%s: Authentication tried for %.100s with "
+ "correct key but not from a permitted "
+ "host (host=%.200s, ip=%.200s, required=%.200s).",
+ loc, pw->pw_name, remote_host, remote_ip,
+ opts->required_from_host_keys);
+ auth_debug_add("%s: Your host '%.200s' is not "
+ "permitted to use this key for login.",
+ loc, remote_host);
+ /* deny access */
+ return -1;
+ }
+ }
+ /* Check source-address restriction from certificate */
+ if (opts->required_from_host_cert != NULL) {
+ switch (addr_match_cidr_list(remote_ip,
+ opts->required_from_host_cert)) {
+ case 1:
+ /* accepted */
+ break;
+ case -1:
+ default:
+ /* invalid */
+ error("%s: Certificate source-address invalid",
+ loc);
+ /* FALLTHROUGH */
+ case 0:
+ logit("%s: Authentication tried for %.100s with valid "
+ "certificate but not from a permitted source "
+ "address (%.200s).", loc, pw->pw_name, remote_ip);
+ auth_debug_add("%s: Your address '%.200s' is not "
+ "permitted to use this certificate for login.",
+ loc, remote_ip);
+ return -1;
+ }
+ }
+ /*
+ *
+ * XXX this is spammy. We should report remotely only for keys
+ * that are successful in actual auth attempts, and not PK_OK
+ * tests.
+ */
+ auth_log_authopts(loc, opts, 1);
+
+ return 0;
+}
diff --git a/auth.h b/auth.h
index db860376..becc672b 100644
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.h,v 1.82 2015/02/16 22:13:32 djm Exp $ */
+/* $OpenBSD: auth.h,v 1.100 2019/09/06 05:23:55 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -30,8 +30,6 @@
#include <signal.h>
-#include <openssl/rsa.h>
-
#ifdef HAVE_LOGIN_CAP
#include <login_cap.h>
#endif
@@ -42,8 +40,11 @@
#include <krb5.h>
#endif
+struct passwd;
struct ssh;
+struct sshbuf;
struct sshkey;
+struct sshauthopt;
typedef struct Authctxt Authctxt;
typedef struct Authmethod Authmethod;
@@ -56,19 +57,23 @@ struct Authctxt {
int valid; /* user exists and is allowed to login */
int attempt;
int failures;
- int server_caused_failure;
+ int server_caused_failure;
int force_pwchange;
char *user; /* username sent by the client */
char *service;
struct passwd *pw; /* set if 'valid' */
char *style;
+
+ /* Method lists for multiple authentication */
+ char **auth_methods; /* modified from server config */
+ u_int num_auth_methods;
+
+ /* Authentication method-specific data */
+ void *methoddata;
void *kbdintctxt;
- char *info; /* Extra info for next auth_log */
#ifdef BSD_AUTH
auth_session_t *as;
#endif
- char **auth_methods; /* modified from server config */
- u_int num_auth_methods;
#ifdef KRB5
krb5_context krb5_ctx;
krb5_ccache krb5_fwd_ccache;
@@ -76,12 +81,20 @@ struct Authctxt {
char *krb5_ticket_file;
char *krb5_ccname;
#endif
- Buffer *loginmsg;
- void *methoddata;
+ struct sshbuf *loginmsg;
+
+ /* Authentication keys already used; these will be refused henceforth */
+ struct sshkey **prev_keys;
+ u_int nprev_keys;
+
+ /* Last used key and ancillary information from active auth method */
+ struct sshkey *auth_method_key;
+ char *auth_method_info;
- struct sshkey **prev_userkeys;
- u_int nprev_userkeys;
+ /* Information exposed to session */
+ struct sshbuf *session_info; /* Auth info for environment */
};
+
/*
* Every authentication method has to handle authentication requests for
* non-existing users, or for users that are not allowed to login. In this
@@ -91,7 +104,7 @@ struct Authctxt {
struct Authmethod {
char *name;
- int (*userauth)(Authctxt *authctxt);
+ int (*userauth)(struct ssh *);
int *enabled;
};
@@ -112,29 +125,27 @@ struct KbdintDevice
void (*free_ctx)(void *ctx);
};
-int auth_rhosts(struct passwd *, const char *);
int
auth_rhosts2(struct passwd *, const char *, const char *, const char *);
-int auth_rhosts_rsa(Authctxt *, char *, Key *);
-int auth_password(Authctxt *, const char *);
-int auth_rsa(Authctxt *, BIGNUM *);
-int auth_rsa_challenge_dialog(Key *);
-BIGNUM *auth_rsa_generate_challenge(Key *);
-int auth_rsa_verify_response(Key *, BIGNUM *, u_char[]);
-int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
-
-int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
-int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
-int user_key_allowed(struct passwd *, Key *);
-void pubkey_auth_info(Authctxt *, const Key *, const char *, ...)
- __attribute__((__format__ (printf, 3, 4)));
-void auth2_record_userkey(Authctxt *, struct sshkey *);
-int auth2_userkey_already_used(Authctxt *, struct sshkey *);
-
-struct stat;
-int auth_secure_path(const char *, struct stat *, const char *, uid_t,
- char *, size_t);
+int auth_password(struct ssh *, const char *);
+
+int hostbased_key_allowed(struct ssh *, struct passwd *,
+ const char *, char *, struct sshkey *);
+int user_key_allowed(struct ssh *, struct passwd *, struct sshkey *, int,
+ struct sshauthopt **);
+int auth2_key_already_used(Authctxt *, const struct sshkey *);
+
+/*
+ * Handling auth method-specific information for logging and prevention
+ * of key reuse during multiple authentication.
+ */
+void auth2_authctxt_reset_info(Authctxt *);
+void auth2_record_key(Authctxt *, int, const struct sshkey *);
+void auth2_record_info(Authctxt *authctxt, const char *, ...)
+ __attribute__((__format__ (printf, 2, 3)))
+ __attribute__((__nonnull__ (2)));
+void auth2_update_session_info(Authctxt *, const char *, const char *);
#ifdef KRB5
int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
@@ -153,20 +164,12 @@ int auth_shadow_pwexpired(Authctxt *);
#include "audit.h"
void remove_kbdint_device(const char *);
-void disable_forwarding(void);
+void do_authentication2(struct ssh *);
-void do_authentication(Authctxt *);
-void do_authentication2(Authctxt *);
-
-void auth_info(Authctxt *authctxt, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)))
- __attribute__((__nonnull__ (2)));
-void auth_log(Authctxt *, int, int, const char *, const char *);
-void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
-void userauth_finish(Authctxt *, int, const char *, const char *);
-int auth_root_allowed(const char *);
-
-void userauth_send_banner(const char *);
+void auth_log(struct ssh *, int, int, const char *, const char *);
+void auth_maxtries_exceeded(struct ssh *) __attribute__((noreturn));
+void userauth_finish(struct ssh *, int, const char *, const char *);
+int auth_root_allowed(struct ssh *, const char *);
char *auth2_read_banner(void);
int auth2_methods_valid(const char *, int);
@@ -176,54 +179,62 @@ int auth2_method_allowed(Authctxt *, const char *, const char *);
void privsep_challenge_enable(void);
-int auth2_challenge(Authctxt *, char *);
-void auth2_challenge_stop(Authctxt *);
+int auth2_challenge(struct ssh *, char *);
+void auth2_challenge_stop(struct ssh *);
int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
int bsdauth_respond(void *, u_int, char **);
-int skey_query(void *, char **, char **, u_int *, char ***, u_int **);
-int skey_respond(void *, u_int, char **);
-
-int allowed_user(struct passwd *);
-struct passwd * getpwnamallow(const char *user);
-char *get_challenge(Authctxt *);
-int verify_response(Authctxt *, const char *);
-void abandon_challenge_response(Authctxt *);
+int allowed_user(struct ssh *, struct passwd *);
+struct passwd * getpwnamallow(struct ssh *, const char *user);
char *expand_authorized_keys(const char *, struct passwd *pw);
char *authorized_principals_file(struct passwd *);
FILE *auth_openkeyfile(const char *, struct passwd *, int);
FILE *auth_openprincipals(const char *, struct passwd *, int);
-int auth_key_is_revoked(Key *);
+int auth_key_is_revoked(struct sshkey *);
+
+const char *auth_get_canonical_hostname(struct ssh *, int);
HostStatus
-check_key_in_hostfiles(struct passwd *, Key *, const char *,
+check_key_in_hostfiles(struct passwd *, struct sshkey *, const char *,
const char *, const char *);
/* hostkey handling */
-Key *get_hostkey_by_index(int);
-Key *get_hostkey_public_by_index(int, struct ssh *);
-Key *get_hostkey_public_by_type(int, int, struct ssh *);
-Key *get_hostkey_private_by_type(int, int, struct ssh *);
-int get_hostkey_index(Key *, int, struct ssh *);
-int ssh1_session_key(BIGNUM *);
-int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *,
- const u_char *, size_t, u_int);
+struct sshkey *get_hostkey_by_index(int);
+struct sshkey *get_hostkey_public_by_index(int, struct ssh *);
+struct sshkey *get_hostkey_public_by_type(int, int, struct ssh *);
+struct sshkey *get_hostkey_private_by_type(int, int, struct ssh *);
+int get_hostkey_index(struct sshkey *, int, struct ssh *);
+int sshd_hostkey_sign(struct ssh *, struct sshkey *, struct sshkey *,
+ u_char **, size_t *, const u_char *, size_t, const char *);
+
+/* Key / cert options linkage to auth layer */
+const struct sshauthopt *auth_options(struct ssh *);
+int auth_activate_options(struct ssh *, struct sshauthopt *);
+void auth_restrict_session(struct ssh *);
+int auth_authorise_keyopts(struct ssh *, struct passwd *pw,
+ struct sshauthopt *, int, const char *);
+void auth_log_authopts(const char *, const struct sshauthopt *, int);
/* debug messages during authentication */
-void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
-void auth_debug_send(void);
+void auth_debug_add(const char *fmt,...)
+ __attribute__((format(printf, 1, 2)));
+void auth_debug_send(struct ssh *);
void auth_debug_reset(void);
struct passwd *fakepw(void);
-int sys_auth_passwd(Authctxt *, const char *);
+#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);
-#define SKEY_PROMPT "\nS/Key Password: "
+int sys_auth_passwd(struct ssh *, const char *);
#if defined(KRB5) && !defined(HEIMDAL)
-#include <krb5.h>
krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *);
#endif
-#endif
+
+#endif /* AUTH_H */
diff --git a/auth1.c b/auth1.c
deleted file mode 100644
index 5073c49b..00000000
--- a/auth1.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/* $OpenBSD: auth1.c,v 1.82 2014/07/15 15:54:14 millert Exp $ */
-/*
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-
-#include "includes.h"
-
-#ifdef WITH_SSH1
-
-#include <sys/types.h>
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <pwd.h>
-
-#include "openbsd-compat/sys-queue.h"
-#include "xmalloc.h"
-#include "rsa.h"
-#include "ssh1.h"
-#include "packet.h"
-#include "buffer.h"
-#include "log.h"
-#include "misc.h"
-#include "servconf.h"
-#include "compat.h"
-#include "key.h"
-#include "hostfile.h"
-#include "auth.h"
-#include "channels.h"
-#include "session.h"
-#include "uidswap.h"
-#ifdef GSSAPI
-#include "ssh-gss.h"
-#endif
-#include "monitor_wrap.h"
-#include "buffer.h"
-
-/* import */
-extern ServerOptions options;
-extern Buffer loginmsg;
-
-static int auth1_process_password(Authctxt *);
-static int auth1_process_rsa(Authctxt *);
-static int auth1_process_rhosts_rsa(Authctxt *);
-static int auth1_process_tis_challenge(Authctxt *);
-static int auth1_process_tis_response(Authctxt *);
-
-static char *client_user = NULL; /* Used to fill in remote user for PAM */
-
-struct AuthMethod1 {
- int type;
- char *name;
- int *enabled;
- int (*method)(Authctxt *);
-};
-
-const struct AuthMethod1 auth1_methods[] = {
- {
- SSH_CMSG_AUTH_PASSWORD, "password",
- &options.password_authentication, auth1_process_password
- },
- {
- SSH_CMSG_AUTH_RSA, "rsa",
- &options.rsa_authentication, auth1_process_rsa
- },
- {
- SSH_CMSG_AUTH_RHOSTS_RSA, "rhosts-rsa",
- &options.rhosts_rsa_authentication, auth1_process_rhosts_rsa
- },
- {
- SSH_CMSG_AUTH_TIS, "challenge-response",
- &options.challenge_response_authentication,
- auth1_process_tis_challenge
- },
- {
- SSH_CMSG_AUTH_TIS_RESPONSE, "challenge-response",
- &options.challenge_response_authentication,
- auth1_process_tis_response
- },
- { -1, NULL, NULL, NULL}
-};
-
-static const struct AuthMethod1
-*lookup_authmethod1(int type)
-{
- int i;
-
- for (i = 0; auth1_methods[i].name != NULL; i++)
- if (auth1_methods[i].type == type)
- return (&(auth1_methods[i]));
-
- return (NULL);
-}
-
-static char *
-get_authname(int type)
-{
- const struct AuthMethod1 *a;
- static char buf[64];
-
- if ((a = lookup_authmethod1(type)) != NULL)
- return (a->name);
- snprintf(buf, sizeof(buf), "bad-auth-msg-%d", type);
- return (buf);
-}
-
-/*ARGSUSED*/
-static int
-auth1_process_password(Authctxt *authctxt)
-{
- int authenticated = 0;
- char *password;
- u_int dlen;
-
- /*
- * Read user password. It is in plain text, but was
- * transmitted over the encrypted channel so it is
- * not visible to an outside observer.
- */
- password = packet_get_string(&dlen);
- packet_check_eom();
-
- /* Try authentication with the password. */
- authenticated = PRIVSEP(auth_password(authctxt, password));
-
- explicit_bzero(password, dlen);
- free(password);
-
- return (authenticated);
-}
-
-/*ARGSUSED*/
-static int
-auth1_process_rsa(Authctxt *authctxt)
-{
- int authenticated = 0;
- BIGNUM *n;
-
- /* RSA authentication requested. */
- if ((n = BN_new()) == NULL)
- fatal("do_authloop: BN_new failed");
- packet_get_bignum(n);
- packet_check_eom();
- authenticated = auth_rsa(authctxt, n);
- BN_clear_free(n);
-
- return (authenticated);
-}
-
-/*ARGSUSED*/
-static int
-auth1_process_rhosts_rsa(Authctxt *authctxt)
-{
- int keybits, authenticated = 0;
- u_int bits;
- Key *client_host_key;
- u_int ulen;
-
- /*
- * Get client user name. Note that we just have to
- * trust the client; root on the client machine can
- * claim to be any user.
- */
- client_user = packet_get_cstring(&ulen);
-
- /* Get the client host key. */
- client_host_key = key_new(KEY_RSA1);
- bits = packet_get_int();
- packet_get_bignum(client_host_key->rsa->e);
- packet_get_bignum(client_host_key->rsa->n);
-
- keybits = BN_num_bits(client_host_key->rsa->n);
- if (keybits < 0 || bits != (u_int)keybits) {
- verbose("Warning: keysize mismatch for client_host_key: "
- "actual %d, announced %d",
- BN_num_bits(client_host_key->rsa->n), bits);
- }
- packet_check_eom();
-
- authenticated = auth_rhosts_rsa(authctxt, client_user,
- client_host_key);
- key_free(client_host_key);
-
- auth_info(authctxt, "ruser %.100s", client_user);
-
- return (authenticated);
-}
-
-/*ARGSUSED*/
-static int
-auth1_process_tis_challenge(Authctxt *authctxt)
-{
- char *challenge;
-
- if ((challenge = get_challenge(authctxt)) == NULL)
- return (0);
-
- debug("sending challenge '%s'", challenge);
- packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
- packet_put_cstring(challenge);
- free(challenge);
- packet_send();
- packet_write_wait();
-
- return (-1);
-}
-
-/*ARGSUSED*/
-static int
-auth1_process_tis_response(Authctxt *authctxt)
-{
- int authenticated = 0;
- char *response;
- u_int dlen;
-
- response = packet_get_string(&dlen);
- packet_check_eom();
- authenticated = verify_response(authctxt, response);
- explicit_bzero(response, dlen);
- free(response);
-
- return (authenticated);
-}
-
-/*
- * read packets, try to authenticate the user and
- * return only if authentication is successful
- */
-static void
-do_authloop(Authctxt *authctxt)
-{
- int authenticated = 0;
- int prev = 0, type = 0;
- const struct AuthMethod1 *meth;
-
- debug("Attempting authentication for %s%.100s.",
- authctxt->valid ? "" : "invalid user ", authctxt->user);
-
- /* If the user has no password, accept authentication immediately. */
- if (options.permit_empty_passwd && options.password_authentication &&
-#ifdef KRB5
- (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
-#endif
- PRIVSEP(auth_password(authctxt, ""))) {
-#ifdef USE_PAM
- if (options.use_pam && (PRIVSEP(do_pam_account())))
-#endif
- {
- auth_log(authctxt, 1, 0, "without authentication",
- NULL);
- return;
- }
- }
-
- /* Indicate that authentication is needed. */
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
-
- for (;;) {
- /* default to fail */
- authenticated = 0;
-
-
- /* Get a packet from the client. */
- prev = type;
- type = packet_read();
-
- /*
- * If we started challenge-response authentication but the
- * next packet is not a response to our challenge, release
- * the resources allocated by get_challenge() (which would
- * normally have been released by verify_response() had we
- * received such a response)
- */
- if (prev == SSH_CMSG_AUTH_TIS &&
- type != SSH_CMSG_AUTH_TIS_RESPONSE)
- abandon_challenge_response(authctxt);
-
- if (authctxt->failures >= options.max_authtries)
- goto skip;
- if ((meth = lookup_authmethod1(type)) == NULL) {
- logit("Unknown message during authentication: "
- "type %d", type);
- goto skip;
- }
-
- if (!*(meth->enabled)) {
- verbose("%s authentication disabled.", meth->name);
- goto skip;
- }
-
- authenticated = meth->method(authctxt);
- if (authenticated == -1)
- continue; /* "postponed" */
-
-#ifdef BSD_AUTH
- if (authctxt->as) {
- auth_close(authctxt->as);
- authctxt->as = NULL;
- }
-#endif
- if (!authctxt->valid && authenticated)
- fatal("INTERNAL ERROR: authenticated invalid user %s",
- authctxt->user);
-
-#ifdef _UNICOS
- if (authenticated && cray_access_denied(authctxt->user)) {
- authenticated = 0;
- fatal("Access denied for user %s.",authctxt->user);
- }
-#endif /* _UNICOS */
-
-#ifndef HAVE_CYGWIN
- /* Special handling for root */
- if (authenticated && authctxt->pw->pw_uid == 0 &&
- !auth_root_allowed(meth->name)) {
- authenticated = 0;
-# ifdef SSH_AUDIT_EVENTS
- PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
-# endif
- }
-#endif
-
-#ifdef USE_PAM
- if (options.use_pam && authenticated &&
- !PRIVSEP(do_pam_account())) {
- char *msg;
- size_t len;
-
- error("Access denied for user %s by PAM account "
- "configuration", authctxt->user);
- len = buffer_len(&loginmsg);
- buffer_append(&loginmsg, "\0", 1);
- msg = buffer_ptr(&loginmsg);
- /* strip trailing newlines */
- if (len > 0)
- while (len > 0 && msg[--len] == '\n')
- msg[len] = '\0';
- else
- msg = "Access denied.";
- packet_disconnect("%s", msg);
- }
-#endif
-
- skip:
- /* Log before sending the reply */
- auth_log(authctxt, authenticated, 0, get_authname(type), NULL);
-
- free(client_user);
- client_user = NULL;
-
- if (authenticated)
- return;
-
- if (++authctxt->failures >= options.max_authtries) {
-#ifdef SSH_AUDIT_EVENTS
- PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
-#endif
- auth_maxtries_exceeded(authctxt);
- }
-
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
- }
-}
-
-/*
- * Performs authentication of an incoming connection. Session key has already
- * been exchanged and encryption is enabled.
- */
-void
-do_authentication(Authctxt *authctxt)
-{
- u_int ulen;
- char *user, *style = NULL;
-
- /* Get the name of the user that we wish to log in as. */
- packet_read_expect(SSH_CMSG_USER);
-
- /* Get the user name. */
- user = packet_get_cstring(&ulen);
- packet_check_eom();
-
- if ((style = strchr(user, ':')) != NULL)
- *style++ = '\0';
-
- authctxt->user = user;
- authctxt->style = style;
-
- /* Verify that the user is a valid user. */
- if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
- authctxt->valid = 1;
- else {
- debug("do_authentication: invalid user %s", user);
- authctxt->pw = fakepw();
- }
-
- /* Configuration may have changed as a result of Match */
- if (options.num_auth_methods != 0)
- fatal("AuthenticationMethods is not supported with SSH "
- "protocol 1");
-
- setproctitle("%s%s", authctxt->valid ? user : "unknown",
- use_privsep ? " [net]" : "");
-
-#ifdef USE_PAM
- if (options.use_pam)
- PRIVSEP(start_pam(authctxt));
-#endif
-
- /*
- * If we are not running as root, the user must have the same uid as
- * the server.
- */
-#ifndef HAVE_CYGWIN
- if (!use_privsep && getuid() != 0 && authctxt->pw &&
- authctxt->pw->pw_uid != getuid())
- packet_disconnect("Cannot change user when server not running as root.");
-#endif
-
- /*
- * Loop until the user has been authenticated or the connection is
- * closed, do_authloop() returns only if authentication is successful
- */
- do_authloop(authctxt);
-
- /* The user has been authenticated and accepted. */
- packet_start(SSH_SMSG_SUCCESS);
- packet_send();
- packet_write_wait();
-}
-
-#endif /* WITH_SSH1 */
diff --git a/auth2-chall.c b/auth2-chall.c
index ddabe1a9..3acd0a83 100644
--- a/auth2-chall.c
+++ b/auth2-chall.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-chall.c,v 1.42 2015/01/19 20:07:45 markus Exp $ */
+/* $OpenBSD: auth2-chall.c,v 1.53 2020/02/26 13:40:09 jsg Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2001 Per Allansson. All rights reserved.
@@ -28,18 +28,20 @@
#include <sys/types.h>
-#include <stdarg.h>
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <stdarg.h>
#include "xmalloc.h"
#include "ssh2.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "packet.h"
#include "dispatch.h"
+#include "ssherr.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
@@ -47,9 +49,9 @@
/* import */
extern ServerOptions options;
-static int auth2_challenge_start(Authctxt *);
-static int send_userauth_info_request(Authctxt *);
-static int input_userauth_info_response(int, u_int32_t, void *);
+static int auth2_challenge_start(struct ssh *);
+static int send_userauth_info_request(struct ssh *);
+static int input_userauth_info_response(int, u_int32_t, struct ssh *);
#ifdef BSD_AUTH
extern KbdintDevice bsdauth_device;
@@ -57,9 +59,6 @@ extern KbdintDevice bsdauth_device;
#ifdef USE_PAM
extern KbdintDevice sshpam_device;
#endif
-#ifdef SKEY
-extern KbdintDevice skey_device;
-#endif
#endif
KbdintDevice *devices[] = {
@@ -69,9 +68,6 @@ KbdintDevice *devices[] = {
#ifdef USE_PAM
&sshpam_device,
#endif
-#ifdef SKEY
- &skey_device,
-#endif
#endif
NULL
};
@@ -83,6 +79,7 @@ struct KbdintAuthctxt
void *ctxt;
KbdintDevice *device;
u_int nreq;
+ u_int devices_done;
};
#ifdef USE_PAM
@@ -104,8 +101,8 @@ static KbdintAuthctxt *
kbdint_alloc(const char *devs)
{
KbdintAuthctxt *kbdintctxt;
- Buffer b;
- int i;
+ struct sshbuf *b;
+ int i, r;
#ifdef USE_PAM
if (!options.use_pam)
@@ -114,16 +111,17 @@ kbdint_alloc(const char *devs)
kbdintctxt = xcalloc(1, sizeof(KbdintAuthctxt));
if (strcmp(devs, "") == 0) {
- buffer_init(&b);
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
for (i = 0; devices[i]; i++) {
- if (buffer_len(&b) > 0)
- buffer_append(&b, ",", 1);
- buffer_append(&b, devices[i]->name,
- strlen(devices[i]->name));
+ if ((r = sshbuf_putf(b, "%s%s",
+ sshbuf_len(b) ? "," : "", devices[i]->name)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
}
- buffer_append(&b, "\0", 1);
- kbdintctxt->devices = xstrdup(buffer_ptr(&b));
- buffer_free(&b);
+ if ((kbdintctxt->devices = sshbuf_dup_string(b)) == NULL)
+ fatal("%s: sshbuf_dup_string failed", __func__);
+ sshbuf_free(b);
} else {
kbdintctxt->devices = xstrdup(devs);
}
@@ -149,8 +147,7 @@ kbdint_free(KbdintAuthctxt *kbdintctxt)
if (kbdintctxt->device)
kbdint_reset_device(kbdintctxt);
free(kbdintctxt->devices);
- explicit_bzero(kbdintctxt, sizeof(*kbdintctxt));
- free(kbdintctxt);
+ freezero(kbdintctxt, sizeof(*kbdintctxt));
}
/* get next device */
static int
@@ -169,11 +166,15 @@ kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt)
if (len == 0)
break;
for (i = 0; devices[i]; i++) {
- if (!auth2_method_allowed(authctxt,
+ if ((kbdintctxt->devices_done & (1 << i)) != 0 ||
+ !auth2_method_allowed(authctxt,
"keyboard-interactive", devices[i]->name))
continue;
- if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0)
+ if (strncmp(kbdintctxt->devices, devices[i]->name,
+ len) == 0) {
kbdintctxt->device = devices[i];
+ kbdintctxt->devices_done |= 1 << i;
+ }
}
t = kbdintctxt->devices;
kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL;
@@ -190,8 +191,9 @@ kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt)
* wait for the response.
*/
int
-auth2_challenge(Authctxt *authctxt, char *devs)
+auth2_challenge(struct ssh *ssh, char *devs)
{
+ Authctxt *authctxt = ssh->authctxt;
debug("auth2_challenge: user=%s devs=%s",
authctxt->user ? authctxt->user : "<nouser>",
devs ? devs : "<no devs>");
@@ -200,15 +202,16 @@ auth2_challenge(Authctxt *authctxt, char *devs)
return 0;
if (authctxt->kbdintctxt == NULL)
authctxt->kbdintctxt = kbdint_alloc(devs);
- return auth2_challenge_start(authctxt);
+ return auth2_challenge_start(ssh);
}
/* unregister kbd-int callbacks and context */
void
-auth2_challenge_stop(Authctxt *authctxt)
+auth2_challenge_stop(struct ssh *ssh)
{
+ Authctxt *authctxt = ssh->authctxt;
/* unregister callback */
- dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
if (authctxt->kbdintctxt != NULL) {
kbdint_free(authctxt->kbdintctxt);
authctxt->kbdintctxt = NULL;
@@ -217,29 +220,30 @@ auth2_challenge_stop(Authctxt *authctxt)
/* side effect: sets authctxt->postponed if a reply was sent*/
static int
-auth2_challenge_start(Authctxt *authctxt)
+auth2_challenge_start(struct ssh *ssh)
{
+ Authctxt *authctxt = ssh->authctxt;
KbdintAuthctxt *kbdintctxt = authctxt->kbdintctxt;
debug2("auth2_challenge_start: devices %s",
kbdintctxt->devices ? kbdintctxt->devices : "<empty>");
if (kbdint_next_device(authctxt, kbdintctxt) == 0) {
- auth2_challenge_stop(authctxt);
+ auth2_challenge_stop(ssh);
return 0;
}
debug("auth2_challenge_start: trying authentication method '%s'",
kbdintctxt->device->name);
if ((kbdintctxt->ctxt = kbdintctxt->device->init_ctx(authctxt)) == NULL) {
- auth2_challenge_stop(authctxt);
+ auth2_challenge_stop(ssh);
return 0;
}
- if (send_userauth_info_request(authctxt) == 0) {
- auth2_challenge_stop(authctxt);
+ if (send_userauth_info_request(ssh) == 0) {
+ auth2_challenge_stop(ssh);
return 0;
}
- dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE,
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE,
&input_userauth_info_response);
authctxt->postponed = 1;
@@ -247,28 +251,32 @@ auth2_challenge_start(Authctxt *authctxt)
}
static int
-send_userauth_info_request(Authctxt *authctxt)
+send_userauth_info_request(struct ssh *ssh)
{
+ Authctxt *authctxt = ssh->authctxt;
KbdintAuthctxt *kbdintctxt;
char *name, *instr, **prompts;
- u_int i, *echo_on;
+ u_int r, i, *echo_on;
kbdintctxt = authctxt->kbdintctxt;
if (kbdintctxt->device->query(kbdintctxt->ctxt,
&name, &instr, &kbdintctxt->nreq, &prompts, &echo_on))
return 0;
- packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
- packet_put_cstring(name);
- packet_put_cstring(instr);
- packet_put_cstring(""); /* language not used */
- packet_put_int(kbdintctxt->nreq);
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, name)) != 0 ||
+ (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));
for (i = 0; i < kbdintctxt->nreq; i++) {
- packet_put_cstring(prompts[i]);
- packet_put_char(echo_on[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));
}
- packet_send();
- packet_write_wait();
+ if ((r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
for (i = 0; i < kbdintctxt->nreq; i++)
free(prompts[i]);
@@ -280,11 +288,12 @@ send_userauth_info_request(Authctxt *authctxt)
}
static int
-input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
+input_userauth_info_response(int type, u_int32_t seq, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
+ Authctxt *authctxt = ssh->authctxt;
KbdintAuthctxt *kbdintctxt;
int authenticated = 0, res;
+ int r;
u_int i, nresp;
const char *devicename = NULL;
char **response = NULL;
@@ -298,7 +307,8 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
fatal("input_userauth_info_response: no device");
authctxt->postponed = 0; /* reset */
- nresp = packet_get_int();
+ if ((r = sshpkt_get_u32(ssh, &nresp)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
if (nresp != kbdintctxt->nreq)
fatal("input_userauth_info_response: wrong number of replies");
if (nresp > 100)
@@ -306,9 +316,12 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
if (nresp > 0) {
response = xcalloc(nresp, sizeof(char *));
for (i = 0; i < nresp; i++)
- response[i] = packet_get_string(NULL);
+ if ((r = sshpkt_get_cstring(ssh, &response[i],
+ NULL)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
}
- packet_check_eom();
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response);
@@ -325,7 +338,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
break;
case 1:
/* Authentication needs further interaction */
- if (send_userauth_info_request(authctxt) == 1)
+ if (send_userauth_info_request(ssh) == 1)
authctxt->postponed = 1;
break;
default:
@@ -335,14 +348,14 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
devicename = kbdintctxt->device->name;
if (!authctxt->postponed) {
if (authenticated) {
- auth2_challenge_stop(authctxt);
+ auth2_challenge_stop(ssh);
} else {
/* start next device */
/* may set authctxt->postponed */
- auth2_challenge_start(authctxt);
+ auth2_challenge_start(ssh);
}
}
- userauth_finish(authctxt, authenticated, "keyboard-interactive",
+ userauth_finish(ssh, authenticated, "keyboard-interactive",
devicename);
return 0;
}
@@ -350,7 +363,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
void
privsep_challenge_enable(void)
{
-#if defined(BSD_AUTH) || defined(USE_PAM) || defined(SKEY)
+#if defined(BSD_AUTH) || defined(USE_PAM)
int n = 0;
#endif
#ifdef BSD_AUTH
@@ -359,9 +372,6 @@ privsep_challenge_enable(void)
#ifdef USE_PAM
extern KbdintDevice mm_sshpam_device;
#endif
-#ifdef SKEY
- extern KbdintDevice mm_skey_device;
-#endif
#ifdef BSD_AUTH
devices[n++] = &mm_bsdauth_device;
@@ -369,8 +379,5 @@ privsep_challenge_enable(void)
#ifdef USE_PAM
devices[n++] = &mm_sshpam_device;
#endif
-#ifdef SKEY
- devices[n++] = &mm_skey_device;
-#endif
#endif
}
diff --git a/auth2-gss.c b/auth2-gss.c
index 1ca83577..9351e042 100644
--- a/auth2-gss.c
+++ b/auth2-gss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-gss.c,v 1.22 2015/01/19 20:07:45 markus Exp $ */
+/* $OpenBSD: auth2-gss.c,v 1.29 2018/07/31 03:10:27 djm Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@@ -33,13 +33,14 @@
#include <stdarg.h>
#include "xmalloc.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "ssh2.h"
#include "log.h"
#include "dispatch.h"
-#include "buffer.h"
+#include "sshbuf.h"
+#include "ssherr.h"
#include "misc.h"
#include "servconf.h"
#include "packet.h"
@@ -48,30 +49,30 @@
extern ServerOptions options;
-static int input_gssapi_token(int type, u_int32_t plen, void *ctxt);
-static int input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
-static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
-static int input_gssapi_errtok(int, u_int32_t, void *);
+static int input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh);
+static int input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh);
+static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh);
+static int input_gssapi_errtok(int, u_int32_t, struct ssh *);
/*
* We only support those mechanisms that we know about (ie ones that we know
* how to check local user kuserok and the like)
*/
static int
-userauth_gssapi(Authctxt *authctxt)
+userauth_gssapi(struct ssh *ssh)
{
+ Authctxt *authctxt = ssh->authctxt;
gss_OID_desc goid = {0, NULL};
Gssctxt *ctxt = NULL;
- int mechs;
- int present;
+ int r, present;
+ u_int mechs;
OM_uint32 ms;
- u_int len;
+ size_t len;
u_char *doid = NULL;
- if (!authctxt->valid || authctxt->user == NULL)
- return (0);
+ if ((r = sshpkt_get_u32(ssh, &mechs)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
- mechs = packet_get_int();
if (mechs == 0) {
debug("Mechanism negotiation is not supported");
return (0);
@@ -83,7 +84,8 @@ userauth_gssapi(Authctxt *authctxt)
free(doid);
present = 0;
- doid = packet_get_string(&len);
+ if ((r = sshpkt_get_string(ssh, &doid, &len)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
if (len > 2 && doid[0] == SSH_GSS_OIDTYPE &&
doid[1] == len - 2) {
@@ -101,6 +103,12 @@ userauth_gssapi(Authctxt *authctxt)
return (0);
}
+ if (!authctxt->valid || authctxt->user == NULL) {
+ debug2("%s: disabled because of invalid user", __func__);
+ free(doid);
+ return (0);
+ }
+
if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
if (ctxt != NULL)
ssh_gssapi_delete_ctx(&ctxt);
@@ -111,67 +119,76 @@ userauth_gssapi(Authctxt *authctxt)
authctxt->methoddata = (void *)ctxt;
- packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);
-
/* Return the OID that we received */
- packet_put_string(doid, len);
+ 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));
- packet_send();
free(doid);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
authctxt->postponed = 1;
return (0);
}
static int
-input_gssapi_token(int type, u_int32_t plen, void *ctxt)
+input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
+ Authctxt *authctxt = ssh->authctxt;
Gssctxt *gssctxt;
gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
gss_buffer_desc recv_tok;
OM_uint32 maj_status, min_status, flags;
- u_int len;
+ u_char *p;
+ size_t len;
+ int r;
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
fatal("No authentication or GSSAPI context");
gssctxt = authctxt->methoddata;
- recv_tok.value = packet_get_string(&len);
- recv_tok.length = len; /* u_int vs. size_t */
-
- packet_check_eom();
+ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+ recv_tok.value = p;
+ recv_tok.length = len;
maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
&send_tok, &flags));
- free(recv_tok.value);
+ free(p);
if (GSS_ERROR(maj_status)) {
if (send_tok.length != 0) {
- packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
- packet_put_string(send_tok.value, send_tok.length);
- packet_send();
+ if ((r = sshpkt_start(ssh,
+ SSH2_MSG_USERAUTH_GSSAPI_ERRTOK)) != 0 ||
+ (r = sshpkt_put_string(ssh, send_tok.value,
+ send_tok.length)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
}
authctxt->postponed = 0;
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
- userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+ userauth_finish(ssh, 0, "gssapi-with-mic", NULL);
} else {
if (send_tok.length != 0) {
- packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
- packet_put_string(send_tok.value, send_tok.length);
- packet_send();
+ if ((r = sshpkt_start(ssh,
+ SSH2_MSG_USERAUTH_GSSAPI_TOKEN)) != 0 ||
+ (r = sshpkt_put_string(ssh, send_tok.value,
+ send_tok.length)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
}
if (maj_status == GSS_S_COMPLETE) {
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
if (flags & GSS_C_INTEG_FLAG)
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC,
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC,
&input_gssapi_mic);
else
- dispatch_set(
+ ssh_dispatch_set(ssh,
SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
&input_gssapi_exchange_complete);
}
@@ -182,24 +199,27 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
}
static int
-input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
+input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
+ Authctxt *authctxt = ssh->authctxt;
Gssctxt *gssctxt;
gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
gss_buffer_desc recv_tok;
OM_uint32 maj_status;
- u_int len;
+ int r;
+ u_char *p;
+ size_t len;
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
fatal("No authentication or GSSAPI context");
gssctxt = authctxt->methoddata;
- recv_tok.value = packet_get_string(&len);
+ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+ recv_tok.value = p;
recv_tok.length = len;
- packet_check_eom();
-
/* Push the error token into GSSAPI to see what it says */
maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
&send_tok, NULL));
@@ -207,8 +227,8 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
free(recv_tok.value);
/* We can't return anything to the client, even if we wanted to */
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
/* The client will have already moved on to the next auth */
@@ -223,10 +243,11 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
*/
static int
-input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
+input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
- int authenticated;
+ Authctxt *authctxt = ssh->authctxt;
+ int r, authenticated;
+ const char *displayname;
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
fatal("No authentication or GSSAPI context");
@@ -236,57 +257,72 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
* the dispatcher once the exchange is complete
*/
- packet_check_eom();
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+ if ((!use_privsep || mm_is_monitor()) &&
+ (displayname = ssh_gssapi_displayname()) != NULL)
+ auth2_record_info(authctxt, "%s", displayname);
+
authctxt->postponed = 0;
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
- userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
+ userauth_finish(ssh, authenticated, "gssapi-with-mic", NULL);
return 0;
}
static int
-input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
+input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
+ Authctxt *authctxt = ssh->authctxt;
Gssctxt *gssctxt;
- int authenticated = 0;
- Buffer b;
+ int r, authenticated = 0;
+ struct sshbuf *b;
gss_buffer_desc mic, gssbuf;
- u_int len;
+ const char *displayname;
+ u_char *p;
+ size_t len;
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
fatal("No authentication or GSSAPI context");
gssctxt = authctxt->methoddata;
- mic.value = packet_get_string(&len);
+ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ mic.value = p;
mic.length = len;
-
- ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
+ ssh_gssapi_buildmic(b, authctxt->user, authctxt->service,
"gssapi-with-mic");
- gssbuf.value = buffer_ptr(&b);
- gssbuf.length = buffer_len(&b);
+ if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL)
+ fatal("%s: sshbuf_mutable_ptr failed", __func__);
+ gssbuf.length = sshbuf_len(b);
if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
else
logit("GSSAPI MIC check failed");
- buffer_free(&b);
+ sshbuf_free(b);
free(mic.value);
+ if ((!use_privsep || mm_is_monitor()) &&
+ (displayname = ssh_gssapi_displayname()) != NULL)
+ auth2_record_info(authctxt, "%s", displayname);
+
authctxt->postponed = 0;
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
- userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
+ userauth_finish(ssh, authenticated, "gssapi-with-mic", NULL);
return 0;
}
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index eebfe8fc..5e9b7c65 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-hostbased.c,v 1.24 2015/01/28 22:36:00 djm Exp $ */
+/* $OpenBSD: auth2-hostbased.c,v 1.42 2019/11/25 00:51:37 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -27,6 +27,7 @@
#include <sys/types.h>
+#include <stdlib.h>
#include <pwd.h>
#include <string.h>
#include <stdarg.h>
@@ -34,12 +35,12 @@
#include "xmalloc.h"
#include "ssh2.h"
#include "packet.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "canohost.h"
@@ -48,6 +49,7 @@
#endif
#include "monitor_wrap.h"
#include "pathnames.h"
+#include "ssherr.h"
#include "match.h"
/* import */
@@ -56,98 +58,107 @@ extern u_char *session_id2;
extern u_int session_id2_len;
static int
-userauth_hostbased(Authctxt *authctxt)
+userauth_hostbased(struct ssh *ssh)
{
- Buffer b;
- Key *key = NULL;
- char *pkalg, *cuser, *chost, *service;
+ Authctxt *authctxt = ssh->authctxt;
+ struct sshbuf *b;
+ struct sshkey *key = NULL;
+ char *pkalg, *cuser, *chost;
u_char *pkblob, *sig;
- u_int alen, blen, slen;
- int pktype;
- int authenticated = 0;
+ size_t alen, blen, slen;
+ int r, pktype, authenticated = 0;
- if (!authctxt->valid) {
- debug2("userauth_hostbased: disabled because of invalid user");
- return 0;
- }
- pkalg = packet_get_string(&alen);
- pkblob = packet_get_string(&blen);
- chost = packet_get_string(NULL);
- cuser = packet_get_string(NULL);
- sig = packet_get_string(&slen);
+ /* XXX use sshkey_froms() */
+ if ((r = sshpkt_get_cstring(ssh, &pkalg, &alen)) != 0 ||
+ (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &chost, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &cuser, NULL)) != 0 ||
+ (r = sshpkt_get_string(ssh, &sig, &slen)) != 0)
+ fatal("%s: packet parsing: %s", __func__, ssh_err(r));
- debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
+ debug("%s: cuser %s chost %s pkalg %s slen %zu", __func__,
cuser, chost, pkalg, slen);
#ifdef DEBUG_PK
debug("signature:");
- buffer_init(&b);
- buffer_append(&b, sig, slen);
- buffer_dump(&b);
- buffer_free(&b);
+ sshbuf_dump_data(sig, slen, stderr);
#endif
- pktype = key_type_from_name(pkalg);
+ pktype = sshkey_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
- logit("userauth_hostbased: unsupported "
- "public key algorithm: %s", pkalg);
+ logit("%s: unsupported public key algorithm: %s",
+ __func__, pkalg);
+ goto done;
+ }
+ if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
+ error("%s: key_from_blob: %s", __func__, ssh_err(r));
goto done;
}
- key = key_from_blob(pkblob, blen);
if (key == NULL) {
- error("userauth_hostbased: cannot decode key: %s", pkalg);
+ error("%s: cannot decode key: %s", __func__, pkalg);
goto done;
}
if (key->type != pktype) {
- error("userauth_hostbased: type mismatch for decoded key "
- "(received %d, expected %d)", key->type, pktype);
+ error("%s: type mismatch for decoded key "
+ "(received %d, expected %d)", __func__, key->type, pktype);
goto done;
}
- if (key_type_plain(key->type) == KEY_RSA &&
- (datafellows & SSH_BUG_RSASIGMD5) != 0) {
+ if (sshkey_type_plain(key->type) == KEY_RSA &&
+ (ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
error("Refusing RSA key because peer uses unsafe "
"signature format");
goto done;
}
- if (match_pattern_list(sshkey_ssh_name(key),
- options.hostbased_key_types,
- strlen(options.hostbased_key_types), 0) != 1) {
+ if (match_pattern_list(pkalg, options.hostbased_key_types, 0) != 1) {
logit("%s: key type %s not in HostbasedAcceptedKeyTypes",
__func__, sshkey_type(key));
goto done;
}
+ if ((r = sshkey_check_cert_sigtype(key,
+ options.ca_sign_algorithms)) != 0) {
+ logit("%s: certificate signature algorithm %s: %s", __func__,
+ (key->cert == NULL || key->cert->signature_type == NULL) ?
+ "(null)" : key->cert->signature_type, ssh_err(r));
+ goto done;
+ }
+
+ if (!authctxt->valid || authctxt->user == NULL) {
+ debug2("%s: disabled because of invalid user", __func__);
+ goto done;
+ }
- service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
- authctxt->service;
- buffer_init(&b);
- buffer_put_string(&b, session_id2, session_id2_len);
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
/* reconstruct packet */
- buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
- buffer_put_cstring(&b, authctxt->user);
- buffer_put_cstring(&b, service);
- buffer_put_cstring(&b, "hostbased");
- buffer_put_string(&b, pkalg, alen);
- buffer_put_string(&b, pkblob, blen);
- buffer_put_cstring(&b, chost);
- buffer_put_cstring(&b, cuser);
+ if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 ||
+ (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
+ (r = sshbuf_put_cstring(b, authctxt->user)) != 0 ||
+ (r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
+ (r = sshbuf_put_cstring(b, "hostbased")) != 0 ||
+ (r = sshbuf_put_string(b, pkalg, alen)) != 0 ||
+ (r = sshbuf_put_string(b, pkblob, blen)) != 0 ||
+ (r = sshbuf_put_cstring(b, chost)) != 0 ||
+ (r = sshbuf_put_cstring(b, cuser)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
#ifdef DEBUG_PK
- buffer_dump(&b);
+ sshbuf_dump(b, stderr);
#endif
- pubkey_auth_info(authctxt, key,
+ auth2_record_info(authctxt,
"client user \"%.100s\", client host \"%.100s\"", cuser, chost);
/* test for allowed key and correct signature */
authenticated = 0;
- if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
- buffer_len(&b))) == 1)
+ if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser,
+ chost, key)) &&
+ PRIVSEP(sshkey_verify(key, sig, slen,
+ sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL)) == 0)
authenticated = 1;
- buffer_free(&b);
+ auth2_record_key(authctxt, authenticated, key);
+ sshbuf_free(b);
done:
- debug2("userauth_hostbased: authenticated %d", authenticated);
- if (key != NULL)
- key_free(key);
+ debug2("%s: authenticated %d", __func__, authenticated);
+ sshkey_free(key);
free(pkalg);
free(pkblob);
free(cuser);
@@ -158,8 +169,8 @@ done:
/* return 1 if given hostkey is allowed */
int
-hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
- Key *key)
+hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
+ const char *cuser, char *chost, struct sshkey *key)
{
const char *resolvedname, *ipaddr, *lookup, *reason;
HostStatus host_status;
@@ -169,8 +180,8 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
if (auth_key_is_revoked(key))
return 0;
- resolvedname = get_canonical_hostname(options.use_dns);
- ipaddr = get_remote_ipaddr();
+ resolvedname = auth_get_canonical_hostname(ssh, options.use_dns);
+ ipaddr = ssh_remote_ipaddr(ssh);
debug2("%s: chost %s resolvedname %s ipaddr %s", __func__,
chost, resolvedname, ipaddr);
@@ -203,8 +214,8 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
}
debug2("%s: access allowed by auth_rhosts2", __func__);
- if (key_is_cert(key) &&
- key_cert_check_authority(key, 1, 0, lookup, &reason)) {
+ if (sshkey_is_cert(key) &&
+ sshkey_cert_check_authority(key, 1, 0, lookup, &reason)) {
error("%s", reason);
auth_debug_add("%s", reason);
return 0;
@@ -223,20 +234,20 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
}
if (host_status == HOST_OK) {
- if (key_is_cert(key)) {
+ if (sshkey_is_cert(key)) {
if ((fp = sshkey_fingerprint(key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
verbose("Accepted certificate ID \"%s\" signed by "
"%s CA %s from %s@%s", key->cert->key_id,
- key_type(key->cert->signature_key), fp,
+ sshkey_type(key->cert->signature_key), fp,
cuser, lookup);
} else {
if ((fp = sshkey_fingerprint(key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
verbose("Accepted %s public key %s from %s@%s",
- key_type(key), fp, cuser, lookup);
+ sshkey_type(key), fp, cuser, lookup);
}
free(fp);
}
diff --git a/auth2-kbdint.c b/auth2-kbdint.c
index bf75c605..e23d2edd 100644
--- a/auth2-kbdint.c
+++ b/auth2-kbdint.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: auth2-kbdint.c,v 1.11 2019/11/13 04:47:52 deraadt Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -27,35 +27,37 @@
#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "packet.h"
-#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "log.h"
-#include "buffer.h"
#include "misc.h"
#include "servconf.h"
+#include "ssherr.h"
/* import */
extern ServerOptions options;
static int
-userauth_kbdint(Authctxt *authctxt)
+userauth_kbdint(struct ssh *ssh)
{
- int authenticated = 0;
+ int r, authenticated = 0;
char *lang, *devs;
- lang = packet_get_string(NULL);
- devs = packet_get_string(NULL);
- packet_check_eom();
+ 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));
debug("keyboard-interactive devs %s", devs);
if (options.challenge_response_authentication)
- authenticated = auth2_challenge(authctxt, devs);
+ authenticated = auth2_challenge(ssh, devs);
free(devs);
free(lang);
diff --git a/auth2-none.c b/auth2-none.c
index 5d59bda3..f457c378 100644
--- a/auth2-none.c
+++ b/auth2-none.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: auth2-none.c,v 1.22 2018/07/09 21:35:50 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -37,16 +37,16 @@
#include "atomicio.h"
#include "xmalloc.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "packet.h"
#include "log.h"
-#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "ssh2.h"
+#include "ssherr.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
@@ -59,15 +59,18 @@ extern ServerOptions options;
static int none_enabled = 1;
static int
-userauth_none(Authctxt *authctxt)
+userauth_none(struct ssh *ssh)
{
+ int r;
+
none_enabled = 0;
- packet_check_eom();
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
/* no password authentication in Android. */
#if !defined(ANDROID)
if (options.permit_empty_passwd && options.password_authentication)
- return (PRIVSEP(auth_password(authctxt, "")));
+ return (PRIVSEP(auth_password(ssh, "")));
#endif
return (0);
}
diff --git a/auth2-passwd.c b/auth2-passwd.c
index 09cf077c..2d0b2af2 100644
--- a/auth2-passwd.c
+++ b/auth2-passwd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: auth2-passwd.c,v 1.18 2020/02/26 13:40:09 jsg Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -27,16 +27,17 @@
#include <sys/types.h>
+#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
+#include <stdio.h>
-#include "xmalloc.h"
#include "packet.h"
+#include "ssherr.h"
#include "log.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
-#include "buffer.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
@@ -48,32 +49,27 @@
extern ServerOptions options;
static int
-userauth_passwd(Authctxt *authctxt)
+userauth_passwd(struct ssh *ssh)
{
- char *password, *newpass;
- int authenticated = 0;
- int change;
- u_int len, newlen;
+ char *password;
+ int authenticated = 0, r;
+ u_char change;
+ size_t len;
- change = packet_get_char();
- password = packet_get_string(&len);
- if (change) {
- /* discard new password from packet */
- newpass = packet_get_string(&newlen);
- explicit_bzero(newpass, newlen);
- free(newpass);
- }
- packet_check_eom();
+ if ((r = sshpkt_get_u8(ssh, &change)) != 0 ||
+ (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));
if (change)
logit("password change not supported");
#if !defined(ANDROID)
/* no password authentication in Android */
- else if (PRIVSEP(auth_password(authctxt, password)) == 1)
+ else if (PRIVSEP(auth_password(ssh, password)) == 1)
authenticated = 1;
#endif
- explicit_bzero(password, len);
- free(password);
+ freezero(password, len);
return authenticated;
}
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index d943efa1..815ea0f2 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.47 2015/02/17 00:14:05 djm Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.99 2020/02/06 22:30:54 naddy Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -27,8 +27,8 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/wait.h>
+#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_PATHS_H
@@ -47,12 +47,12 @@
#include "ssh.h"
#include "ssh2.h"
#include "packet.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "pathnames.h"
@@ -65,124 +65,196 @@
#include "monitor_wrap.h"
#include "authfile.h"
#include "match.h"
+#include "ssherr.h"
+#include "channels.h" /* XXX for session.h */
+#include "session.h" /* XXX for child_set_env(); refactor? */
+#include "sk-api.h"
/* import */
extern ServerOptions options;
extern u_char *session_id2;
extern u_int session_id2_len;
+static char *
+format_key(const struct sshkey *key)
+{
+ char *ret, *fp = sshkey_fingerprint(key,
+ options.fingerprint_hash, SSH_FP_DEFAULT);
+
+ xasprintf(&ret, "%s %s", sshkey_type(key), fp);
+ free(fp);
+ return ret;
+}
+
static int
-userauth_pubkey(Authctxt *authctxt)
+userauth_pubkey(struct ssh *ssh)
{
- Buffer b;
- Key *key = NULL;
- char *pkalg, *userstyle;
- u_char *pkblob, *sig;
- u_int alen, blen, slen;
- int have_sig, pktype;
- int authenticated = 0;
-
- if (!authctxt->valid) {
- debug2("userauth_pubkey: disabled because of invalid user");
- return 0;
- }
- have_sig = packet_get_char();
- if (datafellows & SSH_BUG_PKAUTH) {
- debug2("userauth_pubkey: SSH_BUG_PKAUTH");
- /* no explicit pkalg given */
- pkblob = packet_get_string(&blen);
- buffer_init(&b);
- buffer_append(&b, pkblob, blen);
- /* so we have to extract the pkalg from the pkblob */
- pkalg = buffer_get_string(&b, &alen);
- buffer_free(&b);
- } else {
- pkalg = packet_get_string(&alen);
- pkblob = packet_get_string(&blen);
+ Authctxt *authctxt = ssh->authctxt;
+ struct passwd *pw = authctxt->pw;
+ struct sshbuf *b = NULL;
+ struct sshkey *key = NULL;
+ char *pkalg = NULL, *userstyle = NULL, *key_s = NULL, *ca_s = NULL;
+ u_char *pkblob = NULL, *sig = NULL, have_sig;
+ size_t blen, slen;
+ int r, pktype;
+ int req_presence = 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));
+
+ if (log_level_get() >= SYSLOG_LEVEL_DEBUG2) {
+ char *keystring;
+ struct sshbuf *pkbuf;
+
+ if ((pkbuf = sshbuf_from(pkblob, blen)) == NULL)
+ fatal("%s: sshbuf_from failed", __func__);
+ if ((keystring = sshbuf_dtob64_string(pkbuf, 0)) == NULL)
+ fatal("%s: sshbuf_dtob64 failed", __func__);
+ debug2("%s: %s user %s %s public key %s %s", __func__,
+ authctxt->valid ? "valid" : "invalid", authctxt->user,
+ have_sig ? "attempting" : "querying", pkalg, keystring);
+ sshbuf_free(pkbuf);
+ free(keystring);
}
- pktype = key_type_from_name(pkalg);
+
+ pktype = sshkey_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
- logit("userauth_pubkey: unsupported public key algorithm: %s",
- pkalg);
+ verbose("%s: unsupported public key algorithm: %s",
+ __func__, pkalg);
+ goto done;
+ }
+ if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
+ error("%s: could not parse key: %s", __func__, ssh_err(r));
goto done;
}
- key = key_from_blob(pkblob, blen);
if (key == NULL) {
- error("userauth_pubkey: cannot decode key: %s", pkalg);
+ error("%s: cannot decode key: %s", __func__, pkalg);
goto done;
}
if (key->type != pktype) {
- error("userauth_pubkey: type mismatch for decoded key "
- "(received %d, expected %d)", key->type, pktype);
+ error("%s: type mismatch for decoded key "
+ "(received %d, expected %d)", __func__, key->type, pktype);
goto done;
}
- if (key_type_plain(key->type) == KEY_RSA &&
- (datafellows & SSH_BUG_RSASIGMD5) != 0) {
+ if (sshkey_type_plain(key->type) == KEY_RSA &&
+ (ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
logit("Refusing RSA key because client uses unsafe "
"signature scheme");
goto done;
}
- if (auth2_userkey_already_used(authctxt, key)) {
- logit("refusing previously-used %s key", key_type(key));
+ if (auth2_key_already_used(authctxt, key)) {
+ logit("refusing previously-used %s key", sshkey_type(key));
goto done;
}
- if (match_pattern_list(sshkey_ssh_name(key), options.pubkey_key_types,
- strlen(options.pubkey_key_types), 0) != 1) {
+ if (match_pattern_list(pkalg, options.pubkey_key_types, 0) != 1) {
logit("%s: key type %s not in PubkeyAcceptedKeyTypes",
__func__, sshkey_ssh_name(key));
goto done;
}
+ if ((r = sshkey_check_cert_sigtype(key,
+ options.ca_sign_algorithms)) != 0) {
+ logit("%s: certificate signature algorithm %s: %s", __func__,
+ (key->cert == NULL || key->cert->signature_type == NULL) ?
+ "(null)" : key->cert->signature_type, ssh_err(r));
+ goto done;
+ }
+ key_s = format_key(key);
+ if (sshkey_is_cert(key))
+ ca_s = format_key(key->cert->signature_key);
if (have_sig) {
- sig = packet_get_string(&slen);
- packet_check_eom();
- buffer_init(&b);
- if (datafellows & SSH_OLD_SESSIONID) {
- buffer_append(&b, session_id2, session_id2_len);
+ debug3("%s: have %s signature for %s%s%s",
+ __func__, pkalg, key_s,
+ ca_s == NULL ? "" : " CA ",
+ ca_s == NULL ? "" : ca_s);
+ if ((r = sshpkt_get_string(ssh, &sig, &slen)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if (ssh->compat & SSH_OLD_SESSIONID) {
+ if ((r = sshbuf_put(b, session_id2,
+ session_id2_len)) != 0)
+ fatal("%s: sshbuf_put session id: %s",
+ __func__, ssh_err(r));
} else {
- buffer_put_string(&b, session_id2, session_id2_len);
+ if ((r = sshbuf_put_string(b, session_id2,
+ session_id2_len)) != 0)
+ fatal("%s: sshbuf_put_string session id: %s",
+ __func__, ssh_err(r));
+ }
+ if (!authctxt->valid || authctxt->user == NULL) {
+ debug2("%s: disabled because of invalid user",
+ __func__);
+ goto done;
}
/* reconstruct packet */
- buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
xasprintf(&userstyle, "%s%s%s", authctxt->user,
authctxt->style ? ":" : "",
authctxt->style ? authctxt->style : "");
- buffer_put_cstring(&b, userstyle);
- free(userstyle);
- buffer_put_cstring(&b,
- datafellows & SSH_BUG_PKSERVICE ?
- "ssh-userauth" :
- authctxt->service);
- if (datafellows & SSH_BUG_PKAUTH) {
- buffer_put_char(&b, have_sig);
- } else {
- buffer_put_cstring(&b, "publickey");
- buffer_put_char(&b, have_sig);
- buffer_put_cstring(&b, pkalg);
- }
- buffer_put_string(&b, pkblob, blen);
+ if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
+ (r = sshbuf_put_cstring(b, userstyle)) != 0 ||
+ (r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
+ (r = sshbuf_put_cstring(b, "publickey")) != 0 ||
+ (r = sshbuf_put_u8(b, have_sig)) != 0 ||
+ (r = sshbuf_put_cstring(b, pkalg)) != 0 ||
+ (r = sshbuf_put_string(b, pkblob, blen)) != 0)
+ fatal("%s: build packet failed: %s",
+ __func__, ssh_err(r));
#ifdef DEBUG_PK
- buffer_dump(&b);
+ sshbuf_dump(b, stderr);
#endif
- pubkey_auth_info(authctxt, key, NULL);
-
/* test for correct signature */
authenticated = 0;
- if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
- buffer_len(&b))) == 1) {
+ if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) &&
+ PRIVSEP(sshkey_verify(key, sig, slen,
+ sshbuf_ptr(b), sshbuf_len(b),
+ (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL,
+ ssh->compat, &sig_details)) == 0) {
authenticated = 1;
- /* Record the successful key to prevent reuse */
- auth2_record_userkey(authctxt, key);
- key = NULL; /* Don't free below */
}
- buffer_free(&b);
- free(sig);
+ 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);
+ req_presence = (options.pubkey_auth_options &
+ PUBKEYAUTH_TOUCH_REQUIRED) ||
+ !authopts->no_require_user_presence;
+ if (req_presence && (sig_details->sk_flags &
+ SSH_SK_USER_PRESENCE_REQD) == 0) {
+ error("public key %s signature for %s%s from "
+ "%.128s port %d rejected: user presence "
+ "(authenticator touch) requirement "
+ "not met ", key_s,
+ authctxt->valid ? "" : "invalid user ",
+ authctxt->user, ssh_remote_ipaddr(ssh),
+ ssh_remote_port(ssh));
+ authenticated = 0;
+ goto done;
+ }
+ }
+ auth2_record_key(authctxt, authenticated, key);
} else {
- debug("test whether pkalg/pkblob are acceptable");
- packet_check_eom();
+ debug("%s: test pkalg %s pkblob %s%s%s",
+ __func__, pkalg, key_s,
+ ca_s == NULL ? "" : " CA ",
+ ca_s == NULL ? "" : ca_s);
+
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+ if (!authctxt->valid || authctxt->user == NULL) {
+ debug2("%s: disabled because of invalid user",
+ __func__);
+ goto done;
+ }
/* XXX fake reply and always send PK_OK ? */
/*
* XXX this allows testing whether a user is allowed
@@ -191,63 +263,37 @@ userauth_pubkey(Authctxt *authctxt)
* if a user is not allowed to login. is this an
* issue? -markus
*/
- if (PRIVSEP(user_key_allowed(authctxt->pw, key))) {
- packet_start(SSH2_MSG_USERAUTH_PK_OK);
- packet_put_string(pkalg, alen);
- packet_put_string(pkblob, blen);
- packet_send();
- packet_write_wait();
+ if (PRIVSEP(user_key_allowed(ssh, pw, key, 0, NULL))) {
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_PK_OK))
+ != 0 ||
+ (r = sshpkt_put_cstring(ssh, pkalg)) != 0 ||
+ (r = sshpkt_put_string(ssh, pkblob, blen)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
authctxt->postponed = 1;
}
}
- if (authenticated != 1)
- auth_clear_options();
done:
- debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
- if (key != NULL)
- key_free(key);
+ if (authenticated == 1 && auth_activate_options(ssh, authopts) != 0) {
+ debug("%s: key options inconsistent with existing", __func__);
+ authenticated = 0;
+ }
+ debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
+
+ sshbuf_free(b);
+ sshauthopt_free(authopts);
+ sshkey_free(key);
+ free(userstyle);
free(pkalg);
free(pkblob);
+ free(key_s);
+ free(ca_s);
+ free(sig);
+ sshkey_sig_details_free(sig_details);
return authenticated;
}
-void
-pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
-{
- char *fp, *extra;
- va_list ap;
- int i;
-
- extra = NULL;
- if (fmt != NULL) {
- va_start(ap, fmt);
- i = vasprintf(&extra, fmt, ap);
- va_end(ap);
- if (i < 0 || extra == NULL)
- fatal("%s: vasprintf failed", __func__);
- }
-
- if (key_is_cert(key)) {
- fp = sshkey_fingerprint(key->cert->signature_key,
- options.fingerprint_hash, SSH_FP_DEFAULT);
- auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
- key_type(key), key->cert->key_id,
- (unsigned long long)key->cert->serial,
- key_type(key->cert->signature_key),
- fp == NULL ? "(null)" : fp,
- extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
- free(fp);
- } else {
- fp = sshkey_fingerprint(key, options.fingerprint_hash,
- SSH_FP_DEFAULT);
- auth_info(authctxt, "%s %s%s%s", key_type(key),
- fp == NULL ? "(null)" : fp,
- extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
- free(fp);
- }
- free(extra);
-}
-
static int
match_principals_option(const char *principal_list, struct sshkey_cert *cert)
{
@@ -268,21 +314,79 @@ match_principals_option(const char *principal_list, struct sshkey_cert *cert)
return 0;
}
+/*
+ * Process a single authorized_principals format line. Returns 0 and sets
+ * authoptsp is principal is authorised, -1 otherwise. "loc" is used as a
+ * log preamble for file/line information.
+ */
static int
-match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert)
+check_principals_line(struct ssh *ssh, char *cp, const struct sshkey_cert *cert,
+ const char *loc, struct sshauthopt **authoptsp)
{
- FILE *f;
- char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
- u_long linenum = 0;
- u_int i;
+ u_int i, found = 0;
+ char *ep, *line_opts;
+ const char *reason = NULL;
+ struct sshauthopt *opts = NULL;
- temporarily_use_uid(pw);
- debug("trying authorized principals file %s", file);
- if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) {
- restore_uid();
- return 0;
+ if (authoptsp != NULL)
+ *authoptsp = NULL;
+
+ /* Trim trailing whitespace. */
+ ep = cp + strlen(cp) - 1;
+ while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
+ *ep-- = '\0';
+
+ /*
+ * If the line has internal whitespace then assume it has
+ * key options.
+ */
+ line_opts = NULL;
+ if ((ep = strrchr(cp, ' ')) != NULL ||
+ (ep = strrchr(cp, '\t')) != NULL) {
+ for (; *ep == ' ' || *ep == '\t'; ep++)
+ ;
+ line_opts = cp;
+ cp = ep;
+ }
+ if ((opts = sshauthopt_parse(line_opts, &reason)) == NULL) {
+ debug("%s: bad principals options: %s", loc, reason);
+ auth_debug_add("%s: bad principals options: %s", loc, reason);
+ return -1;
+ }
+ /* Check principals in cert against those on line */
+ for (i = 0; i < cert->nprincipals; i++) {
+ if (strcmp(cp, cert->principals[i]) != 0)
+ continue;
+ debug3("%s: matched principal \"%.100s\"",
+ loc, cert->principals[i]);
+ found = 1;
}
- while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
+ if (found && authoptsp != NULL) {
+ *authoptsp = opts;
+ opts = NULL;
+ }
+ sshauthopt_free(opts);
+ return found ? 0 : -1;
+}
+
+static int
+process_principals(struct ssh *ssh, FILE *f, const char *file,
+ const struct sshkey_cert *cert, struct sshauthopt **authoptsp)
+{
+ char loc[256], *line = NULL, *cp, *ep;
+ size_t linesize = 0;
+ u_long linenum = 0;
+ u_int found_principal = 0;
+
+ if (authoptsp != NULL)
+ *authoptsp = NULL;
+
+ while (getline(&line, &linesize, f) != -1) {
+ linenum++;
+ /* Always consume entire input */
+ if (found_principal)
+ continue;
+
/* Skip leading whitespace. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
@@ -291,39 +395,313 @@ match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert)
*ep = '\0';
if (!*cp || *cp == '\n')
continue;
- /* Trim trailing whitespace. */
- ep = cp + strlen(cp) - 1;
- while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
- *ep-- = '\0';
- /*
- * If the line has internal whitespace then assume it has
- * key options.
- */
- line_opts = NULL;
- if ((ep = strrchr(cp, ' ')) != NULL ||
- (ep = strrchr(cp, '\t')) != NULL) {
- for (; *ep == ' ' || *ep == '\t'; ep++)
- ;
- line_opts = cp;
- cp = ep;
- }
- for (i = 0; i < cert->nprincipals; i++) {
- if (strcmp(cp, cert->principals[i]) == 0) {
- debug3("matched principal \"%.100s\" "
- "from file \"%s\" on line %lu",
- cert->principals[i], file, linenum);
- if (auth_parse_options(pw, line_opts,
- file, linenum) != 1)
- continue;
- fclose(f);
- restore_uid();
- return 1;
- }
- }
+
+ snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum);
+ if (check_principals_line(ssh, cp, cert, loc, authoptsp) == 0)
+ found_principal = 1;
}
+ free(line);
+ return found_principal;
+}
+
+/* XXX remove pw args here and elsewhere once ssh->authctxt is guaranteed */
+
+static int
+match_principals_file(struct ssh *ssh, struct passwd *pw, char *file,
+ struct sshkey_cert *cert, struct sshauthopt **authoptsp)
+{
+ FILE *f;
+ int success;
+
+ if (authoptsp != NULL)
+ *authoptsp = NULL;
+
+ temporarily_use_uid(pw);
+ debug("trying authorized principals file %s", file);
+ if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) {
+ restore_uid();
+ return 0;
+ }
+ success = process_principals(ssh, f, file, cert, authoptsp);
fclose(f);
restore_uid();
- return 0;
+ return success;
+}
+
+/*
+ * Checks whether principal is allowed in output of command.
+ * returns 1 if the principal is allowed or 0 otherwise.
+ */
+static int
+match_principals_command(struct ssh *ssh, struct passwd *user_pw,
+ const struct sshkey *key, struct sshauthopt **authoptsp)
+{
+ struct passwd *runas_pw = NULL;
+ const struct sshkey_cert *cert = key->cert;
+ FILE *f = NULL;
+ int r, ok, found_principal = 0;
+ int i, ac = 0, uid_swapped = 0;
+ pid_t pid;
+ char *tmp, *username = NULL, *command = NULL, **av = NULL;
+ char *ca_fp = NULL, *key_fp = NULL, *catext = NULL, *keytext = NULL;
+ char serial_s[32], uidstr[32];
+ void (*osigchld)(int);
+
+ if (authoptsp != NULL)
+ *authoptsp = NULL;
+ if (options.authorized_principals_command == NULL)
+ return 0;
+ if (options.authorized_principals_command_user == NULL) {
+ error("No user for AuthorizedPrincipalsCommand specified, "
+ "skipping");
+ return 0;
+ }
+
+ /*
+ * NB. all returns later this function should go via "out" to
+ * ensure the original SIGCHLD handler is restored properly.
+ */
+ osigchld = ssh_signal(SIGCHLD, SIG_DFL);
+
+ /* Prepare and verify the user for the command */
+ username = percent_expand(options.authorized_principals_command_user,
+ "u", user_pw->pw_name, (char *)NULL);
+ runas_pw = getpwnam(username);
+ if (runas_pw == NULL) {
+ error("AuthorizedPrincipalsCommandUser \"%s\" not found: %s",
+ username, strerror(errno));
+ goto out;
+ }
+
+ /* Turn the command into an argument vector */
+ if (argv_split(options.authorized_principals_command, &ac, &av) != 0) {
+ error("AuthorizedPrincipalsCommand \"%s\" contains "
+ "invalid quotes", options.authorized_principals_command);
+ goto out;
+ }
+ if (ac == 0) {
+ error("AuthorizedPrincipalsCommand \"%s\" yielded no arguments",
+ options.authorized_principals_command);
+ goto out;
+ }
+ if ((ca_fp = sshkey_fingerprint(cert->signature_key,
+ options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
+ error("%s: sshkey_fingerprint failed", __func__);
+ goto out;
+ }
+ if ((key_fp = sshkey_fingerprint(key,
+ options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
+ error("%s: sshkey_fingerprint failed", __func__);
+ goto out;
+ }
+ if ((r = sshkey_to_base64(cert->signature_key, &catext)) != 0) {
+ error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if ((r = sshkey_to_base64(key, &keytext)) != 0) {
+ error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ snprintf(serial_s, sizeof(serial_s), "%llu",
+ (unsigned long long)cert->serial);
+ snprintf(uidstr, sizeof(uidstr), "%llu",
+ (unsigned long long)user_pw->pw_uid);
+ for (i = 1; i < ac; i++) {
+ tmp = percent_expand(av[i],
+ "U", uidstr,
+ "u", user_pw->pw_name,
+ "h", user_pw->pw_dir,
+ "t", sshkey_ssh_name(key),
+ "T", sshkey_ssh_name(cert->signature_key),
+ "f", key_fp,
+ "F", ca_fp,
+ "k", keytext,
+ "K", catext,
+ "i", cert->key_id,
+ "s", serial_s,
+ (char *)NULL);
+ if (tmp == NULL)
+ fatal("%s: percent_expand failed", __func__);
+ free(av[i]);
+ av[i] = tmp;
+ }
+ /* Prepare a printable command for logs, etc. */
+ command = argv_assemble(ac, av);
+
+ if ((pid = subprocess("AuthorizedPrincipalsCommand", runas_pw, command,
+ ac, av, &f,
+ SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
+ goto out;
+
+ uid_swapped = 1;
+ temporarily_use_uid(runas_pw);
+
+ ok = process_principals(ssh, f, "(command)", cert, authoptsp);
+
+ fclose(f);
+ f = NULL;
+
+ if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command, 0) != 0)
+ goto out;
+
+ /* Read completed successfully */
+ found_principal = ok;
+ out:
+ if (f != NULL)
+ fclose(f);
+ ssh_signal(SIGCHLD, osigchld);
+ for (i = 0; i < ac; i++)
+ free(av[i]);
+ free(av);
+ if (uid_swapped)
+ restore_uid();
+ free(command);
+ free(username);
+ free(ca_fp);
+ free(key_fp);
+ free(catext);
+ free(keytext);
+ return found_principal;
+}
+
+/*
+ * Check a single line of an authorized_keys-format file. Returns 0 if key
+ * matches, -1 otherwise. Will return key/cert options via *authoptsp
+ * on success. "loc" is used as file/line location in log messages.
+ */
+static int
+check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
+ char *cp, const char *loc, struct sshauthopt **authoptsp)
+{
+ int want_keytype = sshkey_is_cert(key) ? KEY_UNSPEC : key->type;
+ struct sshkey *found = NULL;
+ struct sshauthopt *keyopts = NULL, *certopts = NULL, *finalopts = NULL;
+ char *key_options = NULL, *fp = NULL;
+ const char *reason = NULL;
+ int ret = -1;
+
+ if (authoptsp != NULL)
+ *authoptsp = NULL;
+
+ if ((found = sshkey_new(want_keytype)) == NULL) {
+ debug3("%s: keytype %d failed", __func__, want_keytype);
+ goto out;
+ }
+
+ /* XXX djm: peek at key type in line and skip if unwanted */
+
+ if (sshkey_read(found, &cp) != 0) {
+ /* no key? check for options */
+ debug2("%s: check options: '%s'", loc, cp);
+ key_options = cp;
+ if (sshkey_advance_past_options(&cp) != 0) {
+ reason = "invalid key option string";
+ goto fail_reason;
+ }
+ skip_space(&cp);
+ if (sshkey_read(found, &cp) != 0) {
+ /* still no key? advance to next line*/
+ debug2("%s: advance: '%s'", loc, cp);
+ goto out;
+ }
+ }
+ /* Parse key options now; we need to know if this is a CA key */
+ if ((keyopts = sshauthopt_parse(key_options, &reason)) == NULL) {
+ debug("%s: bad key options: %s", loc, reason);
+ auth_debug_add("%s: bad key options: %s", loc, reason);
+ goto out;
+ }
+ /* Ignore keys that don't match or incorrectly marked as CAs */
+ if (sshkey_is_cert(key)) {
+ /* Certificate; check signature key against CA */
+ if (!sshkey_equal(found, key->cert->signature_key) ||
+ !keyopts->cert_authority)
+ goto out;
+ } else {
+ /* Plain key: check it against key found in file */
+ if (!sshkey_equal(found, key) || keyopts->cert_authority)
+ goto out;
+ }
+
+ /* We have a candidate key, perform authorisation checks */
+ if ((fp = sshkey_fingerprint(found,
+ options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
+ fatal("%s: fingerprint failed", __func__);
+
+ debug("%s: matching %s found: %s %s", loc,
+ sshkey_is_cert(key) ? "CA" : "key", sshkey_type(found), fp);
+
+ if (auth_authorise_keyopts(ssh, pw, keyopts,
+ sshkey_is_cert(key), loc) != 0) {
+ reason = "Refused by key options";
+ goto fail_reason;
+ }
+ /* That's all we need for plain keys. */
+ if (!sshkey_is_cert(key)) {
+ verbose("Accepted key %s %s found at %s",
+ sshkey_type(found), fp, loc);
+ finalopts = keyopts;
+ keyopts = NULL;
+ goto success;
+ }
+
+ /*
+ * Additional authorisation for certificates.
+ */
+
+ /* Parse and check options present in certificate */
+ if ((certopts = sshauthopt_from_cert(key)) == NULL) {
+ reason = "Invalid certificate options";
+ goto fail_reason;
+ }
+ if (auth_authorise_keyopts(ssh, pw, certopts, 0, loc) != 0) {
+ reason = "Refused by certificate options";
+ goto fail_reason;
+ }
+ if ((finalopts = sshauthopt_merge(keyopts, certopts, &reason)) == NULL)
+ goto fail_reason;
+
+ /*
+ * If the user has specified a list of principals as
+ * a key option, then prefer that list to matching
+ * their username in the certificate principals list.
+ */
+ if (keyopts->cert_principals != NULL &&
+ !match_principals_option(keyopts->cert_principals, key->cert)) {
+ reason = "Certificate does not contain an authorized principal";
+ goto fail_reason;
+ }
+ if (sshkey_cert_check_authority(key, 0, 0,
+ keyopts->cert_principals == NULL ? pw->pw_name : NULL, &reason) != 0)
+ goto fail_reason;
+
+ verbose("Accepted certificate ID \"%s\" (serial %llu) "
+ "signed by CA %s %s found at %s",
+ key->cert->key_id,
+ (unsigned long long)key->cert->serial,
+ sshkey_type(found), fp, loc);
+
+ success:
+ if (finalopts == NULL)
+ fatal("%s: internal error: missing options", __func__);
+ if (authoptsp != NULL) {
+ *authoptsp = finalopts;
+ finalopts = NULL;
+ }
+ /* success */
+ ret = 0;
+ goto out;
+
+ fail_reason:
+ error("%s", reason);
+ auth_debug_add("%s", reason);
+ out:
+ free(fp);
+ sshauthopt_free(keyopts);
+ sshauthopt_free(certopts);
+ sshauthopt_free(finalopts);
+ sshkey_free(found);
+ return ret;
}
/*
@@ -331,137 +709,62 @@ match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert)
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
-check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
+check_authkeys_file(struct ssh *ssh, struct passwd *pw, FILE *f,
+ char *file, struct sshkey *key, struct sshauthopt **authoptsp)
{
- char line[SSH_MAX_PUBKEY_BYTES];
- const char *reason;
+ char *cp, *line = NULL, loc[256];
+ size_t linesize = 0;
int found_key = 0;
u_long linenum = 0;
- Key *found;
- char *fp;
- found_key = 0;
+ if (authoptsp != NULL)
+ *authoptsp = NULL;
- found = NULL;
- while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
- char *cp, *key_options = NULL;
- if (found != NULL)
- key_free(found);
- found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
- auth_clear_options();
+ while (getline(&line, &linesize, f) != -1) {
+ linenum++;
+ /* Always consume entire file */
+ if (found_key)
+ continue;
/* Skip leading whitespace, empty and comment lines. */
- for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
- ;
+ cp = line;
+ skip_space(&cp);
if (!*cp || *cp == '\n' || *cp == '#')
continue;
-
- if (key_read(found, &cp) != 1) {
- /* no key? check if there are options for this key */
- int quoted = 0;
- debug2("user_key_allowed: check options: '%s'", cp);
- key_options = cp;
- for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
- if (*cp == '\\' && cp[1] == '"')
- cp++; /* Skip both */
- else if (*cp == '"')
- quoted = !quoted;
- }
- /* Skip remaining whitespace. */
- for (; *cp == ' ' || *cp == '\t'; cp++)
- ;
- if (key_read(found, &cp) != 1) {
- debug2("user_key_allowed: advance: '%s'", cp);
- /* still no key? advance to next line*/
- continue;
- }
- }
- if (key_is_cert(key)) {
- if (!key_equal(found, key->cert->signature_key))
- continue;
- if (auth_parse_options(pw, key_options, file,
- linenum) != 1)
- continue;
- if (!key_is_cert_authority)
- continue;
- if ((fp = sshkey_fingerprint(found,
- options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
- continue;
- debug("matching CA found: file %s, line %lu, %s %s",
- file, linenum, key_type(found), fp);
- /*
- * If the user has specified a list of principals as
- * a key option, then prefer that list to matching
- * their username in the certificate principals list.
- */
- if (authorized_principals != NULL &&
- !match_principals_option(authorized_principals,
- key->cert)) {
- reason = "Certificate does not contain an "
- "authorized principal";
- fail_reason:
- free(fp);
- error("%s", reason);
- auth_debug_add("%s", reason);
- continue;
- }
- if (key_cert_check_authority(key, 0, 0,
- authorized_principals == NULL ? pw->pw_name : NULL,
- &reason) != 0)
- goto fail_reason;
- if (auth_cert_options(key, pw) != 0) {
- free(fp);
- continue;
- }
- verbose("Accepted certificate ID \"%s\" "
- "signed by %s CA %s via %s", key->cert->key_id,
- key_type(found), fp, file);
- free(fp);
- found_key = 1;
- break;
- } else if (key_equal(found, key)) {
- if (auth_parse_options(pw, key_options, file,
- linenum) != 1)
- continue;
- if (key_is_cert_authority)
- continue;
- if ((fp = sshkey_fingerprint(found,
- options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
- continue;
- debug("matching key found: file %s, line %lu %s %s",
- file, linenum, key_type(found), fp);
- free(fp);
+ snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum);
+ if (check_authkey_line(ssh, pw, key, cp, loc, authoptsp) == 0)
found_key = 1;
- break;
- }
}
- if (found != NULL)
- key_free(found);
- if (!found_key)
- debug2("key not found");
+ free(line);
return found_key;
}
/* Authenticate a certificate key against TrustedUserCAKeys */
static int
-user_cert_trusted_ca(struct passwd *pw, Key *key)
+user_cert_trusted_ca(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
+ struct sshauthopt **authoptsp)
{
char *ca_fp, *principals_file = NULL;
const char *reason;
- int ret = 0;
+ struct sshauthopt *principals_opts = NULL, *cert_opts = NULL;
+ struct sshauthopt *final_opts = NULL;
+ int r, ret = 0, found_principal = 0, use_authorized_principals;
+
+ if (authoptsp != NULL)
+ *authoptsp = NULL;
- if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
+ if (!sshkey_is_cert(key) || options.trusted_user_ca_keys == NULL)
return 0;
if ((ca_fp = sshkey_fingerprint(key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
return 0;
- if (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", __func__,
- key_type(key->cert->signature_key), ca_fp,
- options.trusted_user_ca_keys);
+ if ((r = sshkey_in_file(key->cert->signature_key,
+ options.trusted_user_ca_keys, 1, 0)) != 0) {
+ debug2("%s: CA %s %s is not listed in %s: %s", __func__,
+ sshkey_type(key->cert->signature_key), ca_fp,
+ options.trusted_user_ca_keys, ssh_err(r));
goto out;
}
/*
@@ -470,27 +773,69 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
* against the username.
*/
if ((principals_file = authorized_principals_file(pw)) != NULL) {
- if (!match_principals_file(principals_file, pw, key->cert)) {
- reason = "Certificate does not contain an "
- "authorized principal";
+ if (match_principals_file(ssh, pw, principals_file,
+ key->cert, &principals_opts))
+ found_principal = 1;
+ }
+ /* Try querying command if specified */
+ if (!found_principal && match_principals_command(ssh, pw, key,
+ &principals_opts))
+ found_principal = 1;
+ /* If principals file or command is specified, then require a match */
+ use_authorized_principals = principals_file != NULL ||
+ options.authorized_principals_command != NULL;
+ if (!found_principal && use_authorized_principals) {
+ reason = "Certificate does not contain an authorized principal";
+ goto fail_reason;
+ }
+ if (use_authorized_principals && principals_opts == NULL)
+ fatal("%s: internal error: missing principals_opts", __func__);
+ if (sshkey_cert_check_authority(key, 0, 1,
+ use_authorized_principals ? NULL : pw->pw_name, &reason) != 0)
+ goto fail_reason;
+
+ /* Check authority from options in key and from principals file/cmd */
+ if ((cert_opts = sshauthopt_from_cert(key)) == NULL) {
+ reason = "Invalid certificate options";
+ goto fail_reason;
+ }
+ if (auth_authorise_keyopts(ssh, pw, cert_opts, 0, "cert") != 0) {
+ reason = "Refused by certificate options";
+ goto fail_reason;
+ }
+ if (principals_opts == NULL) {
+ final_opts = cert_opts;
+ cert_opts = NULL;
+ } else {
+ if (auth_authorise_keyopts(ssh, pw, principals_opts, 0,
+ "principals") != 0) {
+ reason = "Refused by certificate principals options";
+ goto fail_reason;
+ }
+ if ((final_opts = sshauthopt_merge(principals_opts,
+ cert_opts, &reason)) == NULL) {
fail_reason:
error("%s", reason);
auth_debug_add("%s", reason);
goto out;
}
}
- if (key_cert_check_authority(key, 0, 1,
- principals_file == NULL ? pw->pw_name : NULL, &reason) != 0)
- goto fail_reason;
- if (auth_cert_options(key, pw) != 0)
- goto out;
- verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s",
- key->cert->key_id, key_type(key->cert->signature_key), ca_fp,
+ /* Success */
+ verbose("Accepted certificate ID \"%s\" (serial %llu) signed by "
+ "%s CA %s via %s", key->cert->key_id,
+ (unsigned long long)key->cert->serial,
+ sshkey_type(key->cert->signature_key), ca_fp,
options.trusted_user_ca_keys);
+ if (authoptsp != NULL) {
+ *authoptsp = final_opts;
+ final_opts = NULL;
+ }
ret = 1;
-
out:
+ sshauthopt_free(principals_opts);
+ sshauthopt_free(cert_opts);
+ sshauthopt_free(final_opts);
free(principals_file);
free(ca_fp);
return ret;
@@ -501,17 +846,22 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
-user_key_allowed2(struct passwd *pw, Key *key, char *file)
+user_key_allowed2(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
+ char *file, struct sshauthopt **authoptsp)
{
FILE *f;
int found_key = 0;
+ if (authoptsp != NULL)
+ *authoptsp = NULL;
+
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
debug("trying public key file %s", file);
if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
- found_key = check_authkeys_file(f, file, key, pw);
+ found_key = check_authkeys_file(ssh, pw, f, file,
+ key, authoptsp);
fclose(f);
}
@@ -524,146 +874,130 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
-user_key_command_allowed2(struct passwd *user_pw, Key *key)
+user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw,
+ struct sshkey *key, struct sshauthopt **authoptsp)
{
- FILE *f;
- int ok, found_key = 0;
- struct passwd *pw;
- struct stat st;
- int status, devnull, p[2], i;
+ struct passwd *runas_pw = NULL;
+ FILE *f = NULL;
+ int r, ok, found_key = 0;
+ int i, uid_swapped = 0, ac = 0;
pid_t pid;
- char *username, errmsg[512];
+ char *username = NULL, *key_fp = NULL, *keytext = NULL;
+ char uidstr[32], *tmp, *command = NULL, **av = NULL;
+ void (*osigchld)(int);
- if (options.authorized_keys_command == NULL ||
- options.authorized_keys_command[0] != '/')
+ if (authoptsp != NULL)
+ *authoptsp = NULL;
+ if (options.authorized_keys_command == NULL)
return 0;
-
if (options.authorized_keys_command_user == NULL) {
error("No user for AuthorizedKeysCommand specified, skipping");
return 0;
}
+ /*
+ * NB. all returns later this function should go via "out" to
+ * ensure the original SIGCHLD handler is restored properly.
+ */
+ osigchld = ssh_signal(SIGCHLD, SIG_DFL);
+
+ /* Prepare and verify the user for the command */
username = percent_expand(options.authorized_keys_command_user,
"u", user_pw->pw_name, (char *)NULL);
- pw = getpwnam(username);
- if (pw == NULL) {
+ runas_pw = getpwnam(username);
+ if (runas_pw == NULL) {
error("AuthorizedKeysCommandUser \"%s\" not found: %s",
username, strerror(errno));
- free(username);
- return 0;
+ goto out;
}
- free(username);
-
- temporarily_use_uid(pw);
- if (stat(options.authorized_keys_command, &st) < 0) {
- error("Could not stat AuthorizedKeysCommand \"%s\": %s",
- options.authorized_keys_command, strerror(errno));
+ /* Prepare AuthorizedKeysCommand */
+ if ((key_fp = sshkey_fingerprint(key, options.fingerprint_hash,
+ SSH_FP_DEFAULT)) == NULL) {
+ error("%s: sshkey_fingerprint failed", __func__);
goto out;
}
- if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
- errmsg, sizeof(errmsg)) != 0) {
- error("Unsafe AuthorizedKeysCommand: %s", errmsg);
+ if ((r = sshkey_to_base64(key, &keytext)) != 0) {
+ error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
goto out;
}
- if (pipe(p) != 0) {
- error("%s: pipe: %s", __func__, strerror(errno));
+ /* Turn the command into an argument vector */
+ if (argv_split(options.authorized_keys_command, &ac, &av) != 0) {
+ error("AuthorizedKeysCommand \"%s\" contains invalid quotes",
+ command);
goto out;
}
-
- debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",
- options.authorized_keys_command, user_pw->pw_name, pw->pw_name);
+ if (ac == 0) {
+ error("AuthorizedKeysCommand \"%s\" yielded no arguments",
+ command);
+ goto out;
+ }
+ snprintf(uidstr, sizeof(uidstr), "%llu",
+ (unsigned long long)user_pw->pw_uid);
+ for (i = 1; i < ac; i++) {
+ tmp = percent_expand(av[i],
+ "U", uidstr,
+ "u", user_pw->pw_name,
+ "h", user_pw->pw_dir,
+ "t", sshkey_ssh_name(key),
+ "f", key_fp,
+ "k", keytext,
+ (char *)NULL);
+ if (tmp == NULL)
+ fatal("%s: percent_expand failed", __func__);
+ free(av[i]);
+ av[i] = tmp;
+ }
+ /* Prepare a printable command for logs, etc. */
+ command = argv_assemble(ac, av);
/*
- * Don't want to call this in the child, where it can fatal() and
- * run cleanup_exit() code.
+ * If AuthorizedKeysCommand was run without arguments
+ * then fall back to the old behaviour of passing the
+ * target username as a single argument.
*/
- restore_uid();
-
- switch ((pid = fork())) {
- case -1: /* error */
- error("%s: fork: %s", __func__, strerror(errno));
- close(p[0]);
- close(p[1]);
- return 0;
- case 0: /* child */
- for (i = 0; i < NSIG; i++)
- signal(i, SIG_DFL);
-
- if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
- error("%s: open %s: %s", __func__, _PATH_DEVNULL,
- strerror(errno));
- _exit(1);
- }
- /* Keep stderr around a while longer to catch errors */
- if (dup2(devnull, STDIN_FILENO) == -1 ||
- dup2(p[1], STDOUT_FILENO) == -1) {
- error("%s: dup2: %s", __func__, strerror(errno));
- _exit(1);
- }
- closefrom(STDERR_FILENO + 1);
-
- /* Don't use permanently_set_uid() here to avoid fatal() */
- if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
- error("setresgid %u: %s", (u_int)pw->pw_gid,
- strerror(errno));
- _exit(1);
- }
- if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
- error("setresuid %u: %s", (u_int)pw->pw_uid,
- strerror(errno));
- _exit(1);
- }
- /* stdin is pointed to /dev/null at this point */
- if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
- error("%s: dup2: %s", __func__, strerror(errno));
- _exit(1);
- }
+ if (ac == 1) {
+ av = xreallocarray(av, ac + 2, sizeof(*av));
+ av[1] = xstrdup(user_pw->pw_name);
+ av[2] = NULL;
+ /* Fix up command too, since it is used in log messages */
+ free(command);
+ xasprintf(&command, "%s %s", av[0], av[1]);
+ }
- execl(options.authorized_keys_command,
- options.authorized_keys_command, user_pw->pw_name, NULL);
+ if ((pid = subprocess("AuthorizedKeysCommand", runas_pw, command,
+ ac, av, &f,
+ SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
+ goto out;
- error("AuthorizedKeysCommand %s exec failed: %s",
- options.authorized_keys_command, strerror(errno));
- _exit(127);
- default: /* parent */
- break;
- }
+ uid_swapped = 1;
+ temporarily_use_uid(runas_pw);
- temporarily_use_uid(pw);
+ ok = check_authkeys_file(ssh, user_pw, f,
+ options.authorized_keys_command, key, authoptsp);
- close(p[1]);
- if ((f = fdopen(p[0], "r")) == NULL) {
- error("%s: fdopen: %s", __func__, strerror(errno));
- close(p[0]);
- /* Don't leave zombie child */
- kill(pid, SIGTERM);
- while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
- ;
- goto out;
- }
- ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
fclose(f);
+ f = NULL;
- while (waitpid(pid, &status, 0) == -1) {
- if (errno != EINTR) {
- error("%s: waitpid: %s", __func__, strerror(errno));
- goto out;
- }
- }
- if (WIFSIGNALED(status)) {
- error("AuthorizedKeysCommand %s exited on signal %d",
- options.authorized_keys_command, WTERMSIG(status));
+ if (exited_cleanly(pid, "AuthorizedKeysCommand", command, 0) != 0)
goto out;
- } else if (WEXITSTATUS(status) != 0) {
- error("AuthorizedKeysCommand %s returned status %d",
- options.authorized_keys_command, WEXITSTATUS(status));
- goto out;
- }
+
+ /* Read completed successfully */
found_key = ok;
out:
- restore_uid();
+ if (f != NULL)
+ fclose(f);
+ ssh_signal(SIGCHLD, osigchld);
+ for (i = 0; i < ac; i++)
+ free(av[i]);
+ free(av);
+ if (uid_swapped)
+ restore_uid();
+ free(command);
+ free(username);
+ free(key_fp);
+ free(keytext);
return found_key;
}
@@ -671,65 +1005,54 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
* Check whether key authenticates and authorises the user.
*/
int
-user_key_allowed(struct passwd *pw, Key *key)
+user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
+ int auth_attempt, struct sshauthopt **authoptsp)
{
- u_int success, i;
+ u_int success = 0, i;
char *file;
+ struct sshauthopt *opts = NULL;
+
+ if (authoptsp != NULL)
+ *authoptsp = NULL;
if (auth_key_is_revoked(key))
return 0;
- if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
+ if (sshkey_is_cert(key) &&
+ auth_key_is_revoked(key->cert->signature_key))
return 0;
- success = user_cert_trusted_ca(pw, key);
- if (success)
- return success;
-
- success = user_key_command_allowed2(pw, key);
- if (success > 0)
- return success;
-
for (i = 0; !success && i < options.num_authkeys_files; i++) {
-
if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
continue;
file = expand_authorized_keys(
options.authorized_keys_files[i], pw);
-
- success = user_key_allowed2(pw, key, file);
+ success = user_key_allowed2(ssh, pw, key, file, &opts);
free(file);
+ if (!success) {
+ sshauthopt_free(opts);
+ opts = NULL;
+ }
}
+ if (success)
+ goto out;
- return success;
-}
-
-/* Records a public key in the list of previously-successful keys */
-void
-auth2_record_userkey(Authctxt *authctxt, struct sshkey *key)
-{
- struct sshkey **tmp;
-
- if (authctxt->nprev_userkeys >= INT_MAX ||
- (tmp = reallocarray(authctxt->prev_userkeys,
- authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL)
- fatal("%s: reallocarray failed", __func__);
- authctxt->prev_userkeys = tmp;
- authctxt->prev_userkeys[authctxt->nprev_userkeys] = key;
- authctxt->nprev_userkeys++;
-}
+ if ((success = user_cert_trusted_ca(ssh, pw, key, &opts)) != 0)
+ goto out;
+ sshauthopt_free(opts);
+ opts = NULL;
-/* Checks whether a key has already been used successfully for authentication */
-int
-auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key)
-{
- u_int i;
+ if ((success = user_key_command_allowed2(ssh, pw, key, &opts)) != 0)
+ goto out;
+ sshauthopt_free(opts);
+ opts = NULL;
- for (i = 0; i < authctxt->nprev_userkeys; i++) {
- if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) {
- return 1;
- }
+ out:
+ if (success && authoptsp != NULL) {
+ *authoptsp = opts;
+ opts = NULL;
}
- return 0;
+ sshauthopt_free(opts);
+ return success;
}
Authmethod method_pubkey = {
diff --git a/auth2.c b/auth2.c
index 71779622..91aaf34a 100644
--- a/auth2.c
+++ b/auth2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2.c,v 1.135 2015/01/19 20:07:45 markus Exp $ */
+/* $OpenBSD: auth2.c,v 1.158 2020/03/06 18:16:21 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -30,37 +30,40 @@
#include <sys/uio.h>
#include <fcntl.h>
+#include <limits.h>
#include <pwd.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
+#include <time.h>
+#include "stdlib.h"
#include "atomicio.h"
#include "xmalloc.h"
#include "ssh2.h"
#include "packet.h"
#include "log.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "dispatch.h"
#include "pathnames.h"
-#include "buffer.h"
-
+#include "ssherr.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
+#include "digest.h"
/* import */
extern ServerOptions options;
extern u_char *session_id2;
extern u_int session_id2_len;
-extern Buffer loginmsg;
+extern struct sshbuf *loginmsg;
/* methods */
@@ -87,8 +90,8 @@ Authmethod *authmethods[] = {
/* protocol */
-static int input_service_request(int, u_int32_t, void *);
-static int input_userauth_request(int, u_int32_t, void *);
+static int input_service_request(int, u_int32_t, struct ssh *);
+static int input_userauth_request(int, u_int32_t, struct ssh *);
/* helper */
static Authmethod *authmethod_lookup(Authctxt *, const char *);
@@ -133,30 +136,30 @@ auth2_read_banner(void)
return (banner);
}
-void
-userauth_send_banner(const char *msg)
+static void
+userauth_send_banner(struct ssh *ssh, const char *msg)
{
- if (datafellows & SSH_BUG_BANNER)
- return;
+ int r;
- packet_start(SSH2_MSG_USERAUTH_BANNER);
- packet_put_cstring(msg);
- packet_put_cstring(""); /* language, unused */
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_BANNER)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, msg)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language, unused */
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
debug("%s: sent", __func__);
}
static void
-userauth_banner(void)
+userauth_banner(struct ssh *ssh)
{
char *banner = NULL;
- if (options.banner == NULL || (datafellows & SSH_BUG_BANNER) != 0)
+ if (options.banner == NULL)
return;
if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
goto done;
- userauth_send_banner(banner);
+ userauth_send_banner(ssh, banner);
done:
free(banner);
@@ -166,22 +169,27 @@ done:
* loop until authctxt->success == TRUE
*/
void
-do_authentication2(Authctxt *authctxt)
+do_authentication2(struct ssh *ssh)
{
- dispatch_init(&dispatch_protocol_error);
- dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
- dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
+ Authctxt *authctxt = ssh->authctxt;
+
+ ssh_dispatch_init(ssh, &dispatch_protocol_error);
+ ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request);
+ ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success);
+ ssh->authctxt = NULL;
}
/*ARGSUSED*/
static int
-input_service_request(int type, u_int32_t seq, void *ctxt)
+input_service_request(int type, u_int32_t seq, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
- u_int len;
- int acceptit = 0;
- char *service = packet_get_cstring(&len);
- packet_check_eom();
+ Authctxt *authctxt = ssh->authctxt;
+ char *service = NULL;
+ int r, acceptit = 0;
+
+ if ((r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ goto out;
if (authctxt == NULL)
fatal("input_service_request: no authctxt");
@@ -190,39 +198,82 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
if (!authctxt->success) {
acceptit = 1;
/* now we can handle user-auth requests */
- dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST,
+ &input_userauth_request);
}
}
/* XXX all other service requests are denied */
if (acceptit) {
- packet_start(SSH2_MSG_SERVICE_ACCEPT);
- packet_put_cstring(service);
- packet_send();
- packet_write_wait();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_ACCEPT)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, service)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ goto out;
} else {
debug("bad service request %s", service);
- packet_disconnect("bad service request %s", service);
+ ssh_packet_disconnect(ssh, "bad service request %s", service);
}
+ r = 0;
+ out:
free(service);
- return 0;
+ return r;
+}
+
+#define MIN_FAIL_DELAY_SECONDS 0.005
+static double
+user_specific_delay(const char *user)
+{
+ char b[512];
+ size_t len = ssh_digest_bytes(SSH_DIGEST_SHA512);
+ u_char *hash = xmalloc(len);
+ double delay;
+
+ (void)snprintf(b, sizeof b, "%llu%s",
+ (unsigned long long)options.timing_secret, user);
+ if (ssh_digest_memory(SSH_DIGEST_SHA512, b, strlen(b), hash, len) != 0)
+ fatal("%s: ssh_digest_memory", __func__);
+ /* 0-4.2 ms of delay */
+ delay = (double)PEEK_U32(hash) / 1000 / 1000 / 1000 / 1000;
+ freezero(hash, len);
+ debug3("%s: user specific delay %0.3lfms", __func__, delay/1000);
+ return MIN_FAIL_DELAY_SECONDS + delay;
+}
+
+static void
+ensure_minimum_time_since(double start, double seconds)
+{
+ struct timespec ts;
+ double elapsed = monotime_double() - start, req = seconds, remain;
+
+ /* if we've already passed the requested time, scale up */
+ while ((remain = seconds - elapsed) < 0.0)
+ seconds *= 2;
+
+ ts.tv_sec = remain;
+ ts.tv_nsec = (remain - ts.tv_sec) * 1000000000;
+ debug3("%s: elapsed %0.3lfms, delaying %0.3lfms (requested %0.3lfms)",
+ __func__, elapsed*1000, remain*1000, req*1000);
+ nanosleep(&ts, NULL);
}
/*ARGSUSED*/
static int
-input_userauth_request(int type, u_int32_t seq, void *ctxt)
+input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
+ Authctxt *authctxt = ssh->authctxt;
Authmethod *m = NULL;
- char *user, *service, *method, *style = NULL;
- int authenticated = 0;
+ char *user = NULL, *service = NULL, *method = NULL, *style = NULL;
+ int r, authenticated = 0;
+ double tstart = monotime_double();
if (authctxt == NULL)
fatal("input_userauth_request: no authctxt");
- user = packet_get_cstring(NULL);
- service = packet_get_cstring(NULL);
- method = packet_get_cstring(NULL);
+ if ((r = sshpkt_get_cstring(ssh, &user, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &method, NULL)) != 0)
+ goto out;
debug("userauth-request for user %s service %s method %s", user, service, method);
debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
@@ -231,46 +282,51 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
if (authctxt->attempt++ == 0) {
/* setup auth context */
- authctxt->pw = PRIVSEP(getpwnamallow(user));
+ authctxt->pw = PRIVSEP(getpwnamallow(ssh, user));
authctxt->user = xstrdup(user);
if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
authctxt->valid = 1;
- debug2("input_userauth_request: setting up authctxt for %s", user);
+ debug2("%s: setting up authctxt for %s",
+ __func__, user);
} else {
- logit("input_userauth_request: invalid user %s", user);
+ /* Invalid user, fake password information */
authctxt->pw = fakepw();
#ifdef SSH_AUDIT_EVENTS
- PRIVSEP(audit_event(SSH_INVALID_USER));
+ PRIVSEP(audit_event(ssh, SSH_INVALID_USER));
#endif
}
#ifdef USE_PAM
if (options.use_pam)
- PRIVSEP(start_pam(authctxt));
+ PRIVSEP(start_pam(ssh));
#endif
+ ssh_packet_set_log_preamble(ssh, "%suser %s",
+ authctxt->valid ? "authenticating " : "invalid ", user);
setproctitle("%s%s", authctxt->valid ? user : "unknown",
use_privsep ? " [net]" : "");
authctxt->service = xstrdup(service);
authctxt->style = style ? xstrdup(style) : NULL;
if (use_privsep)
mm_inform_authserv(service, style);
- userauth_banner();
+ userauth_banner(ssh);
if (auth2_setup_methods_lists(authctxt) != 0)
- packet_disconnect("no authentication methods enabled");
+ ssh_packet_disconnect(ssh,
+ "no authentication methods enabled");
} else if (strcmp(user, authctxt->user) != 0 ||
strcmp(service, authctxt->service) != 0) {
- packet_disconnect("Change of username or service not allowed: "
- "(%s,%s) -> (%s,%s)",
+ ssh_packet_disconnect(ssh, "Change of username or service "
+ "not allowed: (%s,%s) -> (%s,%s)",
authctxt->user, authctxt->service, user, service);
}
/* reset state */
- auth2_challenge_stop(authctxt);
+ auth2_challenge_stop(ssh);
#ifdef GSSAPI
/* XXX move to auth2_gssapi_stop() */
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
#endif
+ auth2_authctxt_reset_info(authctxt);
authctxt->postponed = 0;
authctxt->server_caused_failure = 0;
@@ -278,22 +334,27 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
m = authmethod_lookup(authctxt, method);
if (m != NULL && authctxt->failures < options.max_authtries) {
debug2("input_userauth_request: try method %s", method);
- authenticated = m->userauth(authctxt);
+ authenticated = m->userauth(ssh);
}
- userauth_finish(authctxt, authenticated, method, NULL);
-
+ if (!authctxt->authenticated)
+ ensure_minimum_time_since(tstart,
+ user_specific_delay(authctxt->user));
+ userauth_finish(ssh, authenticated, method, NULL);
+ r = 0;
+ out:
free(service);
free(user);
free(method);
- return 0;
+ return r;
}
void
-userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
+userauth_finish(struct ssh *ssh, int authenticated, const char *method,
const char *submethod)
{
+ Authctxt *authctxt = ssh->authctxt;
char *methods;
- int partial = 0;
+ int r, partial = 0;
if (!authctxt->valid && authenticated)
fatal("INTERNAL ERROR: authenticated invalid user %s",
@@ -303,10 +364,10 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
/* Special handling for root */
if (authenticated && authctxt->pw->pw_uid == 0 &&
- !auth_root_allowed(method)) {
+ !auth_root_allowed(ssh, method)) {
authenticated = 0;
#ifdef SSH_AUDIT_EVENTS
- PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
+ PRIVSEP(audit_event(ssh, SSH_LOGIN_ROOT_DENIED));
#endif
}
@@ -318,19 +379,30 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
}
/* Log before sending the reply */
- auth_log(authctxt, authenticated, partial, method, submethod);
+ auth_log(ssh, authenticated, partial, method, submethod);
+
+ /* Update information exposed to session */
+ if (authenticated || partial)
+ auth2_update_session_info(authctxt, method, submethod);
if (authctxt->postponed)
return;
#ifdef USE_PAM
if (options.use_pam && authenticated) {
+ int r;
+
if (!PRIVSEP(do_pam_account())) {
/* if PAM returned a message, send it to the user */
- if (buffer_len(&loginmsg) > 0) {
- buffer_append(&loginmsg, "\0", 1);
- userauth_send_banner(buffer_ptr(&loginmsg));
- packet_write_wait();
+ 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__);
+ }
}
fatal("Access denied for user %s by PAM account "
"configuration", authctxt->user);
@@ -338,41 +410,37 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
}
#endif
-#ifdef _UNICOS
- if (authenticated && cray_access_denied(authctxt->user)) {
- authenticated = 0;
- fatal("Access denied for user %s.", authctxt->user);
- }
-#endif /* _UNICOS */
-
if (authenticated == 1) {
/* turn off userauth */
- dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
- packet_start(SSH2_MSG_USERAUTH_SUCCESS);
- packet_send();
- packet_write_wait();
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST,
+ &dispatch_protocol_ignore);
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_SUCCESS)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
/* now we can break out */
authctxt->success = 1;
+ ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
} else {
-
/* Allow initial try of "none" auth without failure penalty */
if (!partial && !authctxt->server_caused_failure &&
(authctxt->attempt > 1 || strcmp(method, "none") != 0))
authctxt->failures++;
if (authctxt->failures >= options.max_authtries) {
#ifdef SSH_AUDIT_EVENTS
- PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
+ PRIVSEP(audit_event(ssh, SSH_LOGIN_EXCEED_MAXTRIES));
#endif
- auth_maxtries_exceeded(authctxt);
+ auth_maxtries_exceeded(ssh);
}
methods = authmethods_get(authctxt);
debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
partial, methods);
- packet_start(SSH2_MSG_USERAUTH_FAILURE);
- packet_put_cstring(methods);
- packet_put_char(partial);
- packet_send();
- packet_write_wait();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_FAILURE)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, methods)) != 0 ||
+ (r = sshpkt_put_u8(ssh, partial)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
free(methods);
}
}
@@ -405,11 +473,12 @@ auth2_method_allowed(Authctxt *authctxt, const char *method,
static char *
authmethods_get(Authctxt *authctxt)
{
- Buffer b;
+ struct sshbuf *b;
char *list;
- u_int i;
+ int i, r;
- buffer_init(&b);
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
for (i = 0; authmethods[i] != NULL; i++) {
if (strcmp(authmethods[i]->name, "none") == 0)
continue;
@@ -419,14 +488,13 @@ authmethods_get(Authctxt *authctxt)
if (!auth2_method_allowed(authctxt, authmethods[i]->name,
NULL))
continue;
- if (buffer_len(&b) > 0)
- buffer_append(&b, ",", 1);
- buffer_append(&b, authmethods[i]->name,
- strlen(authmethods[i]->name));
+ if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) ? "," : "",
+ authmethods[i]->name)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
- buffer_append(&b, "\0", 1);
- list = xstrdup(buffer_ptr(&b));
- buffer_free(&b);
+ if ((list = sshbuf_dup_string(b)) == NULL)
+ fatal("%s: sshbuf_dup_string failed", __func__);
+ sshbuf_free(b);
return list;
}
@@ -507,6 +575,14 @@ auth2_setup_methods_lists(Authctxt *authctxt)
{
u_int i;
+ /* First, normalise away the "any" pseudo-method */
+ if (options.num_auth_methods == 1 &&
+ strcmp(options.auth_methods[0], "any") == 0) {
+ free(options.auth_methods[0]);
+ options.auth_methods[0] = NULL;
+ options.num_auth_methods = 0;
+ }
+
if (options.num_auth_methods == 0)
return 0;
debug3("%s: checking methods", __func__);
@@ -616,4 +692,128 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method,
return 0;
}
+/* Reset method-specific information */
+void auth2_authctxt_reset_info(Authctxt *authctxt)
+{
+ sshkey_free(authctxt->auth_method_key);
+ free(authctxt->auth_method_info);
+ authctxt->auth_method_key = NULL;
+ authctxt->auth_method_info = NULL;
+}
+
+/* Record auth method-specific information for logs */
+void
+auth2_record_info(Authctxt *authctxt, const char *fmt, ...)
+{
+ va_list ap;
+ int i;
+
+ free(authctxt->auth_method_info);
+ authctxt->auth_method_info = NULL;
+
+ va_start(ap, fmt);
+ i = vasprintf(&authctxt->auth_method_info, fmt, ap);
+ va_end(ap);
+
+ if (i == -1)
+ fatal("%s: vasprintf failed", __func__);
+}
+
+/*
+ * Records a public key used in authentication. This is used for logging
+ * and to ensure that the same key is not subsequently accepted again for
+ * multiple authentication.
+ */
+void
+auth2_record_key(Authctxt *authctxt, int authenticated,
+ const struct sshkey *key)
+{
+ struct sshkey **tmp, *dup;
+ int r;
+
+ if ((r = sshkey_from_private(key, &dup)) != 0)
+ fatal("%s: copy key: %s", __func__, ssh_err(r));
+ sshkey_free(authctxt->auth_method_key);
+ authctxt->auth_method_key = dup;
+
+ if (!authenticated)
+ return;
+
+ /* If authenticated, make sure we don't accept this key again */
+ if ((r = sshkey_from_private(key, &dup)) != 0)
+ fatal("%s: copy key: %s", __func__, ssh_err(r));
+ if (authctxt->nprev_keys >= INT_MAX ||
+ (tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys,
+ authctxt->nprev_keys + 1, sizeof(*authctxt->prev_keys))) == NULL)
+ fatal("%s: reallocarray failed", __func__);
+ authctxt->prev_keys = tmp;
+ authctxt->prev_keys[authctxt->nprev_keys] = dup;
+ authctxt->nprev_keys++;
+
+}
+
+/* Checks whether a key has already been previously used for authentication */
+int
+auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key)
+{
+ u_int i;
+ char *fp;
+
+ for (i = 0; i < authctxt->nprev_keys; i++) {
+ if (sshkey_equal_public(key, authctxt->prev_keys[i])) {
+ fp = sshkey_fingerprint(authctxt->prev_keys[i],
+ options.fingerprint_hash, SSH_FP_DEFAULT);
+ debug3("%s: key already used: %s %s", __func__,
+ sshkey_type(authctxt->prev_keys[i]),
+ fp == NULL ? "UNKNOWN" : fp);
+ free(fp);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Updates authctxt->session_info with details of authentication. Should be
+ * whenever an authentication method succeeds.
+ */
+void
+auth2_update_session_info(Authctxt *authctxt, const char *method,
+ const char *submethod)
+{
+ int r;
+
+ if (authctxt->session_info == NULL) {
+ if ((authctxt->session_info = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ }
+
+ /* Append method[/submethod] */
+ if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s",
+ method, submethod == NULL ? "" : "/",
+ submethod == NULL ? "" : submethod)) != 0)
+ fatal("%s: append method: %s", __func__, ssh_err(r));
+
+ /* Append key if present */
+ if (authctxt->auth_method_key != NULL) {
+ if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
+ (r = sshkey_format_text(authctxt->auth_method_key,
+ authctxt->session_info)) != 0)
+ fatal("%s: append key: %s", __func__, ssh_err(r));
+ }
+
+ if (authctxt->auth_method_info != NULL) {
+ /* Ensure no ambiguity here */
+ if (strchr(authctxt->auth_method_info, '\n') != NULL)
+ fatal("%s: auth_method_info contains \\n", __func__);
+ if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
+ (r = sshbuf_putf(authctxt->session_info, "%s",
+ authctxt->auth_method_info)) != 0) {
+ fatal("%s: append method info: %s",
+ __func__, ssh_err(r));
+ }
+ }
+ if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0)
+ fatal("%s: append: %s", __func__, ssh_err(r));
+}
diff --git a/authfd.c b/authfd.c
index 5d9414fa..4b647a62 100644
--- a/authfd.c
+++ b/authfd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.c,v 1.94 2015/01/14 20:05:27 djm Exp $ */
+/* $OpenBSD: authfd.c,v 1.123 2020/03/06 18:24:39 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -44,14 +44,13 @@
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
-#include <stdarg.h>
#include <string.h>
+#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include "xmalloc.h"
#include "ssh.h"
-#include "rsa.h"
#include "sshbuf.h"
#include "sshkey.h"
#include "authfd.h"
@@ -83,31 +82,26 @@ decode_reply(u_char type)
return SSH_ERR_INVALID_FORMAT;
}
-/* Returns the number of the authentication fd, or -1 if there is none. */
+/*
+ * Opens an authentication socket at the provided path and stores the file
+ * descriptor in fdp. Returns 0 on success and an error on failure.
+ */
int
-ssh_get_authentication_socket(int *fdp)
+ssh_get_authentication_socket_path(const char *authsocket, int *fdp)
{
- const char *authsocket;
int sock, oerrno;
struct sockaddr_un sunaddr;
- if (fdp != NULL)
- *fdp = -1;
-
- authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
- if (!authsocket)
- return SSH_ERR_AGENT_NOT_PRESENT;
-
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
- if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
return SSH_ERR_SYSTEM_ERROR;
/* close on exec */
if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1 ||
- connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
+ connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) {
oerrno = errno;
close(sock);
errno = oerrno;
@@ -120,6 +114,25 @@ ssh_get_authentication_socket(int *fdp)
return 0;
}
+/*
+ * Opens the default authentication socket and stores the file descriptor in
+ * fdp. Returns 0 on success and an error on failure.
+ */
+int
+ssh_get_authentication_socket(int *fdp)
+{
+ const char *authsocket;
+
+ if (fdp != NULL)
+ *fdp = -1;
+
+ authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
+ if (authsocket == NULL || *authsocket == '\0')
+ return SSH_ERR_AGENT_NOT_PRESENT;
+
+ return ssh_get_authentication_socket_path(authsocket, fdp);
+}
+
/* Communicate with agent: send request and read reply */
static int
ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply)
@@ -130,11 +143,11 @@ ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply)
/* Get the length of the message, and format it in the buffer. */
len = sshbuf_len(request);
- put_u32(buf, len);
+ POKE_U32(buf, len);
/* Send the length and then the packet to the agent. */
if (atomicio(vwrite, sock, buf, 4) != 4 ||
- atomicio(vwrite, sock, (u_char *)sshbuf_ptr(request),
+ atomicio(vwrite, sock, sshbuf_mutable_ptr(request),
sshbuf_len(request)) != sshbuf_len(request))
return SSH_ERR_AGENT_COMMUNICATION;
/*
@@ -145,7 +158,7 @@ ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply)
return SSH_ERR_AGENT_COMMUNICATION;
/* Extract the length, and check it for sanity. */
- len = get_u32(buf);
+ len = PEEK_U32(buf);
if (len > MAX_AGENT_REPLY_LEN)
return SSH_ERR_INVALID_FORMAT;
@@ -199,43 +212,6 @@ ssh_lock_agent(int sock, int lock, const char *password)
return r;
}
-#ifdef WITH_SSH1
-static int
-deserialise_identity1(struct sshbuf *ids, struct sshkey **keyp, char **commentp)
-{
- struct sshkey *key;
- int r, keybits;
- u_int32_t bits;
- char *comment = NULL;
-
- if ((key = sshkey_new(KEY_RSA1)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_get_u32(ids, &bits)) != 0 ||
- (r = sshbuf_get_bignum1(ids, key->rsa->e)) != 0 ||
- (r = sshbuf_get_bignum1(ids, key->rsa->n)) != 0 ||
- (r = sshbuf_get_cstring(ids, &comment, NULL)) != 0)
- goto out;
- keybits = BN_num_bits(key->rsa->n);
- /* XXX previously we just warned here. I think we should be strict */
- if (keybits < 0 || bits != (u_int)keybits) {
- r = SSH_ERR_KEY_BITS_MISMATCH;
- goto out;
- }
- if (keyp != NULL) {
- *keyp = key;
- key = NULL;
- }
- if (commentp != NULL) {
- *commentp = comment;
- comment = NULL;
- }
- r = 0;
- out:
- sshkey_free(key);
- free(comment);
- return r;
-}
-#endif
static int
deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp)
@@ -264,35 +240,21 @@ deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp)
* Fetch list of identities held by the agent.
*/
int
-ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp)
+ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp)
{
- u_char type, code1 = 0, code2 = 0;
+ u_char type;
u_int32_t num, i;
struct sshbuf *msg;
struct ssh_identitylist *idl = NULL;
int r;
- /* Determine request and expected response types */
- switch (version) {
- case 1:
- code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
- code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER;
- break;
- case 2:
- code1 = SSH2_AGENTC_REQUEST_IDENTITIES;
- code2 = SSH2_AGENT_IDENTITIES_ANSWER;
- break;
- default:
- return SSH_ERR_INVALID_ARGUMENT;
- }
-
/*
* Send a message to the agent requesting for a list of the
* identities it can represent.
*/
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_put_u8(msg, code1)) != 0)
+ if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_REQUEST_IDENTITIES)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
@@ -304,7 +266,7 @@ ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp)
if (agent_failed(type)) {
r = SSH_ERR_AGENT_FAILURE;
goto out;
- } else if (type != code2) {
+ } else if (type != SSH2_AGENT_IDENTITIES_ANSWER) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
@@ -329,25 +291,14 @@ ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp)
goto out;
}
for (i = 0; i < num;) {
- switch (version) {
- case 1:
-#ifdef WITH_SSH1
- if ((r = deserialise_identity1(msg,
- &(idl->keys[i]), &(idl->comments[i]))) != 0)
+ if ((r = deserialise_identity2(msg, &(idl->keys[i]),
+ &(idl->comments[i]))) != 0) {
+ if (r == SSH_ERR_KEY_TYPE_UNKNOWN) {
+ /* Gracefully skip unknown key types */
+ num--;
+ continue;
+ } else
goto out;
-#endif
- break;
- case 2:
- if ((r = deserialise_identity2(msg,
- &(idl->keys[i]), &(idl->comments[i]))) != 0) {
- if (r == SSH_ERR_KEY_TYPE_UNKNOWN) {
- /* Gracefully skip unknown key types */
- num--;
- continue;
- } else
- goto out;
- }
- break;
}
i++;
}
@@ -375,88 +326,86 @@ ssh_free_identitylist(struct ssh_identitylist *idl)
if (idl->comments != NULL)
free(idl->comments[i]);
}
+ free(idl->keys);
+ free(idl->comments);
free(idl);
}
/*
+ * Check if the ssh agent has a given key.
+ * Returns 0 if found, or a negative SSH_ERR_* error code on failure.
+ */
+int
+ssh_agent_has_key(int sock, struct sshkey *key)
+{
+ int r, ret = SSH_ERR_KEY_NOT_FOUND;
+ size_t i;
+ struct ssh_identitylist *idlist = NULL;
+
+ if ((r = ssh_fetch_identitylist(sock, &idlist)) != 0) {
+ return r;
+ }
+
+ for (i = 0; i < idlist->nkeys; i++) {
+ if (sshkey_equal_public(idlist->keys[i], key)) {
+ ret = 0;
+ break;
+ }
+ }
+
+ ssh_free_identitylist(idlist);
+ return ret;
+}
+
+/*
* Sends a challenge (typically from a server via ssh(1)) to the agent,
* and waits for a response from the agent.
* Returns true (non-zero) if the agent gave the correct answer, zero
* otherwise.
*/
-#ifdef WITH_SSH1
-int
-ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
- u_char session_id[16], u_char response[16])
-{
- struct sshbuf *msg;
- int r;
- u_char type;
- if (key->type != KEY_RSA1)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((msg = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_put_u8(msg, SSH_AGENTC_RSA_CHALLENGE)) != 0 ||
- (r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 ||
- (r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 ||
- (r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0 ||
- (r = sshbuf_put_bignum1(msg, challenge)) != 0 ||
- (r = sshbuf_put(msg, session_id, 16)) != 0 ||
- (r = sshbuf_put_u32(msg, 1)) != 0) /* Response type for proto 1.1 */
- goto out;
- if ((r = ssh_request_reply(sock, msg, msg)) != 0)
- goto out;
- if ((r = sshbuf_get_u8(msg, &type)) != 0)
- goto out;
- if (agent_failed(type)) {
- r = SSH_ERR_AGENT_FAILURE;
- goto out;
- } else if (type != SSH_AGENT_RSA_RESPONSE) {
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
+/* encode signature algorithm in flag bits, so we can keep the msg format */
+static u_int
+agent_encode_alg(const struct sshkey *key, const char *alg)
+{
+ if (alg != NULL && sshkey_type_plain(key->type) == KEY_RSA) {
+ if (strcmp(alg, "rsa-sha2-256") == 0 ||
+ strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
+ return SSH_AGENT_RSA_SHA2_256;
+ if (strcmp(alg, "rsa-sha2-512") == 0 ||
+ strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
+ return SSH_AGENT_RSA_SHA2_512;
}
- if ((r = sshbuf_get(msg, response, 16)) != 0)
- goto out;
- r = 0;
- out:
- sshbuf_free(msg);
- return r;
+ return 0;
}
-#endif
/* ask agent to sign data, returns err.h code on error, 0 on success */
int
-ssh_agent_sign(int sock, struct sshkey *key,
+ssh_agent_sign(int sock, const struct sshkey *key,
u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, u_int compat)
+ const u_char *data, size_t datalen, const char *alg, u_int compat)
{
struct sshbuf *msg;
- u_char *blob = NULL, type;
- size_t blen = 0, len = 0;
+ u_char *sig = NULL, type = 0;
+ size_t len = 0;
u_int flags = 0;
int r = SSH_ERR_INTERNAL_ERROR;
- if (sigp != NULL)
- *sigp = NULL;
- if (lenp != NULL)
- *lenp = 0;
+ *sigp = NULL;
+ *lenp = 0;
if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
return SSH_ERR_INVALID_ARGUMENT;
- if (compat & SSH_BUG_SIGBLOB)
- flags |= SSH_AGENT_OLD_SIGNATURE;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if ((r = sshkey_to_blob(key, &blob, &blen)) != 0)
- goto out;
+ flags |= agent_encode_alg(key, alg);
if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
- (r = sshbuf_put_string(msg, blob, blen)) != 0 ||
+ (r = sshkey_puts(key, msg)) != 0 ||
(r = sshbuf_put_string(msg, data, datalen)) != 0 ||
(r = sshbuf_put_u32(msg, flags)) != 0)
goto out;
- if ((r = ssh_request_reply(sock, msg, msg) != 0))
+ if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
@@ -467,55 +416,29 @@ ssh_agent_sign(int sock, struct sshkey *key,
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
- if ((r = sshbuf_get_string(msg, sigp, &len)) != 0)
+ if ((r = sshbuf_get_string(msg, &sig, &len)) != 0)
goto out;
+ /* Check what we actually got back from the agent. */
+ if ((r = sshkey_check_sigtype(sig, len, alg)) != 0)
+ goto out;
+ /* success */
+ *sigp = sig;
*lenp = len;
+ sig = NULL;
+ len = 0;
r = 0;
out:
- if (blob != NULL) {
- explicit_bzero(blob, blen);
- free(blob);
- }
+ freezero(sig, len);
sshbuf_free(msg);
return r;
}
/* Encode key for a message to the agent. */
-#ifdef WITH_SSH1
-static int
-ssh_encode_identity_rsa1(struct sshbuf *b, RSA *key, const char *comment)
-{
- int r;
-
- /* To keep within the protocol: p < q for ssh. in SSL p > q */
- if ((r = sshbuf_put_u32(b, BN_num_bits(key->n))) != 0 ||
- (r = sshbuf_put_bignum1(b, key->n)) != 0 ||
- (r = sshbuf_put_bignum1(b, key->e)) != 0 ||
- (r = sshbuf_put_bignum1(b, key->d)) != 0 ||
- (r = sshbuf_put_bignum1(b, key->iqmp)) != 0 ||
- (r = sshbuf_put_bignum1(b, key->q)) != 0 ||
- (r = sshbuf_put_bignum1(b, key->p)) != 0 ||
- (r = sshbuf_put_cstring(b, comment)) != 0)
- return r;
- return 0;
-}
-#endif
static int
-ssh_encode_identity_ssh2(struct sshbuf *b, struct sshkey *key,
- const char *comment)
-{
- int r;
-
- if ((r = sshkey_private_serialize(key, b)) != 0 ||
- (r = sshbuf_put_cstring(b, comment)) != 0)
- return r;
- return 0;
-}
-
-static int
-encode_constraints(struct sshbuf *m, u_int life, u_int confirm)
+encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign,
+ const char *provider)
{
int r;
@@ -528,6 +451,19 @@ encode_constraints(struct sshbuf *m, u_int life, u_int confirm)
if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_CONFIRM)) != 0)
goto out;
}
+ if (maxsign != 0) {
+ if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_MAXSIGN)) != 0 ||
+ (r = sshbuf_put_u32(m, maxsign)) != 0)
+ goto out;
+ }
+ if (provider != NULL) {
+ if ((r = sshbuf_put_u8(m,
+ SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 ||
+ (r = sshbuf_put_cstring(m,
+ "sk-provider@openssh.com")) != 0 ||
+ (r = sshbuf_put_cstring(m, provider)) != 0)
+ goto out;
+ }
r = 0;
out:
return r;
@@ -538,44 +474,41 @@ encode_constraints(struct sshbuf *m, u_int life, u_int confirm)
* This call is intended only for use by ssh-add(1) and like applications.
*/
int
-ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment,
- u_int life, u_int confirm)
+ssh_add_identity_constrained(int sock, struct sshkey *key,
+ const char *comment, u_int life, u_int confirm, u_int maxsign,
+ const char *provider)
{
struct sshbuf *msg;
- int r, constrained = (life || confirm);
+ int r, constrained = (life || confirm || maxsign || provider);
u_char type;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
switch (key->type) {
-#ifdef WITH_SSH1
- case KEY_RSA1:
- type = constrained ?
- SSH_AGENTC_ADD_RSA_ID_CONSTRAINED :
- SSH_AGENTC_ADD_RSA_IDENTITY;
- if ((r = sshbuf_put_u8(msg, type)) != 0 ||
- (r = ssh_encode_identity_rsa1(msg, key->rsa, comment)) != 0)
- goto out;
- break;
-#endif
#ifdef WITH_OPENSSL
case KEY_RSA:
case KEY_RSA_CERT:
- case KEY_RSA_CERT_V00:
case KEY_DSA:
case KEY_DSA_CERT:
- case KEY_DSA_CERT_V00:
case KEY_ECDSA:
case KEY_ECDSA_CERT:
+ case KEY_ECDSA_SK:
+ case KEY_ECDSA_SK_CERT:
#endif
case KEY_ED25519:
case KEY_ED25519_CERT:
+ case KEY_ED25519_SK:
+ case KEY_ED25519_SK_CERT:
+ case KEY_XMSS:
+ case KEY_XMSS_CERT:
type = constrained ?
SSH2_AGENTC_ADD_ID_CONSTRAINED :
SSH2_AGENTC_ADD_IDENTITY;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
- (r = ssh_encode_identity_ssh2(msg, key, comment)) != 0)
+ (r = sshkey_private_serialize_maxsign(key, msg, maxsign,
+ NULL)) != 0 ||
+ (r = sshbuf_put_cstring(msg, comment)) != 0)
goto out;
break;
default:
@@ -583,7 +516,8 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment,
goto out;
}
if (constrained &&
- (r = encode_constraints(msg, life, confirm)) != 0)
+ (r = encode_constraints(msg, life, confirm, maxsign,
+ provider)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
@@ -610,16 +544,6 @@ ssh_remove_identity(int sock, struct sshkey *key)
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
-#ifdef WITH_SSH1
- if (key->type == KEY_RSA1) {
- if ((r = sshbuf_put_u8(msg,
- SSH_AGENTC_REMOVE_RSA_IDENTITY)) != 0 ||
- (r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 ||
- (r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 ||
- (r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0)
- goto out;
- } else
-#endif
if (key->type != KEY_UNSPEC) {
if ((r = sshkey_to_blob(key, &blob, &blen)) != 0)
goto out;
@@ -637,10 +561,8 @@ ssh_remove_identity(int sock, struct sshkey *key)
goto out;
r = decode_reply(type);
out:
- if (blob != NULL) {
- explicit_bzero(blob, blen);
- free(blob);
- }
+ if (blob != NULL)
+ freezero(blob, blen);
sshbuf_free(msg);
return r;
}
@@ -671,7 +593,7 @@ ssh_update_card(int sock, int add, const char *reader_id, const char *pin,
(r = sshbuf_put_cstring(msg, pin)) != 0)
goto out;
if (constrained &&
- (r = encode_constraints(msg, life, confirm)) != 0)
+ (r = encode_constraints(msg, life, confirm, 0, NULL)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
@@ -686,6 +608,10 @@ ssh_update_card(int sock, int add, const char *reader_id, const char *pin,
/*
* Removes all identities from the agent.
* This call is intended only for use by ssh-add(1) and like applications.
+ *
+ * This supports the SSH protocol 1 message to because, when clearing all
+ * keys from an agent, we generally want to clear both protocol v1 and v2
+ * keys.
*/
int
ssh_remove_all_identities(int sock, int version)
diff --git a/authfd.h b/authfd.h
index bea20c26..c3bf6259 100644
--- a/authfd.h
+++ b/authfd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.h,v 1.38 2015/01/14 20:05:27 djm Exp $ */
+/* $OpenBSD: authfd.h,v 1.48 2019/12/21 02:19:13 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -24,24 +24,24 @@ struct ssh_identitylist {
};
int ssh_get_authentication_socket(int *fdp);
+int ssh_get_authentication_socket_path(const char *authsocket, int *fdp);
void ssh_close_authentication_socket(int sock);
int ssh_lock_agent(int sock, int lock, const char *password);
-int ssh_fetch_identitylist(int sock, int version,
- struct ssh_identitylist **idlp);
+int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp);
void ssh_free_identitylist(struct ssh_identitylist *idl);
int ssh_add_identity_constrained(int sock, struct sshkey *key,
- const char *comment, u_int life, u_int confirm);
+ 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_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);
-int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
- u_char session_id[16], u_char response[16]);
-int ssh_agent_sign(int sock, struct sshkey *key,
+int ssh_agent_sign(int sock, const struct sshkey *key,
u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, u_int compat);
+ const u_char *data, size_t datalen, const char *alg, u_int compat);
/* Messages for the authentication agent connection. */
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
@@ -78,6 +78,8 @@ int ssh_agent_sign(int sock, struct sshkey *key,
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
+#define SSH_AGENT_CONSTRAIN_MAXSIGN 3
+#define SSH_AGENT_CONSTRAIN_EXTENSION 255
/* extended failure messages */
#define SSH2_AGENT_FAILURE 30
@@ -86,5 +88,7 @@ int ssh_agent_sign(int sock, struct sshkey *key,
#define SSH_COM_AGENT2_FAILURE 102
#define SSH_AGENT_OLD_SIGNATURE 0x01
+#define SSH_AGENT_RSA_SHA2_256 0x02
+#define SSH_AGENT_RSA_SHA2_512 0x04
#endif /* AUTHFD_H */
diff --git a/authfile.c b/authfile.c
index 3a81786c..35ccf576 100644
--- a/authfile.c
+++ b/authfile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.c,v 1.111 2015/02/23 16:55:51 djm Exp $ */
+/* $OpenBSD: authfile.c,v 1.140 2020/04/17 07:15:11 djm Exp $ */
/*
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
*
@@ -39,13 +39,12 @@
#include <limits.h>
#include "cipher.h"
-#include "key.h"
#include "ssh.h"
#include "log.h"
#include "authfile.h"
-#include "rsa.h"
#include "misc.h"
#include "atomicio.h"
+#include "sshkey.h"
#include "sshbuf.h"
#include "ssherr.h"
#include "krl.h"
@@ -56,26 +55,19 @@
static int
sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename)
{
- int fd, oerrno;
+ int r;
+ mode_t omask;
- if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0)
- return SSH_ERR_SYSTEM_ERROR;
- if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(keybuf),
- sshbuf_len(keybuf)) != sshbuf_len(keybuf)) {
- oerrno = errno;
- close(fd);
- unlink(filename);
- errno = oerrno;
- return SSH_ERR_SYSTEM_ERROR;
- }
- close(fd);
- return 0;
+ omask = umask(077);
+ r = sshbuf_write_file(filename, keybuf);
+ umask(omask);
+ return r;
}
int
sshkey_save_private(struct sshkey *key, const char *filename,
const char *passphrase, const char *comment,
- int force_new_format, const char *new_format_cipher, int new_format_rounds)
+ int format, const char *openssh_format_cipher, int openssh_format_rounds)
{
struct sshbuf *keyblob = NULL;
int r;
@@ -83,7 +75,7 @@ sshkey_save_private(struct sshkey *key, const char *filename,
if ((keyblob = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment,
- force_new_format, new_format_cipher, new_format_rounds)) != 0)
+ format, openssh_format_cipher, openssh_format_rounds)) != 0)
goto out;
if ((r = sshkey_save_private_blob(keyblob, filename)) != 0)
goto out;
@@ -93,84 +85,13 @@ sshkey_save_private(struct sshkey *key, const char *filename,
return r;
}
-/* Load a key from a fd into a buffer */
-int
-sshkey_load_file(int fd, struct sshbuf *blob)
-{
- u_char buf[1024];
- size_t len;
- struct stat st;
- int r;
-
- if (fstat(fd, &st) < 0)
- return SSH_ERR_SYSTEM_ERROR;
- if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
- st.st_size > MAX_KEY_FILE_SIZE)
- return SSH_ERR_INVALID_FORMAT;
- for (;;) {
- if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
- if (errno == EPIPE)
- break;
- r = SSH_ERR_SYSTEM_ERROR;
- goto out;
- }
- if ((r = sshbuf_put(blob, buf, len)) != 0)
- goto out;
- if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) {
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- }
- if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
- st.st_size != (off_t)sshbuf_len(blob)) {
- r = SSH_ERR_FILE_CHANGED;
- goto out;
- }
- r = 0;
-
- out:
- explicit_bzero(buf, sizeof(buf));
- if (r != 0)
- sshbuf_reset(blob);
- return r;
-}
-
-#ifdef WITH_SSH1
-/*
- * Loads the public part of the ssh v1 key file. Returns NULL if an error was
- * encountered (the file does not exist or is not readable), and the key
- * otherwise.
- */
-static int
-sshkey_load_public_rsa1(int fd, struct sshkey **keyp, char **commentp)
-{
- struct sshbuf *b = NULL;
- int r;
-
- *keyp = NULL;
- if (commentp != NULL)
- *commentp = NULL;
-
- if ((b = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshkey_load_file(fd, b)) != 0)
- goto out;
- if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0)
- goto out;
- r = 0;
- out:
- sshbuf_free(b);
- return r;
-}
-#endif /* WITH_SSH1 */
-
/* XXX remove error() calls from here? */
int
sshkey_perm_ok(int fd, const char *filename)
{
struct stat st;
- if (fstat(fd, &st) < 0)
+ if (fstat(fd, &st) == -1)
return SSH_ERR_SYSTEM_ERROR;
/*
* if a key owned by the user is accessed, then we check the
@@ -186,56 +107,57 @@ sshkey_perm_ok(int fd, const char *filename)
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("Permissions 0%3.3o for '%s' are too open.",
(u_int)st.st_mode & 0777, filename);
- error("It is recommended that your private key files are NOT accessible by others.");
+ error("It is required that your private key files are NOT accessible by others.");
error("This private key will be ignored.");
return SSH_ERR_KEY_BAD_PERMISSIONS;
}
return 0;
}
-/* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */
int
sshkey_load_private_type(int type, const char *filename, const char *passphrase,
- struct sshkey **keyp, char **commentp, int *perm_ok)
+ struct sshkey **keyp, char **commentp)
{
int fd, r;
- *keyp = NULL;
+ if (keyp != NULL)
+ *keyp = NULL;
if (commentp != NULL)
*commentp = NULL;
- if ((fd = open(filename, O_RDONLY)) < 0) {
- if (perm_ok != NULL)
- *perm_ok = 0;
+ if ((fd = open(filename, O_RDONLY)) == -1)
return SSH_ERR_SYSTEM_ERROR;
- }
- if (sshkey_perm_ok(fd, filename) != 0) {
- if (perm_ok != NULL)
- *perm_ok = 0;
- r = SSH_ERR_KEY_BAD_PERMISSIONS;
+
+ r = sshkey_perm_ok(fd, filename);
+ if (r != 0)
goto out;
- }
- if (perm_ok != NULL)
- *perm_ok = 1;
r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp);
+ if (r == 0 && keyp && *keyp)
+ r = sshkey_set_filename(*keyp, filename);
out:
close(fd);
return r;
}
int
+sshkey_load_private(const char *filename, const char *passphrase,
+ struct sshkey **keyp, char **commentp)
+{
+ return sshkey_load_private_type(KEY_UNSPEC, filename, passphrase,
+ keyp, commentp);
+}
+
+int
sshkey_load_private_type_fd(int fd, int type, const char *passphrase,
struct sshkey **keyp, char **commentp)
{
struct sshbuf *buffer = NULL;
int r;
- if ((buffer = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshkey_load_file(fd, buffer)) != 0 ||
+ if (keyp != NULL)
+ *keyp = NULL;
+ if ((r = sshbuf_load_fd(fd, &buffer)) != 0 ||
(r = sshkey_parse_private_fileblob_type(buffer, type,
passphrase, keyp, commentp)) != 0)
goto out;
@@ -243,61 +165,62 @@ sshkey_load_private_type_fd(int fd, int type, const char *passphrase,
/* success */
r = 0;
out:
- if (buffer != NULL)
- sshbuf_free(buffer);
+ sshbuf_free(buffer);
return r;
}
-/* XXX this is almost identical to sshkey_load_private_type() */
-int
-sshkey_load_private(const char *filename, const char *passphrase,
- struct sshkey **keyp, char **commentp)
+/* Load a pubkey from the unencrypted envelope of a new-format private key */
+static int
+sshkey_load_pubkey_from_private(const char *filename, struct sshkey **pubkeyp)
{
struct sshbuf *buffer = NULL;
+ struct sshkey *pubkey = NULL;
int r, fd;
- *keyp = NULL;
- if (commentp != NULL)
- *commentp = NULL;
+ if (pubkeyp != NULL)
+ *pubkeyp = NULL;
- if ((fd = open(filename, O_RDONLY)) < 0)
+ if ((fd = open(filename, O_RDONLY)) == -1)
return SSH_ERR_SYSTEM_ERROR;
- if (sshkey_perm_ok(fd, filename) != 0) {
- r = SSH_ERR_KEY_BAD_PERMISSIONS;
+ if ((r = sshbuf_load_fd(fd, &buffer)) != 0 ||
+ (r = sshkey_parse_pubkey_from_private_fileblob_type(buffer,
+ KEY_UNSPEC, &pubkey)) != 0)
goto out;
- }
-
- if ((buffer = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
+ if ((r = sshkey_set_filename(pubkey, filename)) != 0)
goto out;
+ /* success */
+ if (pubkeyp != NULL) {
+ *pubkeyp = pubkey;
+ pubkey = NULL;
}
- if ((r = sshkey_load_file(fd, buffer)) != 0 ||
- (r = sshkey_parse_private_fileblob(buffer, passphrase, filename,
- keyp, commentp)) != 0)
- goto out;
r = 0;
out:
close(fd);
- if (buffer != NULL)
- sshbuf_free(buffer);
+ sshbuf_free(buffer);
+ sshkey_free(pubkey);
return r;
}
static int
-sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp)
+sshkey_try_load_public(struct sshkey **kp, const char *filename,
+ char **commentp)
{
FILE *f;
- char line[SSH_MAX_PUBKEY_BYTES];
- char *cp;
- u_long linenum = 0;
+ char *line = NULL, *cp;
+ size_t linesize = 0;
int r;
+ struct sshkey *k = NULL;
+ *kp = NULL;
if (commentp != NULL)
*commentp = NULL;
if ((f = fopen(filename, "r")) == NULL)
return SSH_ERR_SYSTEM_ERROR;
- while (read_keyfile_line(f, filename, line, sizeof(line),
- &linenum) != -1) {
+ if ((k = sshkey_new(KEY_UNSPEC)) == NULL) {
+ fclose(f);
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ while (getline(&line, &linesize, f) != -1) {
cp = line;
switch (*cp) {
case '#':
@@ -321,82 +244,47 @@ sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp)
if (*commentp == NULL)
r = SSH_ERR_ALLOC_FAIL;
}
+ /* success */
+ *kp = k;
+ free(line);
fclose(f);
return r;
}
}
}
+ free(k);
+ free(line);
fclose(f);
return SSH_ERR_INVALID_FORMAT;
}
-/* load public key from ssh v1 private or any pubkey file */
+/* load public key from any pubkey file */
int
sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
{
- struct sshkey *pub = NULL;
- char file[PATH_MAX];
- int r, fd;
+ char *pubfile = NULL;
+ int r;
if (keyp != NULL)
*keyp = NULL;
if (commentp != NULL)
*commentp = NULL;
- /* XXX should load file once and attempt to parse each format */
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- goto skip;
-#ifdef WITH_SSH1
- /* try rsa1 private key */
- r = sshkey_load_public_rsa1(fd, keyp, commentp);
- close(fd);
- switch (r) {
- case SSH_ERR_INTERNAL_ERROR:
- case SSH_ERR_ALLOC_FAIL:
- case SSH_ERR_INVALID_ARGUMENT:
- case SSH_ERR_SYSTEM_ERROR:
- case 0:
- return r;
- }
-#endif /* WITH_SSH1 */
-
- /* try ssh2 public key */
- if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
- if (keyp != NULL)
- *keyp = pub;
- return 0;
- }
- sshkey_free(pub);
-
-#ifdef WITH_SSH1
- /* try rsa1 public key */
- if ((pub = sshkey_new(KEY_RSA1)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
- if (keyp != NULL)
- *keyp = pub;
- return 0;
- }
- sshkey_free(pub);
-#endif /* WITH_SSH1 */
+ if ((r = sshkey_try_load_public(keyp, filename, commentp)) == 0)
+ goto out;
- skip:
/* try .pub suffix */
- if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
+ if (asprintf(&pubfile, "%s.pub", filename) == -1)
return SSH_ERR_ALLOC_FAIL;
- r = SSH_ERR_ALLOC_FAIL; /* in case strlcpy or strlcat fail */
- if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
- (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
- (r = sshkey_try_load_public(pub, file, commentp)) == 0) {
- if (keyp != NULL)
- *keyp = pub;
- return 0;
- }
- sshkey_free(pub);
+ if ((r = sshkey_try_load_public(keyp, pubfile, commentp)) == 0)
+ goto out;
+
+ /* finally, try to extract public key from private key file */
+ if ((r = sshkey_load_pubkey_from_private(filename, keyp)) == 0)
+ goto out;
+ out:
+ free(pubfile);
return r;
}
@@ -408,46 +296,37 @@ sshkey_load_cert(const char *filename, struct sshkey **keyp)
char *file = NULL;
int r = SSH_ERR_INTERNAL_ERROR;
- *keyp = NULL;
+ if (keyp != NULL)
+ *keyp = NULL;
if (asprintf(&file, "%s-cert.pub", filename) == -1)
return SSH_ERR_ALLOC_FAIL;
- if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
- goto out;
- }
- if ((r = sshkey_try_load_public(pub, file, NULL)) != 0)
- goto out;
-
- *keyp = pub;
- pub = NULL;
- r = 0;
-
- out:
- if (file != NULL)
- free(file);
- if (pub != NULL)
- sshkey_free(pub);
+ r = sshkey_try_load_public(keyp, file, NULL);
+ free(file);
+ sshkey_free(pub);
return r;
}
/* Load private key and certificate */
int
sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
- struct sshkey **keyp, int *perm_ok)
+ struct sshkey **keyp)
{
struct sshkey *key = NULL, *cert = NULL;
int r;
- *keyp = NULL;
+ if (keyp != NULL)
+ *keyp = NULL;
switch (type) {
#ifdef WITH_OPENSSL
case KEY_RSA:
case KEY_DSA:
case KEY_ECDSA:
- case KEY_ED25519:
#endif /* WITH_OPENSSL */
+ case KEY_ED25519:
+ case KEY_XMSS:
case KEY_UNSPEC:
break;
default:
@@ -455,7 +334,7 @@ sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
}
if ((r = sshkey_load_private_type(type, filename,
- passphrase, &key, NULL, perm_ok)) != 0 ||
+ passphrase, &key, NULL)) != 0 ||
(r = sshkey_load_cert(filename, &cert)) != 0)
goto out;
@@ -465,17 +344,17 @@ sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
goto out;
}
- if ((r = sshkey_to_certified(key, sshkey_cert_is_legacy(cert))) != 0 ||
+ if ((r = sshkey_to_certified(key)) != 0 ||
(r = sshkey_cert_copy(cert, key)) != 0)
goto out;
r = 0;
- *keyp = key;
- key = NULL;
+ if (keyp != NULL) {
+ *keyp = key;
+ key = NULL;
+ }
out:
- if (key != NULL)
- sshkey_free(key);
- if (cert != NULL)
- sshkey_free(cert);
+ sshkey_free(key);
+ sshkey_free(cert);
return r;
}
@@ -492,19 +371,20 @@ sshkey_in_file(struct sshkey *key, const char *filename, int strict_type,
int check_ca)
{
FILE *f;
- char line[SSH_MAX_PUBKEY_BYTES];
- char *cp;
- u_long linenum = 0;
+ char *line = NULL, *cp;
+ size_t linesize = 0;
int r = 0;
struct sshkey *pub = NULL;
+
int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) =
strict_type ? sshkey_equal : sshkey_equal_public;
if ((f = fopen(filename, "r")) == NULL)
return SSH_ERR_SYSTEM_ERROR;
- while (read_keyfile_line(f, filename, line, sizeof(line),
- &linenum) != -1) {
+ while (getline(&line, &linesize, f) != -1) {
+ sshkey_free(pub);
+ pub = NULL;
cp = line;
/* Skip leading whitespace. */
@@ -523,21 +403,25 @@ sshkey_in_file(struct sshkey *key, const char *filename, int strict_type,
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((r = sshkey_read(pub, &cp)) != 0)
+ switch (r = sshkey_read(pub, &cp)) {
+ case 0:
+ break;
+ case SSH_ERR_KEY_LENGTH:
+ continue;
+ default:
goto out;
+ }
if (sshkey_compare(key, pub) ||
(check_ca && sshkey_is_cert(key) &&
sshkey_compare(key->cert->signature_key, pub))) {
r = 0;
goto out;
}
- sshkey_free(pub);
- pub = NULL;
}
r = SSH_ERR_KEY_NOT_FOUND;
out:
- if (pub != NULL)
- sshkey_free(pub);
+ free(line);
+ sshkey_free(pub);
fclose(f);
return r;
}
@@ -576,3 +460,56 @@ sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file)
}
}
+/*
+ * Advanced *cpp past the end of key options, defined as the first unquoted
+ * whitespace character. Returns 0 on success or -1 on failure (e.g.
+ * unterminated quotes).
+ */
+int
+sshkey_advance_past_options(char **cpp)
+{
+ char *cp = *cpp;
+ int quoted = 0;
+
+ for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
+ if (*cp == '\\' && cp[1] == '"')
+ cp++; /* Skip both */
+ else if (*cp == '"')
+ quoted = !quoted;
+ }
+ *cpp = cp;
+ /* return failure for unterminated quotes */
+ return (*cp == '\0' && quoted) ? -1 : 0;
+}
+
+/* Save a public key */
+int
+sshkey_save_public(const struct sshkey *key, const char *path,
+ const char *comment)
+{
+ int fd, oerrno;
+ FILE *f = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
+ return SSH_ERR_SYSTEM_ERROR;
+ if ((f = fdopen(fd, "w")) == NULL) {
+ r = SSH_ERR_SYSTEM_ERROR;
+ goto fail;
+ }
+ if ((r = sshkey_write(key, f)) != 0)
+ goto fail;
+ fprintf(f, " %s\n", comment);
+ if (ferror(f) || fclose(f) != 0) {
+ r = SSH_ERR_SYSTEM_ERROR;
+ fail:
+ oerrno = errno;
+ if (f != NULL)
+ fclose(f);
+ else
+ close(fd);
+ errno = oerrno;
+ return r;
+ }
+ return 0;
+}
diff --git a/authfile.h b/authfile.h
index 624d269f..1db067a8 100644
--- a/authfile.h
+++ b/authfile.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.h,v 1.21 2015/01/08 10:14:08 djm Exp $ */
+/* $OpenBSD: authfile.h,v 1.25 2020/01/25 23:02:13 djm Exp $ */
/*
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
@@ -35,18 +35,20 @@ struct sshkey;
int sshkey_save_private(struct sshkey *, const char *,
const char *, const char *, int, const char *, int);
-int sshkey_load_file(int, struct sshbuf *);
int sshkey_load_cert(const char *, struct sshkey **);
int sshkey_load_public(const char *, struct sshkey **, char **);
int sshkey_load_private(const char *, const char *, struct sshkey **, char **);
int sshkey_load_private_cert(int, const char *, const char *,
- struct sshkey **, int *);
+ struct sshkey **);
int sshkey_load_private_type(int, const char *, const char *,
- struct sshkey **, char **, int *);
+ struct sshkey **, char **);
int sshkey_load_private_type_fd(int fd, int type, const char *passphrase,
struct sshkey **keyp, char **commentp);
int sshkey_perm_ok(int, const char *);
int sshkey_in_file(struct sshkey *, const char *, int, int);
int sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file);
+int sshkey_advance_past_options(char **cpp);
+int sshkey_save_public(const struct sshkey *key, const char *path,
+ const char *comment);
#endif
diff --git a/bitmap.c b/bitmap.c
index 19cd2e8e..5ecfe68b 100644
--- a/bitmap.c
+++ b/bitmap.c
@@ -1,3 +1,4 @@
+/* $OpenBSD: bitmap.c,v 1.9 2017/10/20 01:56:39 djm Exp $ */
/*
* Copyright (c) 2015 Damien Miller <djm@mindrot.org>
*
@@ -53,8 +54,9 @@ void
bitmap_free(struct bitmap *b)
{
if (b != NULL && b->d != NULL) {
- memset(b->d, 0, b->len);
+ bitmap_zero(b);
free(b->d);
+ b->d = NULL;
}
free(b);
}
@@ -86,10 +88,10 @@ reserve(struct bitmap *b, u_int n)
return -1; /* invalid */
nlen = (n / BITMAP_BITS) + 1;
if (b->len < nlen) {
- if ((tmp = reallocarray(b->d, nlen, BITMAP_BYTES)) == NULL)
+ if ((tmp = recallocarray(b->d, b->len,
+ nlen, BITMAP_BYTES)) == NULL)
return -1;
b->d = tmp;
- memset(b->d + b->len, 0, (nlen - b->len) * BITMAP_BYTES);
b->len = nlen;
}
return 0;
@@ -188,7 +190,7 @@ bitmap_from_string(struct bitmap *b, const void *p, size_t l)
{
int r;
size_t i, offset, shift;
- u_char *s = (u_char *)p;
+ const u_char *s = (const u_char *)p;
if (l > BITMAP_MAX / 8)
return -1;
diff --git a/bitmap.h b/bitmap.h
index c1bb1741..336e90b0 100644
--- a/bitmap.h
+++ b/bitmap.h
@@ -1,3 +1,4 @@
+/* $OpenBSD: bitmap.h,v 1.2 2017/10/20 01:56:39 djm Exp $ */
/*
* Copyright (c) 2015 Damien Miller <djm@mindrot.org>
*
diff --git a/blocks.c b/blocks.c
deleted file mode 100644
index ad93fe50..00000000
--- a/blocks.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/* $OpenBSD: blocks.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
-
-/*
- * Public Domain, Author: Daniel J. Bernstein
- * Copied from nacl-20110221/crypto_hashblocks/sha512/ref/blocks.c
- */
-
-#include "includes.h"
-
-#include "crypto_api.h"
-
-typedef unsigned long long uint64;
-
-static uint64 load_bigendian(const unsigned char *x)
-{
- return
- (uint64) (x[7]) \
- | (((uint64) (x[6])) << 8) \
- | (((uint64) (x[5])) << 16) \
- | (((uint64) (x[4])) << 24) \
- | (((uint64) (x[3])) << 32) \
- | (((uint64) (x[2])) << 40) \
- | (((uint64) (x[1])) << 48) \
- | (((uint64) (x[0])) << 56)
- ;
-}
-
-static void store_bigendian(unsigned char *x,uint64 u)
-{
- x[7] = u; u >>= 8;
- x[6] = u; u >>= 8;
- x[5] = u; u >>= 8;
- x[4] = u; u >>= 8;
- x[3] = u; u >>= 8;
- x[2] = u; u >>= 8;
- x[1] = u; u >>= 8;
- x[0] = u;
-}
-
-#define SHR(x,c) ((x) >> (c))
-#define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c))))
-
-#define Ch(x,y,z) ((x & y) ^ (~x & z))
-#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
-#define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
-#define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
-#define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7))
-#define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6))
-
-#define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0;
-
-#define EXPAND \
- M(w0 ,w14,w9 ,w1 ) \
- M(w1 ,w15,w10,w2 ) \
- M(w2 ,w0 ,w11,w3 ) \
- M(w3 ,w1 ,w12,w4 ) \
- M(w4 ,w2 ,w13,w5 ) \
- M(w5 ,w3 ,w14,w6 ) \
- M(w6 ,w4 ,w15,w7 ) \
- M(w7 ,w5 ,w0 ,w8 ) \
- M(w8 ,w6 ,w1 ,w9 ) \
- M(w9 ,w7 ,w2 ,w10) \
- M(w10,w8 ,w3 ,w11) \
- M(w11,w9 ,w4 ,w12) \
- M(w12,w10,w5 ,w13) \
- M(w13,w11,w6 ,w14) \
- M(w14,w12,w7 ,w15) \
- M(w15,w13,w8 ,w0 )
-
-#define F(w,k) \
- T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \
- T2 = Sigma0(a) + Maj(a,b,c); \
- h = g; \
- g = f; \
- f = e; \
- e = d + T1; \
- d = c; \
- c = b; \
- b = a; \
- a = T1 + T2;
-
-int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen)
-{
- uint64 state[8];
- uint64 a;
- uint64 b;
- uint64 c;
- uint64 d;
- uint64 e;
- uint64 f;
- uint64 g;
- uint64 h;
- uint64 T1;
- uint64 T2;
-
- a = load_bigendian(statebytes + 0); state[0] = a;
- b = load_bigendian(statebytes + 8); state[1] = b;
- c = load_bigendian(statebytes + 16); state[2] = c;
- d = load_bigendian(statebytes + 24); state[3] = d;
- e = load_bigendian(statebytes + 32); state[4] = e;
- f = load_bigendian(statebytes + 40); state[5] = f;
- g = load_bigendian(statebytes + 48); state[6] = g;
- h = load_bigendian(statebytes + 56); state[7] = h;
-
- while (inlen >= 128) {
- uint64 w0 = load_bigendian(in + 0);
- uint64 w1 = load_bigendian(in + 8);
- uint64 w2 = load_bigendian(in + 16);
- uint64 w3 = load_bigendian(in + 24);
- uint64 w4 = load_bigendian(in + 32);
- uint64 w5 = load_bigendian(in + 40);
- uint64 w6 = load_bigendian(in + 48);
- uint64 w7 = load_bigendian(in + 56);
- uint64 w8 = load_bigendian(in + 64);
- uint64 w9 = load_bigendian(in + 72);
- uint64 w10 = load_bigendian(in + 80);
- uint64 w11 = load_bigendian(in + 88);
- uint64 w12 = load_bigendian(in + 96);
- uint64 w13 = load_bigendian(in + 104);
- uint64 w14 = load_bigendian(in + 112);
- uint64 w15 = load_bigendian(in + 120);
-
- F(w0 ,0x428a2f98d728ae22ULL)
- F(w1 ,0x7137449123ef65cdULL)
- F(w2 ,0xb5c0fbcfec4d3b2fULL)
- F(w3 ,0xe9b5dba58189dbbcULL)
- F(w4 ,0x3956c25bf348b538ULL)
- F(w5 ,0x59f111f1b605d019ULL)
- F(w6 ,0x923f82a4af194f9bULL)
- F(w7 ,0xab1c5ed5da6d8118ULL)
- F(w8 ,0xd807aa98a3030242ULL)
- F(w9 ,0x12835b0145706fbeULL)
- F(w10,0x243185be4ee4b28cULL)
- F(w11,0x550c7dc3d5ffb4e2ULL)
- F(w12,0x72be5d74f27b896fULL)
- F(w13,0x80deb1fe3b1696b1ULL)
- F(w14,0x9bdc06a725c71235ULL)
- F(w15,0xc19bf174cf692694ULL)
-
- EXPAND
-
- F(w0 ,0xe49b69c19ef14ad2ULL)
- F(w1 ,0xefbe4786384f25e3ULL)
- F(w2 ,0x0fc19dc68b8cd5b5ULL)
- F(w3 ,0x240ca1cc77ac9c65ULL)
- F(w4 ,0x2de92c6f592b0275ULL)
- F(w5 ,0x4a7484aa6ea6e483ULL)
- F(w6 ,0x5cb0a9dcbd41fbd4ULL)
- F(w7 ,0x76f988da831153b5ULL)
- F(w8 ,0x983e5152ee66dfabULL)
- F(w9 ,0xa831c66d2db43210ULL)
- F(w10,0xb00327c898fb213fULL)
- F(w11,0xbf597fc7beef0ee4ULL)
- F(w12,0xc6e00bf33da88fc2ULL)
- F(w13,0xd5a79147930aa725ULL)
- F(w14,0x06ca6351e003826fULL)
- F(w15,0x142929670a0e6e70ULL)
-
- EXPAND
-
- F(w0 ,0x27b70a8546d22ffcULL)
- F(w1 ,0x2e1b21385c26c926ULL)
- F(w2 ,0x4d2c6dfc5ac42aedULL)
- F(w3 ,0x53380d139d95b3dfULL)
- F(w4 ,0x650a73548baf63deULL)
- F(w5 ,0x766a0abb3c77b2a8ULL)
- F(w6 ,0x81c2c92e47edaee6ULL)
- F(w7 ,0x92722c851482353bULL)
- F(w8 ,0xa2bfe8a14cf10364ULL)
- F(w9 ,0xa81a664bbc423001ULL)
- F(w10,0xc24b8b70d0f89791ULL)
- F(w11,0xc76c51a30654be30ULL)
- F(w12,0xd192e819d6ef5218ULL)
- F(w13,0xd69906245565a910ULL)
- F(w14,0xf40e35855771202aULL)
- F(w15,0x106aa07032bbd1b8ULL)
-
- EXPAND
-
- F(w0 ,0x19a4c116b8d2d0c8ULL)
- F(w1 ,0x1e376c085141ab53ULL)
- F(w2 ,0x2748774cdf8eeb99ULL)
- F(w3 ,0x34b0bcb5e19b48a8ULL)
- F(w4 ,0x391c0cb3c5c95a63ULL)
- F(w5 ,0x4ed8aa4ae3418acbULL)
- F(w6 ,0x5b9cca4f7763e373ULL)
- F(w7 ,0x682e6ff3d6b2b8a3ULL)
- F(w8 ,0x748f82ee5defb2fcULL)
- F(w9 ,0x78a5636f43172f60ULL)
- F(w10,0x84c87814a1f0ab72ULL)
- F(w11,0x8cc702081a6439ecULL)
- F(w12,0x90befffa23631e28ULL)
- F(w13,0xa4506cebde82bde9ULL)
- F(w14,0xbef9a3f7b2c67915ULL)
- F(w15,0xc67178f2e372532bULL)
-
- EXPAND
-
- F(w0 ,0xca273eceea26619cULL)
- F(w1 ,0xd186b8c721c0c207ULL)
- F(w2 ,0xeada7dd6cde0eb1eULL)
- F(w3 ,0xf57d4f7fee6ed178ULL)
- F(w4 ,0x06f067aa72176fbaULL)
- F(w5 ,0x0a637dc5a2c898a6ULL)
- F(w6 ,0x113f9804bef90daeULL)
- F(w7 ,0x1b710b35131c471bULL)
- F(w8 ,0x28db77f523047d84ULL)
- F(w9 ,0x32caab7b40c72493ULL)
- F(w10,0x3c9ebe0a15c9bebcULL)
- F(w11,0x431d67c49c100d4cULL)
- F(w12,0x4cc5d4becb3e42b6ULL)
- F(w13,0x597f299cfc657e2aULL)
- F(w14,0x5fcb6fab3ad6faecULL)
- F(w15,0x6c44198c4a475817ULL)
-
- a += state[0];
- b += state[1];
- c += state[2];
- d += state[3];
- e += state[4];
- f += state[5];
- g += state[6];
- h += state[7];
-
- state[0] = a;
- state[1] = b;
- state[2] = c;
- state[3] = d;
- state[4] = e;
- state[5] = f;
- state[6] = g;
- state[7] = h;
-
- in += 128;
- inlen -= 128;
- }
-
- store_bigendian(statebytes + 0,state[0]);
- store_bigendian(statebytes + 8,state[1]);
- store_bigendian(statebytes + 16,state[2]);
- store_bigendian(statebytes + 24,state[3]);
- store_bigendian(statebytes + 32,state[4]);
- store_bigendian(statebytes + 40,state[5]);
- store_bigendian(statebytes + 48,state[6]);
- store_bigendian(statebytes + 56,state[7]);
-
- return inlen;
-}
diff --git a/bufaux.c b/bufaux.c
deleted file mode 100644
index 3976896a..00000000
--- a/bufaux.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* $OpenBSD: bufaux.c,v 1.60 2014/04/30 05:29:56 djm Exp $ */
-/*
- * Copyright (c) 2012 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.
- */
-
-/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
-
-#include "includes.h"
-
-#include <sys/types.h>
-
-#include "buffer.h"
-#include "log.h"
-#include "ssherr.h"
-
-int
-buffer_get_short_ret(u_short *v, Buffer *buffer)
-{
- int ret;
-
- if ((ret = sshbuf_get_u16(buffer, v)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return -1;
- }
- return 0;
-}
-
-u_short
-buffer_get_short(Buffer *buffer)
-{
- u_short ret;
-
- if (buffer_get_short_ret(&ret, buffer) == -1)
- fatal("%s: buffer error", __func__);
-
- return (ret);
-}
-
-int
-buffer_get_int_ret(u_int *v, Buffer *buffer)
-{
- int ret;
-
- if ((ret = sshbuf_get_u32(buffer, v)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return -1;
- }
- return 0;
-}
-
-u_int
-buffer_get_int(Buffer *buffer)
-{
- u_int ret;
-
- if (buffer_get_int_ret(&ret, buffer) == -1)
- fatal("%s: buffer error", __func__);
-
- return (ret);
-}
-
-int
-buffer_get_int64_ret(u_int64_t *v, Buffer *buffer)
-{
- int ret;
-
- if ((ret = sshbuf_get_u64(buffer, v)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return -1;
- }
- return 0;
-}
-
-u_int64_t
-buffer_get_int64(Buffer *buffer)
-{
- u_int64_t ret;
-
- if (buffer_get_int64_ret(&ret, buffer) == -1)
- fatal("%s: buffer error", __func__);
-
- return (ret);
-}
-
-void
-buffer_put_short(Buffer *buffer, u_short value)
-{
- int ret;
-
- if ((ret = sshbuf_put_u16(buffer, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(ret));
-}
-
-void
-buffer_put_int(Buffer *buffer, u_int value)
-{
- int ret;
-
- if ((ret = sshbuf_put_u32(buffer, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(ret));
-}
-
-void
-buffer_put_int64(Buffer *buffer, u_int64_t value)
-{
- int ret;
-
- if ((ret = sshbuf_put_u64(buffer, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(ret));
-}
-
-void *
-buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
-{
- size_t len;
- int ret;
- u_char *value;
-
- if ((ret = sshbuf_get_string(buffer, &value, &len)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return NULL;
- }
- if (length_ptr != NULL)
- *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */
- return value;
-}
-
-void *
-buffer_get_string(Buffer *buffer, u_int *length_ptr)
-{
- void *ret;
-
- if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL)
- fatal("%s: buffer error", __func__);
- return (ret);
-}
-
-char *
-buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr)
-{
- size_t len;
- int ret;
- char *value;
-
- if ((ret = sshbuf_get_cstring(buffer, &value, &len)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return NULL;
- }
- if (length_ptr != NULL)
- *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */
- return value;
-}
-
-char *
-buffer_get_cstring(Buffer *buffer, u_int *length_ptr)
-{
- char *ret;
-
- if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL)
- fatal("%s: buffer error", __func__);
- return ret;
-}
-
-const void *
-buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr)
-{
- size_t len;
- int ret;
- const u_char *value;
-
- if ((ret = sshbuf_get_string_direct(buffer, &value, &len)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return NULL;
- }
- if (length_ptr != NULL)
- *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */
- return value;
-}
-
-const void *
-buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr)
-{
- const void *ret;
-
- if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL)
- fatal("%s: buffer error", __func__);
- return (ret);
-}
-
-void
-buffer_put_string(Buffer *buffer, const void *buf, u_int len)
-{
- int ret;
-
- if ((ret = sshbuf_put_string(buffer, buf, len)) != 0)
- fatal("%s: %s", __func__, ssh_err(ret));
-}
-
-void
-buffer_put_cstring(Buffer *buffer, const char *s)
-{
- int ret;
-
- if ((ret = sshbuf_put_cstring(buffer, s)) != 0)
- fatal("%s: %s", __func__, ssh_err(ret));
-}
-
-int
-buffer_get_char_ret(char *v, Buffer *buffer)
-{
- int ret;
-
- if ((ret = sshbuf_get_u8(buffer, (u_char *)v)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return -1;
- }
- return 0;
-}
-
-int
-buffer_get_char(Buffer *buffer)
-{
- char ch;
-
- if (buffer_get_char_ret(&ch, buffer) == -1)
- fatal("%s: buffer error", __func__);
- return (u_char) ch;
-}
-
-void
-buffer_put_char(Buffer *buffer, int value)
-{
- int ret;
-
- if ((ret = sshbuf_put_u8(buffer, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(ret));
-}
-
-void
-buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
-{
- int ret;
-
- if ((ret = sshbuf_put_bignum2_bytes(buffer, s, l)) != 0)
- fatal("%s: %s", __func__, ssh_err(ret));
-}
-
diff --git a/bufbn.c b/bufbn.c
deleted file mode 100644
index 33ae7f73..00000000
--- a/bufbn.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/* $OpenBSD: bufbn.c,v 1.12 2014/04/30 05:29:56 djm Exp $ */
-
-/*
- * Copyright (c) 2012 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.
- */
-
-/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
-
-#include "includes.h"
-
-#ifdef WITH_OPENSSL
-
-#include <sys/types.h>
-
-#include "buffer.h"
-#include "log.h"
-#include "ssherr.h"
-
-#ifdef WITH_SSH1
-int
-buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value)
-{
- int ret;
-
- if ((ret = sshbuf_put_bignum1(buffer, value)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return -1;
- }
- return 0;
-}
-
-void
-buffer_put_bignum(Buffer *buffer, const BIGNUM *value)
-{
- if (buffer_put_bignum_ret(buffer, value) == -1)
- fatal("%s: buffer error", __func__);
-}
-
-int
-buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
-{
- int ret;
-
- if ((ret = sshbuf_get_bignum1(buffer, value)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return -1;
- }
- return 0;
-}
-
-void
-buffer_get_bignum(Buffer *buffer, BIGNUM *value)
-{
- if (buffer_get_bignum_ret(buffer, value) == -1)
- fatal("%s: buffer error", __func__);
-}
-#endif /* WITH_SSH1 */
-
-int
-buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
-{
- int ret;
-
- if ((ret = sshbuf_put_bignum2(buffer, value)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return -1;
- }
- return 0;
-}
-
-void
-buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
-{
- if (buffer_put_bignum2_ret(buffer, value) == -1)
- fatal("%s: buffer error", __func__);
-}
-
-int
-buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value)
-{
- int ret;
-
- if ((ret = sshbuf_get_bignum2(buffer, value)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return -1;
- }
- return 0;
-}
-
-void
-buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
-{
- if (buffer_get_bignum2_ret(buffer, value) == -1)
- fatal("%s: buffer error", __func__);
-}
-
-#endif /* WITH_OPENSSL */
diff --git a/bufec.c b/bufec.c
deleted file mode 100644
index 749ce9d4..00000000
--- a/bufec.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* $OpenBSD: bufec.c,v 1.4 2014/04/30 05:29:56 djm Exp $ */
-
-/*
- * Copyright (c) 2012 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.
- */
-
-/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
-
-#include "includes.h"
-
-#include <sys/types.h>
-
-#include "buffer.h"
-#include "log.h"
-#include "ssherr.h"
-
-#ifdef OPENSSL_HAS_ECC
-
-int
-buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
- const EC_POINT *point)
-{
- int ret;
-
- if ((ret = sshbuf_put_ec(buffer, point, curve)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return -1;
- }
- return 0;
-}
-
-void
-buffer_put_ecpoint(Buffer *buffer, const EC_GROUP *curve,
- const EC_POINT *point)
-{
- if (buffer_put_ecpoint_ret(buffer, curve, point) == -1)
- fatal("%s: buffer error", __func__);
-}
-
-int
-buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
- EC_POINT *point)
-{
- int ret;
-
- if ((ret = sshbuf_get_ec(buffer, point, curve)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return -1;
- }
- return 0;
-}
-
-void
-buffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve,
- EC_POINT *point)
-{
- if (buffer_get_ecpoint_ret(buffer, curve, point) == -1)
- fatal("%s: buffer error", __func__);
-}
-
-#endif /* OPENSSL_HAS_ECC */
-
diff --git a/buffer.c b/buffer.c
deleted file mode 100644
index c5f708ab..00000000
--- a/buffer.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* $OpenBSD: buffer.c,v 1.36 2014/04/30 05:29:56 djm Exp $ */
-
-/*
- * Copyright (c) 2012 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.
- */
-
-/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
-
-#include "includes.h"
-
-#include <sys/types.h>
-
-#include "buffer.h"
-#include "log.h"
-#include "ssherr.h"
-
-void
-buffer_append(Buffer *buffer, const void *data, u_int len)
-{
- int ret;
-
- if ((ret = sshbuf_put(buffer, data, len)) != 0)
- fatal("%s: %s", __func__, ssh_err(ret));
-}
-
-void *
-buffer_append_space(Buffer *buffer, u_int len)
-{
- int ret;
- u_char *p;
-
- if ((ret = sshbuf_reserve(buffer, len, &p)) != 0)
- fatal("%s: %s", __func__, ssh_err(ret));
- return p;
-}
-
-int
-buffer_check_alloc(Buffer *buffer, u_int len)
-{
- int ret = sshbuf_check_reserve(buffer, len);
-
- if (ret == 0)
- return 1;
- if (ret == SSH_ERR_NO_BUFFER_SPACE)
- return 0;
- fatal("%s: %s", __func__, ssh_err(ret));
-}
-
-int
-buffer_get_ret(Buffer *buffer, void *buf, u_int len)
-{
- int ret;
-
- if ((ret = sshbuf_get(buffer, buf, len)) != 0) {
- error("%s: %s", __func__, ssh_err(ret));
- return -1;
- }
- return 0;
-}
-
-void
-buffer_get(Buffer *buffer, void *buf, u_int len)
-{
- if (buffer_get_ret(buffer, buf, len) == -1)
- fatal("%s: buffer error", __func__);
-}
-
-int
-buffer_consume_ret(Buffer *buffer, u_int bytes)
-{
- int ret = sshbuf_consume(buffer, bytes);
-
- if (ret == 0)
- return 0;
- if (ret == SSH_ERR_MESSAGE_INCOMPLETE)
- return -1;
- fatal("%s: %s", __func__, ssh_err(ret));
-}
-
-void
-buffer_consume(Buffer *buffer, u_int bytes)
-{
- if (buffer_consume_ret(buffer, bytes) == -1)
- fatal("%s: buffer error", __func__);
-}
-
-int
-buffer_consume_end_ret(Buffer *buffer, u_int bytes)
-{
- int ret = sshbuf_consume_end(buffer, bytes);
-
- if (ret == 0)
- return 0;
- if (ret == SSH_ERR_MESSAGE_INCOMPLETE)
- return -1;
- fatal("%s: %s", __func__, ssh_err(ret));
-}
-
-void
-buffer_consume_end(Buffer *buffer, u_int bytes)
-{
- if (buffer_consume_end_ret(buffer, bytes) == -1)
- fatal("%s: buffer error", __func__);
-}
-
-
diff --git a/buffer.h b/buffer.h
deleted file mode 100644
index df1aebc0..00000000
--- a/buffer.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* $OpenBSD: buffer.h,v 1.25 2014/04/30 05:29:56 djm Exp $ */
-
-/*
- * Copyright (c) 2012 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.
- */
-
-/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
-
-#ifndef BUFFER_H
-#define BUFFER_H
-
-#include "sshbuf.h"
-
-typedef struct sshbuf Buffer;
-
-#define buffer_init(b) sshbuf_init(b)
-#define buffer_clear(b) sshbuf_reset(b)
-#define buffer_free(b) sshbuf_free(b)
-#define buffer_dump(b) sshbuf_dump(b, stderr)
-
-/* XXX cast is safe: sshbuf never stores more than len 2^31 */
-#define buffer_len(b) ((u_int) sshbuf_len(b))
-#define buffer_ptr(b) sshbuf_mutable_ptr(b)
-
-void buffer_append(Buffer *, const void *, u_int);
-void *buffer_append_space(Buffer *, u_int);
-int buffer_check_alloc(Buffer *, u_int);
-void buffer_get(Buffer *, void *, u_int);
-
-void buffer_consume(Buffer *, u_int);
-void buffer_consume_end(Buffer *, u_int);
-
-
-int buffer_get_ret(Buffer *, void *, u_int);
-int buffer_consume_ret(Buffer *, u_int);
-int buffer_consume_end_ret(Buffer *, u_int);
-
-#include <openssl/objects.h>
-#include <openssl/bn.h>
-void buffer_put_bignum(Buffer *, const BIGNUM *);
-void buffer_put_bignum2(Buffer *, const BIGNUM *);
-void buffer_get_bignum(Buffer *, BIGNUM *);
-void buffer_get_bignum2(Buffer *, BIGNUM *);
-void buffer_put_bignum2_from_string(Buffer *, const u_char *, u_int);
-
-u_short buffer_get_short(Buffer *);
-void buffer_put_short(Buffer *, u_short);
-
-u_int buffer_get_int(Buffer *);
-void buffer_put_int(Buffer *, u_int);
-
-u_int64_t buffer_get_int64(Buffer *);
-void buffer_put_int64(Buffer *, u_int64_t);
-
-int buffer_get_char(Buffer *);
-void buffer_put_char(Buffer *, int);
-
-void *buffer_get_string(Buffer *, u_int *);
-const void *buffer_get_string_ptr(Buffer *, u_int *);
-void buffer_put_string(Buffer *, const void *, u_int);
-char *buffer_get_cstring(Buffer *, u_int *);
-void buffer_put_cstring(Buffer *, const char *);
-
-#define buffer_skip_string(b) (void)buffer_get_string_ptr(b, NULL);
-
-int buffer_put_bignum_ret(Buffer *, const BIGNUM *);
-int buffer_get_bignum_ret(Buffer *, BIGNUM *);
-int buffer_put_bignum2_ret(Buffer *, const BIGNUM *);
-int buffer_get_bignum2_ret(Buffer *, BIGNUM *);
-int buffer_get_short_ret(u_short *, Buffer *);
-int buffer_get_int_ret(u_int *, Buffer *);
-int buffer_get_int64_ret(u_int64_t *, Buffer *);
-void *buffer_get_string_ret(Buffer *, u_int *);
-char *buffer_get_cstring_ret(Buffer *, u_int *);
-const void *buffer_get_string_ptr_ret(Buffer *, u_int *);
-int buffer_get_char_ret(char *, Buffer *);
-
-#ifdef OPENSSL_HAS_ECC
-#include <openssl/ec.h>
-int buffer_put_ecpoint_ret(Buffer *, const EC_GROUP *, const EC_POINT *);
-void buffer_put_ecpoint(Buffer *, const EC_GROUP *, const EC_POINT *);
-int buffer_get_ecpoint_ret(Buffer *, const EC_GROUP *, EC_POINT *);
-void buffer_get_ecpoint(Buffer *, const EC_GROUP *, EC_POINT *);
-#endif
-
-#endif /* BUFFER_H */
-
diff --git a/buildpkg.sh.in b/buildpkg.sh.in
index 4b842b3f..4ccc5f8d 100644
--- a/buildpkg.sh.in
+++ b/buildpkg.sh.in
@@ -247,7 +247,7 @@ cat > pkginfo << _EOF
PKG=$PKGNAME
NAME="OpenSSH Portable for ${UNAME_S}"
DESC="Secure Shell remote access utility; replaces telnet and rlogin/rsh."
-VENDOR="OpenSSH Portable Team - http://www.openssh.com/portable.html"
+VENDOR="OpenSSH Portable Team - https://www.openssh.com/portable.html"
ARCH=$ARCH
VERSION=$VERSION$REV
CATEGORY="Security,application"
diff --git a/canohost.c b/canohost.c
index 223964ea..abea9c6e 100644
--- a/canohost.c
+++ b/canohost.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: canohost.c,v 1.72 2015/03/01 15:44:40 millert Exp $ */
+/* $OpenBSD: canohost.c,v 1.74 2019/06/28 13:35:04 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,147 +35,6 @@
#include "canohost.h"
#include "misc.h"
-static void check_ip_options(int, char *);
-static char *canonical_host_ip = NULL;
-static int cached_port = -1;
-
-/*
- * Return the canonical name of the host at the other end of the socket. The
- * caller should free the returned string.
- */
-
-static char *
-get_remote_hostname(int sock, int use_dns)
-{
- struct sockaddr_storage from;
- socklen_t fromlen;
- struct addrinfo hints, *ai, *aitop;
- char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
-
- /* Get IP address of client. */
- fromlen = sizeof(from);
- memset(&from, 0, sizeof(from));
- if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
- debug("getpeername failed: %.100s", strerror(errno));
- cleanup_exit(255);
- }
-
- if (from.ss_family == AF_INET)
- check_ip_options(sock, ntop);
-
- ipv64_normalise_mapped(&from, &fromlen);
-
- if (from.ss_family == AF_INET6)
- fromlen = sizeof(struct sockaddr_in6);
-
- if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
- NULL, 0, NI_NUMERICHOST) != 0)
- fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
-
- if (!use_dns)
- return xstrdup(ntop);
-
- debug3("Trying to reverse map address %.100s.", ntop);
- /* Map the IP address to a host name. */
- if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
- NULL, 0, NI_NAMEREQD) != 0) {
- /* Host name not found. Use ip address. */
- return xstrdup(ntop);
- }
-
- /*
- * if reverse lookup result looks like a numeric hostname,
- * someone is trying to trick us by PTR record like following:
- * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
- */
- memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- hints.ai_flags = AI_NUMERICHOST;
- if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
- logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
- name, ntop);
- freeaddrinfo(ai);
- return xstrdup(ntop);
- }
-
- /* Names are stores in lowercase. */
- lowercase(name);
-
- /*
- * Map it back to an IP address and check that the given
- * address actually is an address of this host. This is
- * necessary because anyone with access to a name server can
- * define arbitrary names for an IP address. Mapping from
- * name to IP address can be trusted better (but can still be
- * fooled if the intruder has access to the name server of
- * the domain).
- */
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = from.ss_family;
- hints.ai_socktype = SOCK_STREAM;
- if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
- logit("reverse mapping checking getaddrinfo for %.700s "
- "[%s] failed - POSSIBLE BREAK-IN ATTEMPT!", name, ntop);
- return xstrdup(ntop);
- }
- /* Look for the address from the list of addresses. */
- for (ai = aitop; ai; ai = ai->ai_next) {
- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
- sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
- (strcmp(ntop, ntop2) == 0))
- break;
- }
- freeaddrinfo(aitop);
- /* If we reached the end of the list, the address was not there. */
- if (!ai) {
- /* Address not found for the host name. */
- logit("Address %.100s maps to %.600s, but this does not "
- "map back to the address - POSSIBLE BREAK-IN ATTEMPT!",
- ntop, name);
- return xstrdup(ntop);
- }
- return xstrdup(name);
-}
-
-/*
- * If IP options are supported, make sure there are none (log and
- * disconnect them if any are found). Basically we are worried about
- * source routing; it can be used to pretend you are somebody
- * (ip-address) you are not. That itself may be "almost acceptable"
- * under certain circumstances, but rhosts autentication is useless
- * if source routing is accepted. Notice also that if we just dropped
- * source routing here, the other side could use IP spoofing to do
- * rest of the interaction and could still bypass security. So we
- * exit here if we detect any IP options.
- */
-/* IPv4 only */
-static void
-check_ip_options(int sock, char *ipaddr)
-{
-#ifdef IP_OPTIONS
- u_char options[200];
- char text[sizeof(options) * 3 + 1];
- socklen_t option_size, i;
- int ipproto;
- struct protoent *ip;
-
- if ((ip = getprotobyname("ip")) != NULL)
- ipproto = ip->p_proto;
- else
- ipproto = IPPROTO_IP;
- option_size = sizeof(options);
- if (getsockopt(sock, ipproto, IP_OPTIONS, options,
- &option_size) >= 0 && option_size != 0) {
- text[0] = '\0';
- for (i = 0; i < option_size; i++)
- snprintf(text + i*3, sizeof(text) - i*3,
- " %2.2x", options[i]);
- fatal("Connection from %.100s with IP options:%.800s",
- ipaddr, text);
- }
-#endif /* IP_OPTIONS */
-}
-
void
ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
{
@@ -202,38 +61,6 @@ ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
}
/*
- * Return the canonical name of the host in the other side of the current
- * connection. The host name is cached, so it is efficient to call this
- * several times.
- */
-
-const char *
-get_canonical_hostname(int use_dns)
-{
- char *host;
- static char *canonical_host_name = NULL;
- static char *remote_ip = NULL;
-
- /* Check if we have previously retrieved name with same option. */
- if (use_dns && canonical_host_name != NULL)
- return canonical_host_name;
- if (!use_dns && remote_ip != NULL)
- return remote_ip;
-
- /* Get the real hostname if socket; otherwise return UNKNOWN. */
- if (packet_connection_is_on_socket())
- host = get_remote_hostname(packet_get_connection_in(), use_dns);
- else
- host = "UNKNOWN";
-
- if (use_dns)
- canonical_host_name = host;
- else
- remote_ip = host;
- return host;
-}
-
-/*
* Returns the local/remote IP-address/hostname of socket as a string.
* The returned string must be freed.
*/
@@ -250,12 +77,10 @@ get_socket_address(int sock, int remote, int flags)
memset(&addr, 0, sizeof(addr));
if (remote) {
- if (getpeername(sock, (struct sockaddr *)&addr, &addrlen)
- < 0)
+ if (getpeername(sock, (struct sockaddr *)&addr, &addrlen) != 0)
return NULL;
} else {
- if (getsockname(sock, (struct sockaddr *)&addr, &addrlen)
- < 0)
+ if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) != 0)
return NULL;
}
@@ -271,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("get_socket_address: getnameinfo %d failed: %s",
+ error("%s: getnameinfo %d failed: %s", __func__,
flags, ssh_gai_strerror(r));
return NULL;
}
@@ -316,7 +141,8 @@ get_local_name(int fd)
/* Handle the case where we were passed a pipe */
if (gethostname(myname, sizeof(myname)) == -1) {
- verbose("get_local_name: gethostname: %s", strerror(errno));
+ verbose("%s: gethostname: %s", __func__, strerror(errno));
+ host = xstrdup("UNKNOWN");
} else {
host = xstrdup(myname);
}
@@ -324,51 +150,9 @@ get_local_name(int fd)
return host;
}
-void
-clear_cached_addr(void)
-{
- free(canonical_host_ip);
- canonical_host_ip = NULL;
- cached_port = -1;
-}
-
-/*
- * Returns the IP-address of the remote host as a string. The returned
- * string must not be freed.
- */
-
-const char *
-get_remote_ipaddr(void)
-{
- /* Check whether we have cached the ipaddr. */
- if (canonical_host_ip == NULL) {
- if (packet_connection_is_on_socket()) {
- canonical_host_ip =
- get_peer_ipaddr(packet_get_connection_in());
- if (canonical_host_ip == NULL)
- cleanup_exit(255);
- } else {
- /* If not on socket, return UNKNOWN. */
- canonical_host_ip = xstrdup("UNKNOWN");
- }
- }
- return canonical_host_ip;
-}
-
-const char *
-get_remote_name_or_ip(u_int utmp_len, int use_dns)
-{
- static const char *remote = "";
- if (utmp_len > 0)
- remote = get_canonical_hostname(use_dns);
- if (utmp_len == 0 || strlen(remote) > utmp_len)
- remote = get_remote_ipaddr();
- return remote;
-}
-
/* Returns the local/remote port for the socket. */
-int
+static int
get_sock_port(int sock, int local)
{
struct sockaddr_storage from;
@@ -380,12 +164,12 @@ get_sock_port(int sock, int local)
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (local) {
- if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
+ if (getsockname(sock, (struct sockaddr *)&from, &fromlen) == -1) {
error("getsockname failed: %.100s", strerror(errno));
return 0;
}
} else {
- if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
+ if (getpeername(sock, (struct sockaddr *)&from, &fromlen) == -1) {
debug("getpeername failed: %.100s", strerror(errno));
return -1;
}
@@ -402,27 +186,11 @@ 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("get_sock_port: getnameinfo NI_NUMERICSERV failed: %s",
+ fatal("%s: getnameinfo NI_NUMERICSERV failed: %s", __func__,
ssh_gai_strerror(r));
return atoi(strport);
}
-/* Returns remote/local port number for the current connection. */
-
-static int
-get_port(int local)
-{
- /*
- * If the connection is not a socket, return 65535. This is
- * intentionally chosen to be an unprivileged port number.
- */
- if (!packet_connection_is_on_socket())
- return 65535;
-
- /* Get socket and return the port number. */
- return get_sock_port(packet_get_connection_in(), local);
-}
-
int
get_peer_port(int sock)
{
@@ -430,17 +198,7 @@ get_peer_port(int sock)
}
int
-get_remote_port(void)
-{
- /* Cache to avoid getpeername() on a dead connection */
- if (cached_port == -1)
- cached_port = get_port(0);
-
- return cached_port;
-}
-
-int
-get_local_port(void)
+get_local_port(int sock)
{
- return get_port(1);
+ return get_sock_port(sock, 1);
}
diff --git a/canohost.h b/canohost.h
index 4c8636f4..26d62855 100644
--- a/canohost.h
+++ b/canohost.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: canohost.h,v 1.11 2009/05/27 06:31:25 andreas Exp $ */
+/* $OpenBSD: canohost.h,v 1.12 2016/03/07 19:02:43 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -12,18 +12,15 @@
* called by a name other than "ssh" or "Secure Shell".
*/
-const char *get_canonical_hostname(int);
-const char *get_remote_ipaddr(void);
-const char *get_remote_name_or_ip(u_int, int);
+#ifndef _CANOHOST_H
+#define _CANOHOST_H
char *get_peer_ipaddr(int);
int get_peer_port(int);
char *get_local_ipaddr(int);
char *get_local_name(int);
+int get_local_port(int);
-int get_remote_port(void);
-int get_local_port(void);
-int get_sock_port(int, int);
-void clear_cached_addr(void);
+#endif /* _CANOHOST_H */
void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *);
diff --git a/chacha.h b/chacha.h
index 40eaf2d9..76205256 100644
--- a/chacha.h
+++ b/chacha.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: chacha.h,v 1.3 2014/05/02 03:27:54 djm Exp $ */
+/* $OpenBSD: chacha.h,v 1.4 2016/08/27 04:04:56 guenther Exp $ */
/*
chacha-merged.c version 20080118
@@ -10,6 +10,7 @@ Public domain.
#define CHACHA_H
#include <sys/types.h>
+#include <stdlib.h>
struct chacha_ctx {
u_int input[16];
diff --git a/channels.c b/channels.c
index 9486c1cf..95a51e21 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.341 2015/02/06 23:21:59 millert Exp $ */
+/* $OpenBSD: channels.c,v 1.398 2020/04/25 06:59:36 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -42,7 +42,6 @@
#include "includes.h"
#include <sys/types.h>
-#include <sys/param.h> /* MIN MAX */
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/un.h>
@@ -56,55 +55,52 @@
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <netdb.h>
+#include <stdarg.h>
#ifdef HAVE_STDINT_H
-#include <stdint.h>
+# include <stdint.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
-#include <stdarg.h>
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
-#include "ssh1.h"
#include "ssh2.h"
+#include "ssherr.h"
+#include "sshbuf.h"
#include "packet.h"
#include "log.h"
#include "misc.h"
-#include "buffer.h"
#include "channels.h"
#include "compat.h"
#include "canohost.h"
-#include "key.h"
+#include "sshkey.h"
#include "authfd.h"
#include "pathnames.h"
+#include "match.h"
-/* -- channel core */
-
-/*
- * Pointer to an array containing all allocated channels. The array is
- * dynamically extended as needed.
- */
-static Channel **channels = NULL;
+/* -- agent forwarding */
+#define NUM_SOCKS 10
-/*
- * Size of the channel array. All slots of the array must always be
- * initialized (at least the type field); unused slots set to NULL
- */
-static u_int channels_alloc = 0;
+/* -- tcp forwarding */
+/* special-case port number meaning allow any port */
+#define FWD_PERMIT_ANY_PORT 0
-/*
- * Maximum file descriptor value used in any of the channels. This is
- * updated in channel_new.
- */
-static int channel_max_fd = 0;
+/* special-case wildcard meaning allow any host */
+#define FWD_PERMIT_ANY_HOST "*"
+/* -- X11 forwarding */
+/* Maximum number of fake X11 displays to try. */
+#define MAX_DISPLAYS 1000
-/* -- tcp forwarding */
+/* Per-channel callback for pre/post select() actions */
+typedef void chan_fn(struct ssh *, Channel *c,
+ fd_set *readset, fd_set *writeset);
/*
* Data structure for storing which hosts are permitted for forward requests.
@@ -115,119 +111,190 @@ static int channel_max_fd = 0;
/* XXX: streamlocal wants a path instead of host:port */
/* Overload host_to_connect; we could just make this match Forward */
/* XXX - can we use listen_host instead of listen_path? */
-typedef struct {
+struct permission {
char *host_to_connect; /* Connect to 'host'. */
int port_to_connect; /* Connect to 'port'. */
char *listen_host; /* Remote side should listen address. */
char *listen_path; /* Remote side should listen path. */
int listen_port; /* Remote side should listen port. */
-} ForwardPermission;
-
-/* List of all permitted host/port pairs to connect by the user. */
-static ForwardPermission *permitted_opens = NULL;
-
-/* List of all permitted host/port pairs to connect by the admin. */
-static ForwardPermission *permitted_adm_opens = NULL;
+ Channel *downstream; /* Downstream mux*/
+};
-/* Number of permitted host/port pairs in the array permitted by the user. */
-static int num_permitted_opens = 0;
+/*
+ * Stores the forwarding permission state for a single direction (local or
+ * remote).
+ */
+struct permission_set {
+ /*
+ * List of all local permitted host/port pairs to allow for the
+ * user.
+ */
+ u_int num_permitted_user;
+ struct permission *permitted_user;
-/* Number of permitted host/port pair in the array permitted by the admin. */
-static int num_adm_permitted_opens = 0;
+ /*
+ * List of all permitted host/port pairs to allow for the admin.
+ */
+ u_int num_permitted_admin;
+ struct permission *permitted_admin;
-/* special-case port number meaning allow any port */
-#define FWD_PERMIT_ANY_PORT 0
+ /*
+ * If this is true, all opens/listens are permitted. This is the
+ * case on the server on which we have to trust the client anyway,
+ * and the user could do anything after logging in.
+ */
+ int all_permitted;
+};
-/*
- * If this is true, all opens are permitted. This is the case on the server
- * on which we have to trust the client anyway, and the user could do
- * anything after logging in anyway.
- */
-static int all_opens_permitted = 0;
+/* Master structure for channels state */
+struct ssh_channels {
+ /*
+ * Pointer to an array containing all allocated channels. The array
+ * is dynamically extended as needed.
+ */
+ Channel **channels;
+ /*
+ * Size of the channel array. All slots of the array must always be
+ * initialized (at least the type field); unused slots set to NULL
+ */
+ u_int channels_alloc;
-/* -- X11 forwarding */
+ /*
+ * Maximum file descriptor value used in any of the channels. This is
+ * updated in channel_new.
+ */
+ int channel_max_fd;
-/* Maximum number of fake X11 displays to try. */
-#define MAX_DISPLAYS 1000
+ /*
+ * 'channel_pre*' are called just before select() to add any bits
+ * relevant to channels in the select bitmasks.
+ *
+ * 'channel_post*': perform any appropriate operations for
+ * channels which have events pending.
+ */
+ chan_fn **channel_pre;
+ chan_fn **channel_post;
-/* Saved X11 local (client) display. */
-static char *x11_saved_display = NULL;
+ /* -- tcp forwarding */
+ struct permission_set local_perms;
+ struct permission_set remote_perms;
-/* Saved X11 authentication protocol name. */
-static char *x11_saved_proto = NULL;
+ /* -- X11 forwarding */
-/* Saved X11 authentication data. This is the real data. */
-static char *x11_saved_data = NULL;
-static u_int x11_saved_data_len = 0;
+ /* Saved X11 local (client) display. */
+ char *x11_saved_display;
-/*
- * Fake X11 authentication data. This is what the server will be sending us;
- * we should replace any occurrences of this by the real data.
- */
-static u_char *x11_fake_data = NULL;
-static u_int x11_fake_data_len;
+ /* Saved X11 authentication protocol name. */
+ char *x11_saved_proto;
+ /* Saved X11 authentication data. This is the real data. */
+ char *x11_saved_data;
+ u_int x11_saved_data_len;
-/* -- agent forwarding */
+ /* Deadline after which all X11 connections are refused */
+ u_int x11_refuse_time;
-#define NUM_SOCKS 10
+ /*
+ * Fake X11 authentication data. This is what the server will be
+ * sending us; we should replace any occurrences of this by the
+ * real data.
+ */
+ u_char *x11_fake_data;
+ u_int x11_fake_data_len;
-/* AF_UNSPEC or AF_INET or AF_INET6 */
-static int IPv4or6 = AF_UNSPEC;
+ /* AF_UNSPEC or AF_INET or AF_INET6 */
+ int IPv4or6;
+};
/* helper */
-static void port_open_helper(Channel *c, char *rtype);
+static void port_open_helper(struct ssh *ssh, Channel *c, char *rtype);
+static const char *channel_rfwd_bind_host(const char *listen_host);
/* non-blocking connect helpers */
static int connect_next(struct channel_connect *);
static void channel_connect_ctx_free(struct channel_connect *);
+static Channel *rdynamic_connect_prepare(struct ssh *, char *, char *);
+static int rdynamic_connect_finish(struct ssh *, Channel *);
+
+/* Setup helper */
+static void channel_handler_init(struct ssh_channels *sc);
/* -- channel core */
+void
+channel_init_channels(struct ssh *ssh)
+{
+ struct ssh_channels *sc;
+
+ if ((sc = calloc(1, sizeof(*sc))) == NULL)
+ fatal("%s: allocation failed", __func__);
+ sc->channels_alloc = 10;
+ sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels));
+ sc->IPv4or6 = AF_UNSPEC;
+ channel_handler_init(sc);
+
+ ssh->chanctxt = sc;
+}
+
Channel *
-channel_by_id(int id)
+channel_by_id(struct ssh *ssh, int id)
{
Channel *c;
- if (id < 0 || (u_int)id >= channels_alloc) {
- logit("channel_by_id: %d: bad id", id);
+ if (id < 0 || (u_int)id >= ssh->chanctxt->channels_alloc) {
+ logit("%s: %d: bad id", __func__, id);
return NULL;
}
- c = channels[id];
+ c = ssh->chanctxt->channels[id];
if (c == NULL) {
- logit("channel_by_id: %d: bad id: channel free", id);
+ logit("%s: %d: bad id: channel free", __func__, id);
return NULL;
}
return c;
}
+Channel *
+channel_by_remote_id(struct ssh *ssh, u_int remote_id)
+{
+ Channel *c;
+ u_int i;
+
+ for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
+ c = ssh->chanctxt->channels[i];
+ if (c != NULL && c->have_remote_id && c->remote_id == remote_id)
+ return c;
+ }
+ return NULL;
+}
+
/*
* Returns the channel if it is allowed to receive protocol messages.
* Private channels, like listening sockets, may not receive messages.
*/
Channel *
-channel_lookup(int id)
+channel_lookup(struct ssh *ssh, int id)
{
Channel *c;
- if ((c = channel_by_id(id)) == NULL)
- return (NULL);
+ if ((c = channel_by_id(ssh, id)) == NULL)
+ return NULL;
switch (c->type) {
case SSH_CHANNEL_X11_OPEN:
case SSH_CHANNEL_LARVAL:
case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_DYNAMIC:
+ case SSH_CHANNEL_RDYNAMIC_OPEN:
+ case SSH_CHANNEL_RDYNAMIC_FINISH:
case SSH_CHANNEL_OPENING:
case SSH_CHANNEL_OPEN:
- case SSH_CHANNEL_INPUT_DRAINING:
- case SSH_CHANNEL_OUTPUT_DRAINING:
case SSH_CHANNEL_ABANDONED:
- return (c);
+ case SSH_CHANNEL_MUX_PROXY:
+ return c;
}
logit("Non-public channel %d, type %d.", id, c->type);
- return (NULL);
+ return NULL;
}
/*
@@ -235,13 +302,15 @@ channel_lookup(int id)
* when the channel consumer/producer is ready, e.g. shell exec'd
*/
static void
-channel_register_fds(Channel *c, int rfd, int wfd, int efd,
+channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd,
int extusage, int nonblock, int is_tty)
{
+ struct ssh_channels *sc = ssh->chanctxt;
+
/* Update the maximum file descriptor value. */
- channel_max_fd = MAX(channel_max_fd, rfd);
- channel_max_fd = MAX(channel_max_fd, wfd);
- channel_max_fd = MAX(channel_max_fd, efd);
+ sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, rfd);
+ sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, wfd);
+ sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, efd);
if (rfd != -1)
fcntl(rfd, F_SETFD, FD_CLOEXEC);
@@ -279,150 +348,273 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd,
* remote_name to be freed.
*/
Channel *
-channel_new(char *ctype, int type, int rfd, int wfd, int efd,
+channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd,
u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock)
{
- int found;
- u_int i;
+ struct ssh_channels *sc = ssh->chanctxt;
+ u_int i, found;
Channel *c;
- /* Do initial allocation if this is the first call. */
- if (channels_alloc == 0) {
- channels_alloc = 10;
- channels = xcalloc(channels_alloc, sizeof(Channel *));
- for (i = 0; i < channels_alloc; i++)
- channels[i] = NULL;
- }
/* Try to find a free slot where to put the new channel. */
- for (found = -1, i = 0; i < channels_alloc; i++)
- if (channels[i] == NULL) {
+ for (i = 0; i < sc->channels_alloc; i++) {
+ if (sc->channels[i] == NULL) {
/* Found a free slot. */
- found = (int)i;
+ found = i;
break;
}
- if (found < 0) {
- /* There are no free slots. Take last+1 slot and expand the array. */
- found = channels_alloc;
- if (channels_alloc > 10000)
- fatal("channel_new: internal error: channels_alloc %d "
- "too big.", channels_alloc);
- channels = xrealloc(channels, channels_alloc + 10,
- sizeof(Channel *));
- channels_alloc += 10;
- debug2("channel: expanding %d", channels_alloc);
- for (i = found; i < channels_alloc; i++)
- channels[i] = NULL;
+ }
+ if (i >= sc->channels_alloc) {
+ /*
+ * There are no free slots. Take last+1 slot and expand
+ * the array.
+ */
+ found = sc->channels_alloc;
+ if (sc->channels_alloc > CHANNELS_MAX_CHANNELS)
+ fatal("%s: internal error: channels_alloc %d too big",
+ __func__, sc->channels_alloc);
+ sc->channels = xrecallocarray(sc->channels, sc->channels_alloc,
+ sc->channels_alloc + 10, sizeof(*sc->channels));
+ sc->channels_alloc += 10;
+ debug2("channel: expanding %d", sc->channels_alloc);
}
/* Initialize and return new channel. */
- c = channels[found] = xcalloc(1, sizeof(Channel));
- buffer_init(&c->input);
- buffer_init(&c->output);
- buffer_init(&c->extended);
- c->path = NULL;
- c->listening_addr = NULL;
- c->listening_port = 0;
+ c = sc->channels[found] = xcalloc(1, sizeof(Channel));
+ if ((c->input = sshbuf_new()) == NULL ||
+ (c->output = sshbuf_new()) == NULL ||
+ (c->extended = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
c->ostate = CHAN_OUTPUT_OPEN;
c->istate = CHAN_INPUT_OPEN;
- c->flags = 0;
- channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, 0);
- c->notbefore = 0;
+ channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0);
c->self = found;
c->type = type;
c->ctype = ctype;
c->local_window = window;
c->local_window_max = window;
- c->local_consumed = 0;
c->local_maxpacket = maxpack;
- c->remote_id = -1;
c->remote_name = xstrdup(remote_name);
- c->remote_window = 0;
- c->remote_maxpacket = 0;
- c->force_drain = 0;
- c->single_connection = 0;
- c->detach_user = NULL;
- c->detach_close = 0;
- c->open_confirm = NULL;
- c->open_confirm_ctx = NULL;
- c->input_filter = NULL;
- c->output_filter = NULL;
- c->filter_ctx = NULL;
- c->filter_cleanup = NULL;
c->ctl_chan = -1;
- c->mux_rcb = NULL;
- c->mux_ctx = NULL;
- c->mux_pause = 0;
c->delayed = 1; /* prevent call to channel_post handler */
TAILQ_INIT(&c->status_confirms);
debug("channel %d: new [%s]", found, remote_name);
return c;
}
-static int
-channel_find_maxfd(void)
+static void
+channel_find_maxfd(struct ssh_channels *sc)
{
u_int i;
int max = 0;
Channel *c;
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
+ for (i = 0; i < sc->channels_alloc; i++) {
+ c = sc->channels[i];
if (c != NULL) {
- max = MAX(max, c->rfd);
- max = MAX(max, c->wfd);
- max = MAX(max, c->efd);
+ max = MAXIMUM(max, c->rfd);
+ max = MAXIMUM(max, c->wfd);
+ max = MAXIMUM(max, c->efd);
}
}
- return max;
+ sc->channel_max_fd = max;
}
int
-channel_close_fd(int *fdp)
+channel_close_fd(struct ssh *ssh, int *fdp)
{
+ struct ssh_channels *sc = ssh->chanctxt;
int ret = 0, fd = *fdp;
if (fd != -1) {
ret = close(fd);
*fdp = -1;
- if (fd == channel_max_fd)
- channel_max_fd = channel_find_maxfd();
+ if (fd == sc->channel_max_fd)
+ channel_find_maxfd(sc);
}
return ret;
}
/* Close all channel fd/socket. */
static void
-channel_close_fds(Channel *c)
+channel_close_fds(struct ssh *ssh, Channel *c)
+{
+ int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd;
+
+ channel_close_fd(ssh, &c->sock);
+ if (rfd != sock)
+ channel_close_fd(ssh, &c->rfd);
+ if (wfd != sock && wfd != rfd)
+ channel_close_fd(ssh, &c->wfd);
+ if (efd != sock && efd != rfd && efd != wfd)
+ channel_close_fd(ssh, &c->efd);
+}
+
+static void
+fwd_perm_clear(struct permission *perm)
+{
+ free(perm->host_to_connect);
+ free(perm->listen_host);
+ free(perm->listen_path);
+ memset(perm, 0, sizeof(*perm));
+}
+
+/* Returns an printable name for the specified forwarding permission list */
+static const char *
+fwd_ident(int who, int where)
+{
+ if (who == FORWARD_ADM) {
+ if (where == FORWARD_LOCAL)
+ return "admin local";
+ else if (where == FORWARD_REMOTE)
+ return "admin remote";
+ } else if (who == FORWARD_USER) {
+ if (where == FORWARD_LOCAL)
+ return "user local";
+ else if (where == FORWARD_REMOTE)
+ return "user remote";
+ }
+ fatal("Unknown forward permission list %d/%d", who, where);
+}
+
+/* Returns the forwarding permission list for the specified direction */
+static struct permission_set *
+permission_set_get(struct ssh *ssh, int where)
+{
+ struct ssh_channels *sc = ssh->chanctxt;
+
+ switch (where) {
+ case FORWARD_LOCAL:
+ return &sc->local_perms;
+ break;
+ case FORWARD_REMOTE:
+ return &sc->remote_perms;
+ break;
+ default:
+ fatal("%s: invalid forwarding direction %d", __func__, where);
+ }
+}
+
+/* Returns pointers to the specified forwarding list and its element count */
+static void
+permission_set_get_array(struct ssh *ssh, int who, int where,
+ struct permission ***permpp, u_int **npermpp)
+{
+ struct permission_set *pset = permission_set_get(ssh, where);
+
+ switch (who) {
+ case FORWARD_USER:
+ *permpp = &pset->permitted_user;
+ *npermpp = &pset->num_permitted_user;
+ break;
+ case FORWARD_ADM:
+ *permpp = &pset->permitted_admin;
+ *npermpp = &pset->num_permitted_admin;
+ break;
+ default:
+ fatal("%s: invalid forwarding client %d", __func__, who);
+ }
+}
+
+/* Adds an entry to the spcified forwarding list */
+static int
+permission_set_add(struct ssh *ssh, int who, int where,
+ const char *host_to_connect, int port_to_connect,
+ const char *listen_host, const char *listen_path, int listen_port,
+ Channel *downstream)
+{
+ struct permission **permp;
+ u_int n, *npermp;
+
+ permission_set_get_array(ssh, who, where, &permp, &npermp);
+
+ if (*npermp >= INT_MAX)
+ fatal("%s: %s overflow", __func__, fwd_ident(who, where));
+
+ *permp = xrecallocarray(*permp, *npermp, *npermp + 1, sizeof(**permp));
+ n = (*npermp)++;
+#define MAYBE_DUP(s) ((s == NULL) ? NULL : xstrdup(s))
+ (*permp)[n].host_to_connect = MAYBE_DUP(host_to_connect);
+ (*permp)[n].port_to_connect = port_to_connect;
+ (*permp)[n].listen_host = MAYBE_DUP(listen_host);
+ (*permp)[n].listen_path = MAYBE_DUP(listen_path);
+ (*permp)[n].listen_port = listen_port;
+ (*permp)[n].downstream = downstream;
+#undef MAYBE_DUP
+ return (int)n;
+}
+
+static void
+mux_remove_remote_forwardings(struct ssh *ssh, Channel *c)
{
- channel_close_fd(&c->sock);
- channel_close_fd(&c->rfd);
- channel_close_fd(&c->wfd);
- channel_close_fd(&c->efd);
+ struct ssh_channels *sc = ssh->chanctxt;
+ struct permission_set *pset = &sc->local_perms;
+ struct permission *perm;
+ int r;
+ u_int i;
+
+ for (i = 0; i < pset->num_permitted_user; i++) {
+ perm = &pset->permitted_user[i];
+ if (perm->downstream != c)
+ continue;
+
+ /* cancel on the server, since mux client is gone */
+ debug("channel %d: cleanup remote forward for %s:%u",
+ c->self, perm->listen_host, perm->listen_port);
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh,
+ "cancel-tcpip-forward")) != 0 ||
+ (r = sshpkt_put_u8(ssh, 0)) != 0 ||
+ (r = sshpkt_put_cstring(ssh,
+ channel_rfwd_bind_host(perm->listen_host))) != 0 ||
+ (r = sshpkt_put_u32(ssh, perm->listen_port)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ fatal("%s: channel %i: %s", __func__,
+ c->self, ssh_err(r));
+ }
+ fwd_perm_clear(perm); /* unregister */
+ }
}
/* Free the channel and close its fd/socket. */
void
-channel_free(Channel *c)
+channel_free(struct ssh *ssh, Channel *c)
{
+ struct ssh_channels *sc = ssh->chanctxt;
char *s;
u_int i, n;
+ Channel *other;
struct channel_confirm *cc;
- for (n = 0, i = 0; i < channels_alloc; i++)
- if (channels[i])
- n++;
+ for (n = 0, i = 0; i < sc->channels_alloc; i++) {
+ if ((other = sc->channels[i]) == NULL)
+ continue;
+ n++;
+ /* detach from mux client and prepare for closing */
+ if (c->type == SSH_CHANNEL_MUX_CLIENT &&
+ other->type == SSH_CHANNEL_MUX_PROXY &&
+ other->mux_ctx == c) {
+ other->mux_ctx = NULL;
+ other->type = SSH_CHANNEL_OPEN;
+ other->istate = CHAN_INPUT_CLOSED;
+ other->ostate = CHAN_OUTPUT_CLOSED;
+ }
+ }
debug("channel %d: free: %s, nchannels %u", c->self,
c->remote_name ? c->remote_name : "???", n);
- s = channel_open_message();
- debug3("channel %d: status: %s", c->self, s);
- free(s);
+ if (c->type == SSH_CHANNEL_MUX_CLIENT)
+ mux_remove_remote_forwardings(ssh, c);
+
+ if (log_level_get() >= SYSLOG_LEVEL_DEBUG3) {
+ s = channel_open_message(ssh);
+ debug3("channel %d: status: %s", c->self, s);
+ free(s);
+ }
- if (c->sock != -1)
- shutdown(c->sock, SHUT_RDWR);
- channel_close_fds(c);
- buffer_free(&c->input);
- buffer_free(&c->output);
- buffer_free(&c->extended);
+ channel_close_fds(ssh, c);
+ sshbuf_free(c->input);
+ sshbuf_free(c->output);
+ sshbuf_free(c->extended);
+ c->input = c->output = c->extended = NULL;
free(c->remote_name);
c->remote_name = NULL;
free(c->path);
@@ -431,25 +623,44 @@ channel_free(Channel *c)
c->listening_addr = NULL;
while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) {
if (cc->abandon_cb != NULL)
- cc->abandon_cb(c, cc->ctx);
+ cc->abandon_cb(ssh, c, cc->ctx);
TAILQ_REMOVE(&c->status_confirms, cc, entry);
- explicit_bzero(cc, sizeof(*cc));
- free(cc);
+ freezero(cc, sizeof(*cc));
}
if (c->filter_cleanup != NULL && c->filter_ctx != NULL)
- c->filter_cleanup(c->self, c->filter_ctx);
- channels[c->self] = NULL;
- free(c);
+ c->filter_cleanup(ssh, c->self, c->filter_ctx);
+ sc->channels[c->self] = NULL;
+ freezero(c, sizeof(*c));
}
void
-channel_free_all(void)
+channel_free_all(struct ssh *ssh)
{
u_int i;
+ struct ssh_channels *sc = ssh->chanctxt;
+
+ for (i = 0; i < sc->channels_alloc; i++)
+ if (sc->channels[i] != NULL)
+ channel_free(ssh, sc->channels[i]);
+
+ free(sc->channels);
+ sc->channels = NULL;
+ sc->channels_alloc = 0;
+ sc->channel_max_fd = 0;
+
+ free(sc->x11_saved_display);
+ sc->x11_saved_display = NULL;
+
+ free(sc->x11_saved_proto);
+ sc->x11_saved_proto = NULL;
- for (i = 0; i < channels_alloc; i++)
- if (channels[i] != NULL)
- channel_free(channels[i]);
+ free(sc->x11_saved_data);
+ sc->x11_saved_data = NULL;
+ sc->x11_saved_data_len = 0;
+
+ free(sc->x11_fake_data);
+ sc->x11_fake_data = NULL;
+ sc->x11_fake_data_len = 0;
}
/*
@@ -457,26 +668,26 @@ channel_free_all(void)
* descriptors after a fork.
*/
void
-channel_close_all(void)
+channel_close_all(struct ssh *ssh)
{
u_int i;
- for (i = 0; i < channels_alloc; i++)
- if (channels[i] != NULL)
- channel_close_fds(channels[i]);
+ for (i = 0; i < ssh->chanctxt->channels_alloc; i++)
+ if (ssh->chanctxt->channels[i] != NULL)
+ channel_close_fds(ssh, ssh->chanctxt->channels[i]);
}
/*
* Stop listening to channels.
*/
void
-channel_stop_listening(void)
+channel_stop_listening(struct ssh *ssh)
{
u_int i;
Channel *c;
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
+ for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
+ c = ssh->chanctxt->channels[i];
if (c != NULL) {
switch (c->type) {
case SSH_CHANNEL_AUTH_SOCKET:
@@ -485,8 +696,8 @@ channel_stop_listening(void)
case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
- channel_close_fd(&c->sock);
- channel_free(c);
+ channel_close_fd(ssh, &c->sock);
+ channel_free(ssh, c);
break;
}
}
@@ -498,28 +709,20 @@ channel_stop_listening(void)
* more channel is overfull.
*/
int
-channel_not_very_much_buffered_data(void)
+channel_not_very_much_buffered_data(struct ssh *ssh)
{
u_int i;
+ u_int maxsize = ssh_packet_get_maxsize(ssh);
Channel *c;
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
- if (c != NULL && c->type == SSH_CHANNEL_OPEN) {
-#if 0
- if (!compat20 &&
- buffer_len(&c->input) > packet_get_maxsize()) {
- debug2("channel %d: big input buffer %d",
- c->self, buffer_len(&c->input));
- return 0;
- }
-#endif
- if (buffer_len(&c->output) > packet_get_maxsize()) {
- debug2("channel %d: big output buffer %u > %u",
- c->self, buffer_len(&c->output),
- packet_get_maxsize());
- return 0;
- }
+ for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
+ c = ssh->chanctxt->channels[i];
+ if (c == NULL || c->type != SSH_CHANNEL_OPEN)
+ continue;
+ if (sshbuf_len(c->output) > maxsize) {
+ debug2("channel %d: big output buffer %zu > %u",
+ c->self, sshbuf_len(c->output), maxsize);
+ return 0;
}
}
return 1;
@@ -527,13 +730,13 @@ channel_not_very_much_buffered_data(void)
/* Returns true if any channel is still open. */
int
-channel_still_open(void)
+channel_still_open(struct ssh *ssh)
{
u_int i;
Channel *c;
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
+ for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
+ c = ssh->chanctxt->channels[i];
if (c == NULL)
continue;
switch (c->type) {
@@ -544,6 +747,7 @@ channel_still_open(void)
case SSH_CHANNEL_CLOSED:
case SSH_CHANNEL_AUTH_SOCKET:
case SSH_CHANNEL_DYNAMIC:
+ case SSH_CHANNEL_RDYNAMIC_OPEN:
case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_ZOMBIE:
case SSH_CHANNEL_ABANDONED:
@@ -551,21 +755,16 @@ channel_still_open(void)
case SSH_CHANNEL_RUNIX_LISTENER:
continue;
case SSH_CHANNEL_LARVAL:
- if (!compat20)
- fatal("cannot happen: SSH_CHANNEL_LARVAL");
continue;
case SSH_CHANNEL_OPENING:
case SSH_CHANNEL_OPEN:
+ case SSH_CHANNEL_RDYNAMIC_FINISH:
case SSH_CHANNEL_X11_OPEN:
case SSH_CHANNEL_MUX_CLIENT:
- return 1;
- case SSH_CHANNEL_INPUT_DRAINING:
- case SSH_CHANNEL_OUTPUT_DRAINING:
- if (!compat13)
- fatal("cannot happen: OUT_DRAIN");
+ case SSH_CHANNEL_MUX_PROXY:
return 1;
default:
- fatal("channel_still_open: bad channel type %d", c->type);
+ fatal("%s: bad channel type %d", __func__, c->type);
/* NOTREACHED */
}
}
@@ -574,23 +773,26 @@ channel_still_open(void)
/* Returns the id of an open channel suitable for keepaliving */
int
-channel_find_open(void)
+channel_find_open(struct ssh *ssh)
{
u_int i;
Channel *c;
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
- if (c == NULL || c->remote_id < 0)
+ for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
+ c = ssh->chanctxt->channels[i];
+ if (c == NULL || !c->have_remote_id)
continue;
switch (c->type) {
case SSH_CHANNEL_CLOSED:
case SSH_CHANNEL_DYNAMIC:
+ case SSH_CHANNEL_RDYNAMIC_OPEN:
+ case SSH_CHANNEL_RDYNAMIC_FINISH:
case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_PORT_LISTENER:
case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_MUX_LISTENER:
case SSH_CHANNEL_MUX_CLIENT:
+ case SSH_CHANNEL_MUX_PROXY:
case SSH_CHANNEL_OPENING:
case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_ZOMBIE:
@@ -603,19 +805,48 @@ channel_find_open(void)
case SSH_CHANNEL_OPEN:
case SSH_CHANNEL_X11_OPEN:
return i;
- case SSH_CHANNEL_INPUT_DRAINING:
- case SSH_CHANNEL_OUTPUT_DRAINING:
- if (!compat13)
- fatal("cannot happen: OUT_DRAIN");
- return i;
default:
- fatal("channel_find_open: bad channel type %d", c->type);
+ fatal("%s: bad channel type %d", __func__, c->type);
/* NOTREACHED */
}
}
return -1;
}
+/* Returns the state of the channel's extended usage flag */
+const char *
+channel_format_extended_usage(const Channel *c)
+{
+ if (c->efd == -1)
+ return "closed";
+
+ switch (c->extended_usage) {
+ case CHAN_EXTENDED_WRITE:
+ return "write";
+ case CHAN_EXTENDED_READ:
+ return "read";
+ case CHAN_EXTENDED_IGNORE:
+ return "ignore";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static char *
+channel_format_status(const Channel *c)
+{
+ char *ret = NULL;
+
+ xasprintf(&ret, "t%d %s%u i%u/%zu o%u/%zu e[%s]/%zu "
+ "fd %d/%d/%d sock %d cc %d",
+ c->type,
+ c->have_remote_id ? "r" : "nr", c->remote_id,
+ c->istate, sshbuf_len(c->input),
+ c->ostate, sshbuf_len(c->output),
+ channel_format_extended_usage(c), sshbuf_len(c->extended),
+ c->rfd, c->wfd, c->efd, c->sock, c->ctl_chan);
+ return ret;
+}
/*
* Returns a message describing the currently open forwarded connections,
@@ -623,18 +854,21 @@ channel_find_open(void)
* newlines.
*/
char *
-channel_open_message(void)
+channel_open_message(struct ssh *ssh)
{
- Buffer buffer;
+ struct sshbuf *buf;
Channel *c;
- char buf[1024], *cp;
u_int i;
-
- buffer_init(&buffer);
- snprintf(buf, sizeof buf, "The following connections are open:\r\n");
- buffer_append(&buffer, buf, strlen(buf));
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
+ int r;
+ char *cp, *ret;
+
+ if ((buf = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_putf(buf,
+ "The following connections are open:\r\n")) != 0)
+ fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r));
+ for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
+ c = ssh->chanctxt->channels[i];
if (c == NULL)
continue;
switch (c->type) {
@@ -645,7 +879,6 @@ channel_open_message(void)
case SSH_CHANNEL_AUTH_SOCKET:
case SSH_CHANNEL_ZOMBIE:
case SSH_CHANNEL_ABANDONED:
- case SSH_CHANNEL_MUX_CLIENT:
case SSH_CHANNEL_MUX_LISTENER:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
@@ -654,73 +887,93 @@ channel_open_message(void)
case SSH_CHANNEL_OPENING:
case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_DYNAMIC:
+ case SSH_CHANNEL_RDYNAMIC_OPEN:
+ case SSH_CHANNEL_RDYNAMIC_FINISH:
case SSH_CHANNEL_OPEN:
case SSH_CHANNEL_X11_OPEN:
- case SSH_CHANNEL_INPUT_DRAINING:
- case SSH_CHANNEL_OUTPUT_DRAINING:
- snprintf(buf, sizeof buf,
- " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d cc %d)\r\n",
- c->self, c->remote_name,
- c->type, c->remote_id,
- c->istate, buffer_len(&c->input),
- c->ostate, buffer_len(&c->output),
- c->rfd, c->wfd, c->ctl_chan);
- buffer_append(&buffer, buf, strlen(buf));
+ case SSH_CHANNEL_MUX_PROXY:
+ case SSH_CHANNEL_MUX_CLIENT:
+ cp = channel_format_status(c);
+ if ((r = sshbuf_putf(buf, " #%d %.300s (%s)\r\n",
+ c->self, c->remote_name, cp)) != 0) {
+ free(cp);
+ fatal("%s: sshbuf_putf: %s",
+ __func__, ssh_err(r));
+ }
+ free(cp);
continue;
default:
- fatal("channel_open_message: bad channel type %d", c->type);
+ fatal("%s: bad channel type %d", __func__, c->type);
/* NOTREACHED */
}
}
- buffer_append(&buffer, "\0", 1);
- cp = xstrdup((char *)buffer_ptr(&buffer));
- buffer_free(&buffer);
- return cp;
+ if ((ret = sshbuf_dup_string(buf)) == NULL)
+ fatal("%s: sshbuf_dup_string", __func__);
+ sshbuf_free(buf);
+ return ret;
+}
+
+static void
+open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type)
+{
+ int r;
+
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, type)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) {
+ fatal("%s: channel %i: open: %s", where, c->self, ssh_err(r));
+ }
}
void
-channel_send_open(int id)
+channel_send_open(struct ssh *ssh, int id)
{
- Channel *c = channel_lookup(id);
+ Channel *c = channel_lookup(ssh, id);
+ int r;
if (c == NULL) {
logit("channel_send_open: %d: bad id", id);
return;
}
debug2("channel %d: send open", id);
- packet_start(SSH2_MSG_CHANNEL_OPEN);
- packet_put_cstring(c->ctype);
- packet_put_int(c->self);
- packet_put_int(c->local_window);
- packet_put_int(c->local_maxpacket);
- packet_send();
+ open_preamble(ssh, __func__, c, c->ctype);
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
}
void
-channel_request_start(int id, char *service, int wantconfirm)
+channel_request_start(struct ssh *ssh, int id, char *service, int wantconfirm)
{
- Channel *c = channel_lookup(id);
+ Channel *c = channel_lookup(ssh, id);
+ int r;
if (c == NULL) {
- logit("channel_request_start: %d: unknown channel id", id);
+ logit("%s: %d: unknown channel id", __func__, id);
return;
}
+ if (!c->have_remote_id)
+ fatal(":%s: channel %d: no remote id", __func__, c->self);
+
debug2("channel %d: request %s confirm %d", id, service, wantconfirm);
- packet_start(SSH2_MSG_CHANNEL_REQUEST);
- packet_put_int(c->remote_id);
- packet_put_cstring(service);
- packet_put_char(wantconfirm);
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, service)) != 0 ||
+ (r = sshpkt_put_u8(ssh, wantconfirm)) != 0) {
+ fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
+ }
}
void
-channel_register_status_confirm(int id, channel_confirm_cb *cb,
- channel_confirm_abandon_cb *abandon_cb, void *ctx)
+channel_register_status_confirm(struct ssh *ssh, int id,
+ channel_confirm_cb *cb, channel_confirm_abandon_cb *abandon_cb, void *ctx)
{
struct channel_confirm *cc;
Channel *c;
- if ((c = channel_lookup(id)) == NULL)
- fatal("channel_register_expect: %d: bad id", id);
+ if ((c = channel_lookup(ssh, id)) == NULL)
+ fatal("%s: %d: bad id", __func__, id);
cc = xcalloc(1, sizeof(*cc));
cc->cb = cb;
@@ -730,12 +983,13 @@ channel_register_status_confirm(int id, channel_confirm_cb *cb,
}
void
-channel_register_open_confirm(int id, channel_open_fn *fn, void *ctx)
+channel_register_open_confirm(struct ssh *ssh, int id,
+ channel_open_fn *fn, void *ctx)
{
- Channel *c = channel_lookup(id);
+ Channel *c = channel_lookup(ssh, id);
if (c == NULL) {
- logit("channel_register_open_confirm: %d: bad id", id);
+ logit("%s: %d: bad id", __func__, id);
return;
}
c->open_confirm = fn;
@@ -743,12 +997,13 @@ channel_register_open_confirm(int id, channel_open_fn *fn, void *ctx)
}
void
-channel_register_cleanup(int id, channel_callback_fn *fn, int do_close)
+channel_register_cleanup(struct ssh *ssh, int id,
+ channel_callback_fn *fn, int do_close)
{
- Channel *c = channel_by_id(id);
+ Channel *c = channel_by_id(ssh, id);
if (c == NULL) {
- logit("channel_register_cleanup: %d: bad id", id);
+ logit("%s: %d: bad id", __func__, id);
return;
}
c->detach_user = fn;
@@ -756,12 +1011,12 @@ channel_register_cleanup(int id, channel_callback_fn *fn, int do_close)
}
void
-channel_cancel_cleanup(int id)
+channel_cancel_cleanup(struct ssh *ssh, int id)
{
- Channel *c = channel_by_id(id);
+ Channel *c = channel_by_id(ssh, id);
if (c == NULL) {
- logit("channel_cancel_cleanup: %d: bad id", id);
+ logit("%s: %d: bad id", __func__, id);
return;
}
c->detach_user = NULL;
@@ -769,13 +1024,13 @@ channel_cancel_cleanup(int id)
}
void
-channel_register_filter(int id, channel_infilter_fn *ifn,
+channel_register_filter(struct ssh *ssh, int id, channel_infilter_fn *ifn,
channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx)
{
- Channel *c = channel_lookup(id);
+ Channel *c = channel_lookup(ssh, id);
if (c == NULL) {
- logit("channel_register_filter: %d: bad id", id);
+ logit("%s: %d: bad id", __func__, id);
return;
}
c->input_filter = ifn;
@@ -785,118 +1040,80 @@ channel_register_filter(int id, channel_infilter_fn *ifn,
}
void
-channel_set_fds(int id, int rfd, int wfd, int efd,
+channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd,
int extusage, int nonblock, int is_tty, u_int window_max)
{
- Channel *c = channel_lookup(id);
+ Channel *c = channel_lookup(ssh, id);
+ int r;
if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
fatal("channel_activate for non-larval channel %d.", id);
- channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, is_tty);
+ if (!c->have_remote_id)
+ fatal(":%s: channel %d: no remote id", __func__, c->self);
+
+ channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty);
c->type = SSH_CHANNEL_OPEN;
c->local_window = c->local_window_max = window_max;
- packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
- packet_put_int(c->remote_id);
- packet_put_int(c->local_window);
- packet_send();
-}
-/*
- * 'channel_pre*' are called just before select() to add any bits relevant to
- * channels in the select bitmasks.
- */
-/*
- * 'channel_post*': perform any appropriate operations for channels which
- * have events pending.
- */
-typedef void chan_fn(Channel *c, fd_set *readset, fd_set *writeset);
-chan_fn *channel_pre[SSH_CHANNEL_MAX_TYPE];
-chan_fn *channel_post[SSH_CHANNEL_MAX_TYPE];
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
+}
-/* ARGSUSED */
static void
-channel_pre_listener(Channel *c, fd_set *readset, fd_set *writeset)
+channel_pre_listener(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
FD_SET(c->sock, readset);
}
-/* ARGSUSED */
static void
-channel_pre_connecting(Channel *c, fd_set *readset, fd_set *writeset)
+channel_pre_connecting(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
debug3("channel %d: waiting for connection", c->self);
FD_SET(c->sock, writeset);
}
static void
-channel_pre_open_13(Channel *c, fd_set *readset, fd_set *writeset)
-{
- if (buffer_len(&c->input) < packet_get_maxsize())
- FD_SET(c->sock, readset);
- if (buffer_len(&c->output) > 0)
- FD_SET(c->sock, writeset);
-}
-
-static void
-channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
+channel_pre_open(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
- u_int limit = compat20 ? c->remote_window : packet_get_maxsize();
-
if (c->istate == CHAN_INPUT_OPEN &&
- limit > 0 &&
- buffer_len(&c->input) < limit &&
- buffer_check_alloc(&c->input, CHAN_RBUF))
+ c->remote_window > 0 &&
+ sshbuf_len(c->input) < c->remote_window &&
+ sshbuf_check_reserve(c->input, CHAN_RBUF) == 0)
FD_SET(c->rfd, readset);
if (c->ostate == CHAN_OUTPUT_OPEN ||
c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
- if (buffer_len(&c->output) > 0) {
+ if (sshbuf_len(c->output) > 0) {
FD_SET(c->wfd, writeset);
} else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
if (CHANNEL_EFD_OUTPUT_ACTIVE(c))
- debug2("channel %d: obuf_empty delayed efd %d/(%d)",
- c->self, c->efd, buffer_len(&c->extended));
+ debug2("channel %d: "
+ "obuf_empty delayed efd %d/(%zu)", c->self,
+ c->efd, sshbuf_len(c->extended));
else
- chan_obuf_empty(c);
+ chan_obuf_empty(ssh, c);
}
}
/** XXX check close conditions, too */
- if (compat20 && c->efd != -1 &&
- !(c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED)) {
+ if (c->efd != -1 && !(c->istate == CHAN_INPUT_CLOSED &&
+ c->ostate == CHAN_OUTPUT_CLOSED)) {
if (c->extended_usage == CHAN_EXTENDED_WRITE &&
- buffer_len(&c->extended) > 0)
+ sshbuf_len(c->extended) > 0)
FD_SET(c->efd, writeset);
else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) &&
(c->extended_usage == CHAN_EXTENDED_READ ||
c->extended_usage == CHAN_EXTENDED_IGNORE) &&
- buffer_len(&c->extended) < c->remote_window)
+ sshbuf_len(c->extended) < c->remote_window)
FD_SET(c->efd, readset);
}
/* XXX: What about efd? races? */
}
-/* ARGSUSED */
-static void
-channel_pre_input_draining(Channel *c, fd_set *readset, fd_set *writeset)
-{
- if (buffer_len(&c->input) == 0) {
- packet_start(SSH_MSG_CHANNEL_CLOSE);
- packet_put_int(c->remote_id);
- packet_send();
- c->type = SSH_CHANNEL_CLOSED;
- debug2("channel %d: closing after input drain.", c->self);
- }
-}
-
-/* ARGSUSED */
-static void
-channel_pre_output_draining(Channel *c, fd_set *readset, fd_set *writeset)
-{
- if (buffer_len(&c->output) == 0)
- chan_mark_dead(c);
- else
- FD_SET(c->sock, writeset);
-}
-
/*
* This is a special state for X11 authentication spoofing. An opened X11
* connection (when authentication spoofing is being done) remains in this
@@ -907,17 +1124,26 @@ channel_pre_output_draining(Channel *c, fd_set *readset, fd_set *writeset)
* Returns: 0 = need more data, -1 = wrong cookie, 1 = ok
*/
static int
-x11_open_helper(Buffer *b)
+x11_open_helper(struct ssh *ssh, struct sshbuf *b)
{
+ struct ssh_channels *sc = ssh->chanctxt;
u_char *ucp;
u_int proto_len, data_len;
+ /* Is this being called after the refusal deadline? */
+ if (sc->x11_refuse_time != 0 &&
+ (u_int)monotime() >= sc->x11_refuse_time) {
+ verbose("Rejected X11 connection after ForwardX11Timeout "
+ "expired");
+ return -1;
+ }
+
/* Check if the fixed size part of the packet is in buffer. */
- if (buffer_len(b) < 12)
+ if (sshbuf_len(b) < 12)
return 0;
/* Parse the lengths of variable-length fields. */
- ucp = buffer_ptr(b);
+ ucp = sshbuf_mutable_ptr(b);
if (ucp[0] == 0x42) { /* Byte order MSB first. */
proto_len = 256 * ucp[6] + ucp[7];
data_len = 256 * ucp[8] + ucp[9];
@@ -931,27 +1157,27 @@ x11_open_helper(Buffer *b)
}
/* Check if the whole packet is in buffer. */
- if (buffer_len(b) <
+ if (sshbuf_len(b) <
12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3))
return 0;
/* Check if authentication protocol matches. */
- if (proto_len != strlen(x11_saved_proto) ||
- memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) {
+ if (proto_len != strlen(sc->x11_saved_proto) ||
+ memcmp(ucp + 12, sc->x11_saved_proto, proto_len) != 0) {
debug2("X11 connection uses different authentication protocol.");
return -1;
}
/* Check if authentication data matches our fake data. */
- if (data_len != x11_fake_data_len ||
+ if (data_len != sc->x11_fake_data_len ||
timingsafe_bcmp(ucp + 12 + ((proto_len + 3) & ~3),
- x11_fake_data, x11_fake_data_len) != 0) {
+ sc->x11_fake_data, sc->x11_fake_data_len) != 0) {
debug2("X11 auth data does not match fake data.");
return -1;
}
/* Check fake data length */
- if (x11_fake_data_len != x11_saved_data_len) {
+ if (sc->x11_fake_data_len != sc->x11_saved_data_len) {
error("X11 fake_data_len %d != saved_data_len %d",
- x11_fake_data_len, x11_saved_data_len);
+ sc->x11_fake_data_len, sc->x11_saved_data_len);
return -1;
}
/*
@@ -960,90 +1186,63 @@ x11_open_helper(Buffer *b)
* data.
*/
memcpy(ucp + 12 + ((proto_len + 3) & ~3),
- x11_saved_data, x11_saved_data_len);
+ sc->x11_saved_data, sc->x11_saved_data_len);
return 1;
}
static void
-channel_pre_x11_open_13(Channel *c, fd_set *readset, fd_set *writeset)
+channel_pre_x11_open(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
- int ret = x11_open_helper(&c->output);
-
- if (ret == 1) {
- /* Start normal processing for the channel. */
- c->type = SSH_CHANNEL_OPEN;
- channel_pre_open_13(c, readset, writeset);
- } else if (ret == -1) {
- /*
- * We have received an X11 connection that has bad
- * authentication information.
- */
- logit("X11 connection rejected because of wrong authentication.");
- buffer_clear(&c->input);
- buffer_clear(&c->output);
- channel_close_fd(&c->sock);
- c->sock = -1;
- c->type = SSH_CHANNEL_CLOSED;
- packet_start(SSH_MSG_CHANNEL_CLOSE);
- packet_put_int(c->remote_id);
- packet_send();
- }
-}
-
-static void
-channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset)
-{
- int ret = x11_open_helper(&c->output);
+ int ret = x11_open_helper(ssh, c->output);
/* c->force_drain = 1; */
if (ret == 1) {
c->type = SSH_CHANNEL_OPEN;
- channel_pre_open(c, readset, writeset);
+ channel_pre_open(ssh, c, readset, writeset);
} else if (ret == -1) {
logit("X11 connection rejected because of wrong authentication.");
- debug2("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate);
- chan_read_failed(c);
- buffer_clear(&c->input);
- chan_ibuf_empty(c);
- buffer_clear(&c->output);
- /* for proto v1, the peer will send an IEOF */
- if (compat20)
- chan_write_failed(c);
- else
- c->type = SSH_CHANNEL_OPEN;
+ debug2("X11 rejected %d i%d/o%d",
+ c->self, c->istate, c->ostate);
+ chan_read_failed(ssh, c);
+ sshbuf_reset(c->input);
+ chan_ibuf_empty(ssh, c);
+ sshbuf_reset(c->output);
+ chan_write_failed(ssh, c);
debug2("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate);
}
}
static void
-channel_pre_mux_client(Channel *c, fd_set *readset, fd_set *writeset)
+channel_pre_mux_client(struct ssh *ssh,
+ Channel *c, fd_set *readset, fd_set *writeset)
{
if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause &&
- buffer_check_alloc(&c->input, CHAN_RBUF))
+ sshbuf_check_reserve(c->input, CHAN_RBUF) == 0)
FD_SET(c->rfd, readset);
if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
/* clear buffer immediately (discard any partial packet) */
- buffer_clear(&c->input);
- chan_ibuf_empty(c);
+ sshbuf_reset(c->input);
+ chan_ibuf_empty(ssh, c);
/* Start output drain. XXX just kill chan? */
- chan_rcvd_oclose(c);
+ chan_rcvd_oclose(ssh, c);
}
if (c->ostate == CHAN_OUTPUT_OPEN ||
c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
- if (buffer_len(&c->output) > 0)
+ if (sshbuf_len(c->output) > 0)
FD_SET(c->wfd, writeset);
else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN)
- chan_obuf_empty(c);
+ chan_obuf_empty(ssh, c);
}
}
/* try to decode a socks4 header */
-/* ARGSUSED */
static int
-channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
+channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output)
{
- char *p, *host;
+ const u_char *p;
+ char *host;
u_int len, have, i, found, need;
char username[256];
struct {
@@ -1052,14 +1251,15 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
u_int16_t dest_port;
struct in_addr dest_addr;
} s4_req, s4_rsp;
+ int r;
debug2("channel %d: decode socks4", c->self);
- have = buffer_len(&c->input);
+ have = sshbuf_len(input);
len = sizeof(s4_req);
if (have < len)
return 0;
- p = (char *)buffer_ptr(&c->input);
+ p = sshbuf_ptr(input);
need = 1;
/* SOCKS4A uses an invalid IP address 0.0.0.x */
@@ -1084,46 +1284,55 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
}
if (found < need)
return 0;
- buffer_get(&c->input, (char *)&s4_req.version, 1);
- buffer_get(&c->input, (char *)&s4_req.command, 1);
- buffer_get(&c->input, (char *)&s4_req.dest_port, 2);
- buffer_get(&c->input, (char *)&s4_req.dest_addr, 4);
- have = buffer_len(&c->input);
- p = (char *)buffer_ptr(&c->input);
- if (memchr(p, '\0', have) == NULL)
- fatal("channel %d: decode socks4: user not nul terminated",
+ if ((r = sshbuf_get(input, &s4_req.version, 1)) != 0 ||
+ (r = sshbuf_get(input, &s4_req.command, 1)) != 0 ||
+ (r = sshbuf_get(input, &s4_req.dest_port, 2)) != 0 ||
+ (r = sshbuf_get(input, &s4_req.dest_addr, 4)) != 0) {
+ debug("channels %d: decode socks4: %s", c->self, ssh_err(r));
+ return -1;
+ }
+ have = sshbuf_len(input);
+ p = sshbuf_ptr(input);
+ if (memchr(p, '\0', have) == NULL) {
+ error("channel %d: decode socks4: user not nul terminated",
c->self);
+ return -1;
+ }
len = strlen(p);
debug2("channel %d: decode socks4: user %s/%d", c->self, p, len);
- len++; /* trailing '\0' */
- if (len > have)
- fatal("channel %d: decode socks4: len %d > have %d",
- c->self, len, have);
+ len++; /* trailing '\0' */
strlcpy(username, p, sizeof(username));
- buffer_consume(&c->input, len);
-
+ if ((r = sshbuf_consume(input, len)) != 0) {
+ fatal("%s: channel %d: consume: %s", __func__,
+ c->self, ssh_err(r));
+ }
free(c->path);
c->path = NULL;
if (need == 1) { /* SOCKS4: one string */
host = inet_ntoa(s4_req.dest_addr);
c->path = xstrdup(host);
} else { /* SOCKS4A: two strings */
- have = buffer_len(&c->input);
- p = (char *)buffer_ptr(&c->input);
+ have = sshbuf_len(input);
+ p = sshbuf_ptr(input);
+ if (memchr(p, '\0', have) == NULL) {
+ error("channel %d: decode socks4a: host not nul "
+ "terminated", c->self);
+ return -1;
+ }
len = strlen(p);
debug2("channel %d: decode socks4a: host %s/%d",
c->self, p, len);
len++; /* trailing '\0' */
- if (len > have)
- fatal("channel %d: decode socks4a: len %d > have %d",
- c->self, len, have);
if (len > NI_MAXHOST) {
error("channel %d: hostname \"%.100s\" too long",
c->self, p);
return -1;
}
c->path = xstrdup(p);
- buffer_consume(&c->input, len);
+ if ((r = sshbuf_consume(input, len)) != 0) {
+ fatal("%s: channel %d: consume: %s", __func__,
+ c->self, ssh_err(r));
+ }
}
c->host_port = ntohs(s4_req.dest_port);
@@ -1139,7 +1348,10 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
s4_rsp.command = 90; /* cd: req granted */
s4_rsp.dest_port = 0; /* ignored */
s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */
- buffer_append(&c->output, &s4_rsp, sizeof(s4_rsp));
+ if ((r = sshbuf_put(output, &s4_rsp, sizeof(s4_rsp))) != 0) {
+ fatal("%s: channel %d: append reply: %s", __func__,
+ c->self, ssh_err(r));
+ }
return 1;
}
@@ -1152,10 +1364,10 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
#define SSH_SOCKS5_CONNECT 0x01
#define SSH_SOCKS5_SUCCESS 0x00
-/* ARGSUSED */
static int
-channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset)
+channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output)
{
+ /* XXX use get/put_u8 instead of trusting struct padding */
struct {
u_int8_t version;
u_int8_t command;
@@ -1164,14 +1376,15 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset)
} s5_req, s5_rsp;
u_int16_t dest_port;
char dest_addr[255+1], ntop[INET6_ADDRSTRLEN];
- u_char *p;
+ const u_char *p;
u_int have, need, i, found, nmethods, addrlen, af;
+ int r;
debug2("channel %d: decode socks5", c->self);
- p = buffer_ptr(&c->input);
+ p = sshbuf_ptr(input);
if (p[0] != 0x05)
return -1;
- have = buffer_len(&c->input);
+ have = sshbuf_len(input);
if (!(c->flags & SSH_SOCKS5_AUTHDONE)) {
/* format: ver | nmethods | methods */
if (have < 2)
@@ -1191,10 +1404,16 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset)
c->self);
return -1;
}
- buffer_consume(&c->input, nmethods + 2);
- buffer_put_char(&c->output, 0x05); /* version */
- buffer_put_char(&c->output, SSH_SOCKS5_NOAUTH); /* method */
- FD_SET(c->sock, writeset);
+ if ((r = sshbuf_consume(input, nmethods + 2)) != 0) {
+ fatal("%s: channel %d: consume: %s", __func__,
+ c->self, ssh_err(r));
+ }
+ /* version, method */
+ if ((r = sshbuf_put_u8(output, 0x05)) != 0 ||
+ (r = sshbuf_put_u8(output, SSH_SOCKS5_NOAUTH)) != 0) {
+ fatal("%s: channel %d: append reply: %s", __func__,
+ c->self, ssh_err(r));
+ }
c->flags |= SSH_SOCKS5_AUTHDONE;
debug2("channel %d: socks5 auth done", c->self);
return 0; /* need more */
@@ -1231,11 +1450,22 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset)
need++;
if (have < need)
return 0;
- buffer_consume(&c->input, sizeof(s5_req));
- if (s5_req.atyp == SSH_SOCKS5_DOMAIN)
- buffer_consume(&c->input, 1); /* host string length */
- buffer_get(&c->input, &dest_addr, addrlen);
- buffer_get(&c->input, (char *)&dest_port, 2);
+ if ((r = sshbuf_consume(input, sizeof(s5_req))) != 0) {
+ fatal("%s: channel %d: consume: %s", __func__,
+ c->self, ssh_err(r));
+ }
+ if (s5_req.atyp == SSH_SOCKS5_DOMAIN) {
+ /* host string length */
+ if ((r = sshbuf_consume(input, 1)) != 0) {
+ fatal("%s: channel %d: consume: %s", __func__,
+ c->self, ssh_err(r));
+ }
+ }
+ if ((r = sshbuf_get(input, &dest_addr, addrlen)) != 0 ||
+ (r = sshbuf_get(input, &dest_port, 2)) != 0) {
+ debug("channel %d: parse addr/port: %s", c->self, ssh_err(r));
+ return -1;
+ }
dest_addr[addrlen] = '\0';
free(c->path);
c->path = NULL;
@@ -1262,22 +1492,23 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset)
s5_rsp.atyp = SSH_SOCKS5_IPV4;
dest_port = 0; /* ignored */
- buffer_append(&c->output, &s5_rsp, sizeof(s5_rsp));
- buffer_put_int(&c->output, ntohl(INADDR_ANY)); /* bind address */
- buffer_append(&c->output, &dest_port, sizeof(dest_port));
+ if ((r = sshbuf_put(output, &s5_rsp, sizeof(s5_rsp))) != 0 ||
+ (r = sshbuf_put_u32(output, ntohl(INADDR_ANY))) != 0 ||
+ (r = sshbuf_put(output, &dest_port, sizeof(dest_port))) != 0)
+ fatal("%s: channel %d: append reply: %s", __func__,
+ c->self, ssh_err(r));
return 1;
}
Channel *
-channel_connect_stdio_fwd(const char *host_to_connect, u_short port_to_connect,
- int in, int out)
+channel_connect_stdio_fwd(struct ssh *ssh,
+ const char *host_to_connect, u_short port_to_connect, int in, int out)
{
Channel *c;
- debug("channel_connect_stdio_fwd %s:%d", host_to_connect,
- port_to_connect);
+ debug("%s %s:%d", __func__, host_to_connect, port_to_connect);
- c = channel_new("stdio-forward", SSH_CHANNEL_OPENING, in, out,
+ 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);
@@ -1286,23 +1517,24 @@ channel_connect_stdio_fwd(const char *host_to_connect, u_short port_to_connect,
c->listening_port = 0;
c->force_drain = 1;
- channel_register_fds(c, in, out, -1, 0, 1, 0);
- port_open_helper(c, "direct-tcpip");
+ channel_register_fds(ssh, c, in, out, -1, 0, 1, 0);
+ port_open_helper(ssh, c, "direct-tcpip");
return c;
}
/* dynamic port forwarding */
static void
-channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset)
+channel_pre_dynamic(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
- u_char *p;
+ const u_char *p;
u_int have;
int ret;
- have = buffer_len(&c->input);
+ have = sshbuf_len(c->input);
debug2("channel %d: pre_dynamic: have %d", c->self, have);
- /* buffer_dump(&c->input); */
+ /* sshbuf_dump(c->input, stderr); */
/* check if the fixed size part of the packet is in buffer. */
if (have < 3) {
/* need more */
@@ -1310,105 +1542,169 @@ channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset)
return;
}
/* try to guess the protocol */
- p = buffer_ptr(&c->input);
+ p = sshbuf_ptr(c->input);
+ /* XXX sshbuf_peek_u8? */
switch (p[0]) {
case 0x04:
- ret = channel_decode_socks4(c, readset, writeset);
+ ret = channel_decode_socks4(c, c->input, c->output);
break;
case 0x05:
- ret = channel_decode_socks5(c, readset, writeset);
+ ret = channel_decode_socks5(c, c->input, c->output);
break;
default:
ret = -1;
break;
}
if (ret < 0) {
- chan_mark_dead(c);
+ chan_mark_dead(ssh, c);
} else if (ret == 0) {
debug2("channel %d: pre_dynamic: need more", c->self);
/* need more */
FD_SET(c->sock, readset);
+ if (sshbuf_len(c->output))
+ FD_SET(c->sock, writeset);
} else {
/* switch to the next state */
c->type = SSH_CHANNEL_OPENING;
- port_open_helper(c, "direct-tcpip");
+ port_open_helper(ssh, c, "direct-tcpip");
+ }
+}
+
+/* simulate read-error */
+static void
+rdynamic_close(struct ssh *ssh, Channel *c)
+{
+ c->type = SSH_CHANNEL_OPEN;
+ chan_read_failed(ssh, c);
+ sshbuf_reset(c->input);
+ chan_ibuf_empty(ssh, c);
+ sshbuf_reset(c->output);
+ chan_write_failed(ssh, c);
+}
+
+/* reverse dynamic port forwarding */
+static void
+channel_before_prepare_select_rdynamic(struct ssh *ssh, Channel *c)
+{
+ const u_char *p;
+ u_int have, len;
+ int r, ret;
+
+ have = sshbuf_len(c->output);
+ debug2("channel %d: pre_rdynamic: have %d", c->self, have);
+ /* sshbuf_dump(c->output, stderr); */
+ /* EOF received */
+ if (c->flags & CHAN_EOF_RCVD) {
+ if ((r = sshbuf_consume(c->output, have)) != 0) {
+ fatal("%s: channel %d: consume: %s",
+ __func__, c->self, ssh_err(r));
+ }
+ rdynamic_close(ssh, c);
+ return;
+ }
+ /* check if the fixed size part of the packet is in buffer. */
+ if (have < 3)
+ return;
+ /* try to guess the protocol */
+ p = sshbuf_ptr(c->output);
+ switch (p[0]) {
+ case 0x04:
+ /* switch input/output for reverse forwarding */
+ ret = channel_decode_socks4(c, c->output, c->input);
+ break;
+ case 0x05:
+ ret = channel_decode_socks5(c, c->output, c->input);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ if (ret < 0) {
+ rdynamic_close(ssh, c);
+ } else if (ret == 0) {
+ debug2("channel %d: pre_rdynamic: need more", c->self);
+ /* send socks request to peer */
+ len = sshbuf_len(c->input);
+ if (len > 0 && len < c->remote_window) {
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_stringb(ssh, c->input)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ fatal("%s: channel %i: rdynamic: %s", __func__,
+ c->self, ssh_err(r));
+ }
+ if ((r = sshbuf_consume(c->input, len)) != 0) {
+ fatal("%s: channel %d: consume: %s",
+ __func__, c->self, ssh_err(r));
+ }
+ c->remote_window -= len;
+ }
+ } else if (rdynamic_connect_finish(ssh, c) < 0) {
+ /* the connect failed */
+ rdynamic_close(ssh, c);
}
}
/* This is our fake X11 server socket. */
-/* ARGSUSED */
static void
-channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
+channel_post_x11_listener(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
Channel *nc;
struct sockaddr_storage addr;
- int newsock, oerrno;
+ int r, newsock, oerrno, remote_port;
socklen_t addrlen;
char buf[16384], *remote_ipaddr;
- int remote_port;
-
- if (FD_ISSET(c->sock, readset)) {
- debug("X11 connection requested.");
- addrlen = sizeof(addr);
- newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
- if (c->single_connection) {
- oerrno = errno;
- debug2("single_connection: closing X11 listener.");
- channel_close_fd(&c->sock);
- chan_mark_dead(c);
- errno = oerrno;
- }
- if (newsock < 0) {
- if (errno != EINTR && errno != EWOULDBLOCK &&
- errno != ECONNABORTED)
- error("accept: %.100s", strerror(errno));
- if (errno == EMFILE || errno == ENFILE)
- c->notbefore = monotime() + 1;
- return;
- }
- set_nodelay(newsock);
- remote_ipaddr = get_peer_ipaddr(newsock);
- remote_port = get_peer_port(newsock);
- snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",
- remote_ipaddr, remote_port);
-
- nc = channel_new("accepted x11 socket",
- SSH_CHANNEL_OPENING, newsock, newsock, -1,
- c->local_window_max, c->local_maxpacket, 0, buf, 1);
- if (compat20) {
- packet_start(SSH2_MSG_CHANNEL_OPEN);
- packet_put_cstring("x11");
- packet_put_int(nc->self);
- packet_put_int(nc->local_window_max);
- packet_put_int(nc->local_maxpacket);
- /* originator ipaddr and port */
- packet_put_cstring(remote_ipaddr);
- if (datafellows & SSH_BUG_X11FWD) {
- debug2("ssh2 x11 bug compat mode");
- } else {
- packet_put_int(remote_port);
- }
- packet_send();
- } else {
- packet_start(SSH_SMSG_X11_OPEN);
- packet_put_int(nc->self);
- if (packet_get_protocol_flags() &
- SSH_PROTOFLAG_HOST_IN_FWD_OPEN)
- packet_put_cstring(buf);
- packet_send();
- }
- free(remote_ipaddr);
+
+ if (!FD_ISSET(c->sock, readset))
+ return;
+
+ debug("X11 connection requested.");
+ addrlen = sizeof(addr);
+ newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
+ if (c->single_connection) {
+ oerrno = errno;
+ debug2("single_connection: closing X11 listener.");
+ channel_close_fd(ssh, &c->sock);
+ chan_mark_dead(ssh, c);
+ errno = oerrno;
+ }
+ if (newsock == -1) {
+ if (errno != EINTR && errno != EWOULDBLOCK &&
+ errno != ECONNABORTED)
+ error("accept: %.100s", strerror(errno));
+ if (errno == EMFILE || errno == ENFILE)
+ c->notbefore = monotime() + 1;
+ return;
}
+ set_nodelay(newsock);
+ remote_ipaddr = get_peer_ipaddr(newsock);
+ remote_port = get_peer_port(newsock);
+ snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",
+ remote_ipaddr, remote_port);
+
+ nc = channel_new(ssh, "accepted x11 socket",
+ SSH_CHANNEL_OPENING, newsock, newsock, -1,
+ c->local_window_max, c->local_maxpacket, 0, buf, 1);
+ open_preamble(ssh, __func__, nc, "x11");
+ if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 ||
+ (r = sshpkt_put_u32(ssh, remote_port)) != 0) {
+ fatal("%s: channel %i: reply %s", __func__,
+ c->self, ssh_err(r));
+ }
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r));
+ free(remote_ipaddr);
}
static void
-port_open_helper(Channel *c, char *rtype)
+port_open_helper(struct ssh *ssh, Channel *c, char *rtype)
{
- char buf[1024];
char *local_ipaddr = get_local_ipaddr(c->sock);
- int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);
+ int local_port = c->sock == -1 ? 65536 : get_local_port(c->sock);
char *remote_ipaddr = get_peer_ipaddr(c->sock);
int remote_port = get_peer_port(c->sock);
+ int r;
if (remote_port == -1) {
/* Fake addr/port to appease peers that validate it (Tectia) */
@@ -1417,78 +1713,73 @@ port_open_helper(Channel *c, char *rtype)
remote_port = 65535;
}
- snprintf(buf, sizeof buf,
+ free(c->remote_name);
+ xasprintf(&c->remote_name,
"%s: listening port %d for %.100s port %d, "
"connect from %.200s port %d to %.100s port %d",
rtype, c->listening_port, c->path, c->host_port,
remote_ipaddr, remote_port, local_ipaddr, local_port);
- free(c->remote_name);
- c->remote_name = xstrdup(buf);
-
- if (compat20) {
- packet_start(SSH2_MSG_CHANNEL_OPEN);
- packet_put_cstring(rtype);
- packet_put_int(c->self);
- packet_put_int(c->local_window_max);
- packet_put_int(c->local_maxpacket);
- if (strcmp(rtype, "direct-tcpip") == 0) {
- /* target host, port */
- packet_put_cstring(c->path);
- packet_put_int(c->host_port);
- } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
- /* target path */
- packet_put_cstring(c->path);
- } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
- /* listen path */
- packet_put_cstring(c->path);
- } else {
- /* listen address, port */
- packet_put_cstring(c->path);
- packet_put_int(local_port);
+ open_preamble(ssh, __func__, c, rtype);
+ if (strcmp(rtype, "direct-tcpip") == 0) {
+ /* target host, port */
+ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->host_port)) != 0) {
+ fatal("%s: channel %i: reply %s", __func__,
+ c->self, ssh_err(r));
}
- if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
- /* reserved for future owner/mode info */
- packet_put_cstring("");
- } else {
- /* originator host and port */
- packet_put_cstring(remote_ipaddr);
- packet_put_int((u_int)remote_port);
+ } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
+ /* target path */
+ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) {
+ fatal("%s: channel %i: reply %s", __func__,
+ c->self, ssh_err(r));
+ }
+ } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
+ /* listen path */
+ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) {
+ fatal("%s: channel %i: reply %s", __func__,
+ c->self, ssh_err(r));
}
- packet_send();
} else {
- packet_start(SSH_MSG_PORT_OPEN);
- packet_put_int(c->self);
- packet_put_cstring(c->path);
- packet_put_int(c->host_port);
- if (packet_get_protocol_flags() &
- SSH_PROTOFLAG_HOST_IN_FWD_OPEN)
- packet_put_cstring(c->remote_name);
- packet_send();
+ /* listen address, port */
+ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 ||
+ (r = sshpkt_put_u32(ssh, local_port)) != 0) {
+ fatal("%s: channel %i: reply %s", __func__,
+ c->self, ssh_err(r));
+ }
+ }
+ if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
+ /* reserved for future owner/mode info */
+ if ((r = sshpkt_put_cstring(ssh, "")) != 0) {
+ fatal("%s: channel %i: reply %s", __func__,
+ c->self, ssh_err(r));
+ }
+ } else {
+ /* originator host and port */
+ if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 ||
+ (r = sshpkt_put_u32(ssh, (u_int)remote_port)) != 0) {
+ fatal("%s: channel %i: reply %s", __func__,
+ c->self, ssh_err(r));
+ }
}
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r));
free(remote_ipaddr);
free(local_ipaddr);
}
-static void
-channel_set_reuseaddr(int fd)
+void
+channel_set_x11_refuse_time(struct ssh *ssh, u_int refuse_time)
{
- int on = 1;
-
- /*
- * Set socket options.
- * Allow local port reuse in TIME_WAIT.
- */
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
- error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno));
+ ssh->chanctxt->x11_refuse_time = refuse_time;
}
/*
* This socket is listening for connections to a forwarded TCP/IP port.
*/
-/* ARGSUSED */
static void
-channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
+channel_post_port_listener(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
Channel *nc;
struct sockaddr_storage addr;
@@ -1496,360 +1787,406 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
socklen_t addrlen;
char *rtype;
- if (FD_ISSET(c->sock, readset)) {
- debug("Connection to port %d forwarding "
- "to %.100s port %d requested.",
- c->listening_port, c->path, c->host_port);
-
- if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
- nextstate = SSH_CHANNEL_OPENING;
- rtype = "forwarded-tcpip";
- } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) {
- nextstate = SSH_CHANNEL_OPENING;
- rtype = "forwarded-streamlocal@openssh.com";
- } else if (c->host_port == PORT_STREAMLOCAL) {
- nextstate = SSH_CHANNEL_OPENING;
- rtype = "direct-streamlocal@openssh.com";
- } else if (c->host_port == 0) {
- nextstate = SSH_CHANNEL_DYNAMIC;
- rtype = "dynamic-tcpip";
- } else {
- nextstate = SSH_CHANNEL_OPENING;
- rtype = "direct-tcpip";
- }
+ if (!FD_ISSET(c->sock, readset))
+ return;
- addrlen = sizeof(addr);
- newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
- if (newsock < 0) {
- if (errno != EINTR && errno != EWOULDBLOCK &&
- errno != ECONNABORTED)
- error("accept: %.100s", strerror(errno));
- if (errno == EMFILE || errno == ENFILE)
- c->notbefore = monotime() + 1;
- return;
- }
- if (c->host_port != PORT_STREAMLOCAL)
- set_nodelay(newsock);
- nc = channel_new(rtype, nextstate, newsock, newsock, -1,
- c->local_window_max, c->local_maxpacket, 0, rtype, 1);
- nc->listening_port = c->listening_port;
- nc->host_port = c->host_port;
- if (c->path != NULL)
- nc->path = xstrdup(c->path);
+ debug("Connection to port %d forwarding to %.100s port %d requested.",
+ c->listening_port, c->path, c->host_port);
+
+ if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
+ nextstate = SSH_CHANNEL_OPENING;
+ rtype = "forwarded-tcpip";
+ } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) {
+ nextstate = SSH_CHANNEL_OPENING;
+ rtype = "forwarded-streamlocal@openssh.com";
+ } else if (c->host_port == PORT_STREAMLOCAL) {
+ nextstate = SSH_CHANNEL_OPENING;
+ rtype = "direct-streamlocal@openssh.com";
+ } else if (c->host_port == 0) {
+ nextstate = SSH_CHANNEL_DYNAMIC;
+ rtype = "dynamic-tcpip";
+ } else {
+ nextstate = SSH_CHANNEL_OPENING;
+ rtype = "direct-tcpip";
+ }
- if (nextstate != SSH_CHANNEL_DYNAMIC)
- port_open_helper(nc, rtype);
+ addrlen = sizeof(addr);
+ newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
+ if (newsock == -1) {
+ if (errno != EINTR && errno != EWOULDBLOCK &&
+ errno != ECONNABORTED)
+ error("accept: %.100s", strerror(errno));
+ if (errno == EMFILE || errno == ENFILE)
+ c->notbefore = monotime() + 1;
+ return;
}
+ if (c->host_port != PORT_STREAMLOCAL)
+ set_nodelay(newsock);
+ nc = channel_new(ssh, rtype, nextstate, newsock, newsock, -1,
+ c->local_window_max, c->local_maxpacket, 0, rtype, 1);
+ nc->listening_port = c->listening_port;
+ nc->host_port = c->host_port;
+ if (c->path != NULL)
+ nc->path = xstrdup(c->path);
+
+ if (nextstate != SSH_CHANNEL_DYNAMIC)
+ port_open_helper(ssh, nc, rtype);
}
/*
* This is the authentication agent socket listening for connections from
* clients.
*/
-/* ARGSUSED */
static void
-channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset)
+channel_post_auth_listener(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
Channel *nc;
- int newsock;
+ int r, newsock;
struct sockaddr_storage addr;
socklen_t addrlen;
- if (FD_ISSET(c->sock, readset)) {
- addrlen = sizeof(addr);
- newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
- if (newsock < 0) {
- error("accept from auth socket: %.100s",
- strerror(errno));
- if (errno == EMFILE || errno == ENFILE)
- c->notbefore = monotime() + 1;
- return;
- }
- nc = channel_new("accepted auth socket",
- SSH_CHANNEL_OPENING, newsock, newsock, -1,
- c->local_window_max, c->local_maxpacket,
- 0, "accepted auth socket", 1);
- if (compat20) {
- packet_start(SSH2_MSG_CHANNEL_OPEN);
- packet_put_cstring("auth-agent@openssh.com");
- packet_put_int(nc->self);
- packet_put_int(c->local_window_max);
- packet_put_int(c->local_maxpacket);
- } else {
- packet_start(SSH_SMSG_AGENT_OPEN);
- packet_put_int(nc->self);
- }
- packet_send();
+ if (!FD_ISSET(c->sock, readset))
+ return;
+
+ addrlen = sizeof(addr);
+ newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
+ if (newsock == -1) {
+ error("accept from auth socket: %.100s", strerror(errno));
+ if (errno == EMFILE || errno == ENFILE)
+ c->notbefore = monotime() + 1;
+ return;
}
+ nc = channel_new(ssh, "accepted auth socket",
+ SSH_CHANNEL_OPENING, newsock, newsock, -1,
+ c->local_window_max, c->local_maxpacket,
+ 0, "accepted auth socket", 1);
+ open_preamble(ssh, __func__, nc, "auth-agent@openssh.com");
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
}
-/* ARGSUSED */
static void
-channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
+channel_post_connecting(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
- int err = 0, sock;
+ int err = 0, sock, isopen, r;
socklen_t sz = sizeof(err);
- if (FD_ISSET(c->sock, writeset)) {
- if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) {
- err = errno;
- error("getsockopt SO_ERROR failed");
+ if (!FD_ISSET(c->sock, writeset))
+ return;
+ if (!c->have_remote_id)
+ fatal(":%s: channel %d: no remote id", __func__, c->self);
+ /* for rdynamic the OPEN_CONFIRMATION has been sent already */
+ isopen = (c->type == SSH_CHANNEL_RDYNAMIC_FINISH);
+ if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) == -1) {
+ err = errno;
+ error("getsockopt SO_ERROR failed");
+ }
+ if (err == 0) {
+ debug("channel %d: connected to %s port %d",
+ c->self, c->connect_ctx.host, c->connect_ctx.port);
+ channel_connect_ctx_free(&c->connect_ctx);
+ c->type = SSH_CHANNEL_OPEN;
+ if (isopen) {
+ /* no message necessary */
+ } else {
+ if ((r = sshpkt_start(ssh,
+ SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_maxpacket))
+ != 0)
+ fatal("%s: channel %i: confirm: %s", __func__,
+ c->self, ssh_err(r));
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: channel %i: %s", __func__, c->self,
+ ssh_err(r));
}
- if (err == 0) {
- debug("channel %d: connected to %s port %d",
- c->self, c->connect_ctx.host, c->connect_ctx.port);
- channel_connect_ctx_free(&c->connect_ctx);
- c->type = SSH_CHANNEL_OPEN;
- if (compat20) {
- packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(c->remote_id);
- packet_put_int(c->self);
- packet_put_int(c->local_window);
- packet_put_int(c->local_maxpacket);
- } else {
- packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(c->remote_id);
- packet_put_int(c->self);
- }
+ } else {
+ debug("channel %d: connection failed: %s",
+ c->self, strerror(err));
+ /* Try next address, if any */
+ if ((sock = connect_next(&c->connect_ctx)) > 0) {
+ close(c->sock);
+ c->sock = c->rfd = c->wfd = sock;
+ channel_find_maxfd(ssh->chanctxt);
+ return;
+ }
+ /* Exhausted all addresses */
+ error("connect_to %.100s port %d: failed.",
+ c->connect_ctx.host, c->connect_ctx.port);
+ channel_connect_ctx_free(&c->connect_ctx);
+ if (isopen) {
+ rdynamic_close(ssh, c);
} else {
- debug("channel %d: connection failed: %s",
- c->self, strerror(err));
- /* Try next address, if any */
- if ((sock = connect_next(&c->connect_ctx)) > 0) {
- close(c->sock);
- c->sock = c->rfd = c->wfd = sock;
- channel_max_fd = channel_find_maxfd();
- return;
- }
- /* Exhausted all addresses */
- error("connect_to %.100s port %d: failed.",
- c->connect_ctx.host, c->connect_ctx.port);
- channel_connect_ctx_free(&c->connect_ctx);
- if (compat20) {
- packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(c->remote_id);
- packet_put_int(SSH2_OPEN_CONNECT_FAILED);
- if (!(datafellows & SSH_BUG_OPENFAILURE)) {
- packet_put_cstring(strerror(err));
- packet_put_cstring("");
- }
- } else {
- packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(c->remote_id);
+ if ((r = sshpkt_start(ssh,
+ SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_u32(ssh,
+ SSH2_OPEN_CONNECT_FAILED)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, strerror(err))) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0) {
+ fatal("%s: channel %i: failure: %s", __func__,
+ c->self, ssh_err(r));
}
- chan_mark_dead(c);
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: channel %i: %s", __func__, c->self,
+ ssh_err(r));
+ chan_mark_dead(ssh, c);
}
- packet_send();
}
}
-/* ARGSUSED */
static int
-channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset)
+channel_handle_rfd(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
char buf[CHAN_RBUF];
- int len, force;
+ ssize_t len;
+ int r, force;
force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED;
- if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) {
- errno = 0;
- len = read(c->rfd, buf, sizeof(buf));
- if (len < 0 && (errno == EINTR ||
- ((errno == EAGAIN || errno == EWOULDBLOCK) && !force)))
- return 1;
+
+ if (c->rfd == -1 || (!force && !FD_ISSET(c->rfd, readset)))
+ return 1;
+
+ errno = 0;
+ len = read(c->rfd, buf, sizeof(buf));
+ if (len == -1 && (errno == EINTR ||
+ ((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)))) {
+ if ((!c->isatty && len <= 0) ||
+ (c->isatty && (len < 0 || (len == 0 && errno != 0)))) {
#endif
- debug2("channel %d: read<=0 rfd %d len %d",
- c->self, c->rfd, len);
- if (c->type != SSH_CHANNEL_OPEN) {
- debug2("channel %d: not open", c->self);
- chan_mark_dead(c);
- return -1;
- } else if (compat13) {
- buffer_clear(&c->output);
- c->type = SSH_CHANNEL_INPUT_DRAINING;
- debug2("channel %d: input draining.", c->self);
- } else {
- chan_read_failed(c);
- }
+ debug2("channel %d: read<=0 rfd %d len %zd",
+ c->self, c->rfd, len);
+ if (c->type != SSH_CHANNEL_OPEN) {
+ debug2("channel %d: not open", c->self);
+ chan_mark_dead(ssh, c);
return -1;
- }
- if (c->input_filter != NULL) {
- if (c->input_filter(c, buf, len) == -1) {
- debug2("channel %d: filter stops", c->self);
- chan_read_failed(c);
- }
- } else if (c->datagram) {
- buffer_put_string(&c->input, buf, len);
} else {
- buffer_append(&c->input, buf, len);
+ chan_read_failed(ssh, c);
+ }
+ return -1;
+ }
+ if (c->input_filter != NULL) {
+ if (c->input_filter(ssh, c, buf, len) == -1) {
+ debug2("channel %d: filter stops", c->self);
+ chan_read_failed(ssh, c);
}
+ } else if (c->datagram) {
+ if ((r = sshbuf_put_string(c->input, buf, len)) != 0)
+ fatal("%s: channel %d: put datagram: %s", __func__,
+ c->self, ssh_err(r));
+ } else if ((r = sshbuf_put(c->input, buf, len)) != 0) {
+ fatal("%s: channel %d: put data: %s", __func__,
+ c->self, ssh_err(r));
}
return 1;
}
-/* ARGSUSED */
static int
-channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
+channel_handle_wfd(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
struct termios tio;
- u_char *data = NULL, *buf;
- u_int dlen, olen = 0;
- int len;
+ u_char *data = NULL, *buf; /* XXX const; need filter API change */
+ size_t dlen, olen = 0;
+ int r, len;
+
+ if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) ||
+ sshbuf_len(c->output) == 0)
+ return 1;
/* Send buffered output data to the socket. */
- if (c->wfd != -1 &&
- FD_ISSET(c->wfd, writeset) &&
- buffer_len(&c->output) > 0) {
- olen = buffer_len(&c->output);
- if (c->output_filter != NULL) {
- if ((buf = c->output_filter(c, &data, &dlen)) == NULL) {
- debug2("channel %d: filter stops", c->self);
- if (c->type != SSH_CHANNEL_OPEN)
- chan_mark_dead(c);
- else
- chan_write_failed(c);
- return -1;
- }
- } else if (c->datagram) {
- buf = data = buffer_get_string(&c->output, &dlen);
- } else {
- buf = data = buffer_ptr(&c->output);
- dlen = buffer_len(&c->output);
+ olen = sshbuf_len(c->output);
+ if (c->output_filter != NULL) {
+ if ((buf = c->output_filter(ssh, c, &data, &dlen)) == NULL) {
+ debug2("channel %d: filter stops", c->self);
+ if (c->type != SSH_CHANNEL_OPEN)
+ chan_mark_dead(ssh, c);
+ else
+ chan_write_failed(ssh, c);
+ return -1;
}
+ } else if (c->datagram) {
+ if ((r = sshbuf_get_string(c->output, &data, &dlen)) != 0)
+ fatal("%s: channel %d: get datagram: %s", __func__,
+ c->self, ssh_err(r));
+ buf = data;
+ } else {
+ buf = data = sshbuf_mutable_ptr(c->output);
+ dlen = sshbuf_len(c->output);
+ }
+
+ if (c->datagram) {
+ /* ignore truncated writes, datagrams might get lost */
+ len = write(c->wfd, buf, dlen);
+ free(data);
+ if (len == -1 && (errno == EINTR || errno == EAGAIN ||
+ errno == EWOULDBLOCK))
+ return 1;
+ if (len <= 0)
+ goto write_fail;
+ goto out;
+ }
- if (c->datagram) {
- /* ignore truncated writes, datagrams might get lost */
- len = write(c->wfd, buf, dlen);
- free(data);
- if (len < 0 && (errno == EINTR || errno == EAGAIN ||
- errno == EWOULDBLOCK))
- return 1;
- if (len <= 0) {
- if (c->type != SSH_CHANNEL_OPEN)
- chan_mark_dead(c);
- else
- chan_write_failed(c);
- return -1;
- }
- goto out;
- }
#ifdef _AIX
- /* XXX: Later AIX versions can't push as much data to tty */
- if (compat20 && c->wfd_isatty)
- dlen = MIN(dlen, 8*1024);
+ /* XXX: Later AIX versions can't push as much data to tty */
+ if (c->wfd_isatty)
+ dlen = MIN(dlen, 8*1024);
#endif
- len = write(c->wfd, buf, dlen);
- if (len < 0 &&
- (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
- return 1;
- if (len <= 0) {
- if (c->type != SSH_CHANNEL_OPEN) {
- debug2("channel %d: not open", c->self);
- chan_mark_dead(c);
- return -1;
- } else if (compat13) {
- buffer_clear(&c->output);
- debug2("channel %d: input draining.", c->self);
- c->type = SSH_CHANNEL_INPUT_DRAINING;
- } else {
- chan_write_failed(c);
- }
+ len = write(c->wfd, buf, dlen);
+ if (len == -1 &&
+ (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
+ return 1;
+ if (len <= 0) {
+ write_fail:
+ if (c->type != SSH_CHANNEL_OPEN) {
+ debug2("channel %d: not open", c->self);
+ chan_mark_dead(ssh, c);
return -1;
+ } else {
+ chan_write_failed(ssh, c);
}
+ return -1;
+ }
#ifndef BROKEN_TCGETATTR_ICANON
- if (compat20 && c->isatty && dlen >= 1 && buf[0] != '\r') {
- if (tcgetattr(c->wfd, &tio) == 0 &&
- !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
- /*
- * Simulate echo to reduce the impact of
- * traffic analysis. We need to match the
- * size of a SSH2_MSG_CHANNEL_DATA message
- * (4 byte channel id + buf)
- */
- packet_send_ignore(4 + len);
- packet_send();
- }
+ if (c->isatty && dlen >= 1 && buf[0] != '\r') {
+ if (tcgetattr(c->wfd, &tio) == 0 &&
+ !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
+ /*
+ * Simulate echo to reduce the impact of
+ * traffic analysis. We need to match the
+ * size of a SSH2_MSG_CHANNEL_DATA message
+ * (4 byte channel id + buf)
+ */
+ if ((r = sshpkt_msg_ignore(ssh, 4+len)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: channel %d: ignore: %s",
+ __func__, c->self, ssh_err(r));
}
-#endif
- buffer_consume(&c->output, len);
+ }
+#endif /* BROKEN_TCGETATTR_ICANON */
+ if ((r = sshbuf_consume(c->output, len)) != 0) {
+ fatal("%s: channel %d: consume: %s",
+ __func__, c->self, ssh_err(r));
}
out:
- if (compat20 && olen > 0)
- c->local_consumed += olen - buffer_len(&c->output);
+ c->local_consumed += olen - sshbuf_len(c->output);
+
+ return 1;
+}
+
+static int
+channel_handle_efd_write(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
+{
+ int r;
+ ssize_t len;
+
+ if (!FD_ISSET(c->efd, writeset) || sshbuf_len(c->extended) == 0)
+ return 1;
+
+ len = write(c->efd, sshbuf_ptr(c->extended),
+ sshbuf_len(c->extended));
+ debug2("channel %d: written %zd to efd %d", c->self, len, c->efd);
+ if (len == -1 && (errno == EINTR || errno == EAGAIN ||
+ errno == EWOULDBLOCK))
+ return 1;
+ if (len <= 0) {
+ debug2("channel %d: closing write-efd %d", c->self, c->efd);
+ channel_close_fd(ssh, &c->efd);
+ } else {
+ if ((r = sshbuf_consume(c->extended, len)) != 0) {
+ fatal("%s: channel %d: consume: %s",
+ __func__, c->self, ssh_err(r));
+ }
+ c->local_consumed += len;
+ }
return 1;
}
static int
-channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
+channel_handle_efd_read(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
char buf[CHAN_RBUF];
- int len;
+ ssize_t len;
+ int r, force;
-/** XXX handle drain efd, too */
- if (c->efd != -1) {
- if (c->extended_usage == CHAN_EXTENDED_WRITE &&
- FD_ISSET(c->efd, writeset) &&
- buffer_len(&c->extended) > 0) {
- len = write(c->efd, buffer_ptr(&c->extended),
- buffer_len(&c->extended));
- debug2("channel %d: written %d to efd %d",
- c->self, len, c->efd);
- if (len < 0 && (errno == EINTR || errno == EAGAIN ||
- errno == EWOULDBLOCK))
- return 1;
- if (len <= 0) {
- debug2("channel %d: closing write-efd %d",
- c->self, c->efd);
- channel_close_fd(&c->efd);
- } else {
- buffer_consume(&c->extended, len);
- c->local_consumed += len;
- }
- } else if (c->efd != -1 &&
- (c->extended_usage == CHAN_EXTENDED_READ ||
- c->extended_usage == CHAN_EXTENDED_IGNORE) &&
- (c->detach_close || FD_ISSET(c->efd, readset))) {
- len = read(c->efd, buf, sizeof(buf));
- debug2("channel %d: read %d from efd %d",
- c->self, len, c->efd);
- if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
- errno == EWOULDBLOCK) && !c->detach_close)))
- return 1;
- if (len <= 0) {
- debug2("channel %d: closing read-efd %d",
- c->self, c->efd);
- channel_close_fd(&c->efd);
- } else {
- if (c->extended_usage == CHAN_EXTENDED_IGNORE) {
- debug3("channel %d: discard efd",
- c->self);
- } else
- buffer_append(&c->extended, buf, len);
- }
+ force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED;
+
+ if (c->efd == -1 || (!force && !FD_ISSET(c->efd, readset)))
+ return 1;
+
+ len = read(c->efd, buf, sizeof(buf));
+ debug2("channel %d: read %zd from efd %d", c->self, len, c->efd);
+ if (len == -1 && (errno == EINTR || ((errno == EAGAIN ||
+ errno == EWOULDBLOCK) && !force)))
+ return 1;
+ if (len <= 0) {
+ debug2("channel %d: closing read-efd %d",
+ c->self, c->efd);
+ channel_close_fd(ssh, &c->efd);
+ } else {
+ if (c->extended_usage == CHAN_EXTENDED_IGNORE) {
+ debug3("channel %d: discard efd",
+ c->self);
+ } else if ((r = sshbuf_put(c->extended, buf, len)) != 0) {
+ fatal("%s: channel %d: append: %s",
+ __func__, c->self, ssh_err(r));
}
}
return 1;
}
static int
-channel_check_window(Channel *c)
+channel_handle_efd(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
+{
+ if (c->efd == -1)
+ return 1;
+
+ /** XXX handle drain efd, too */
+
+ if (c->extended_usage == CHAN_EXTENDED_WRITE)
+ return channel_handle_efd_write(ssh, c, readset, writeset);
+ else if (c->extended_usage == CHAN_EXTENDED_READ ||
+ c->extended_usage == CHAN_EXTENDED_IGNORE)
+ return channel_handle_efd_read(ssh, c, readset, writeset);
+
+ return 1;
+}
+
+static int
+channel_check_window(struct ssh *ssh, Channel *c)
{
+ int r;
+
if (c->type == SSH_CHANNEL_OPEN &&
!(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&
((c->local_window_max - c->local_window >
c->local_maxpacket*3) ||
c->local_window < c->local_window_max/2) &&
c->local_consumed > 0) {
- packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
- packet_put_int(c->remote_id);
- packet_put_int(c->local_consumed);
- packet_send();
+ if (!c->have_remote_id)
+ fatal(":%s: channel %d: no remote id",
+ __func__, c->self);
+ if ((r = sshpkt_start(ssh,
+ SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_consumed)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ fatal("%s: channel %i: %s", __func__,
+ c->self, ssh_err(r));
+ }
debug2("channel %d: window %d sent adjust %d",
c->self, c->local_window,
c->local_consumed);
@@ -1860,90 +2197,112 @@ channel_check_window(Channel *c)
}
static void
-channel_post_open(Channel *c, fd_set *readset, fd_set *writeset)
+channel_post_open(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
- channel_handle_rfd(c, readset, writeset);
- channel_handle_wfd(c, readset, writeset);
- if (!compat20)
- return;
- channel_handle_efd(c, readset, writeset);
- channel_check_window(c);
+ channel_handle_rfd(ssh, c, readset, writeset);
+ channel_handle_wfd(ssh, c, readset, writeset);
+ channel_handle_efd(ssh, c, readset, writeset);
+ channel_check_window(ssh, c);
}
static u_int
-read_mux(Channel *c, u_int need)
+read_mux(struct ssh *ssh, Channel *c, u_int need)
{
char buf[CHAN_RBUF];
- int len;
+ ssize_t len;
u_int rlen;
+ int r;
- if (buffer_len(&c->input) < need) {
- rlen = need - buffer_len(&c->input);
- len = read(c->rfd, buf, MIN(rlen, CHAN_RBUF));
+ if (sshbuf_len(c->input) < need) {
+ rlen = need - sshbuf_len(c->input);
+ len = read(c->rfd, buf, MINIMUM(rlen, CHAN_RBUF));
+ if (len == -1 && (errno == EINTR || errno == EAGAIN))
+ return sshbuf_len(c->input);
if (len <= 0) {
- if (errno != EINTR && errno != EAGAIN) {
- debug2("channel %d: ctl read<=0 rfd %d len %d",
- c->self, c->rfd, len);
- chan_read_failed(c);
- return 0;
- }
- } else
- buffer_append(&c->input, buf, len);
+ debug2("channel %d: ctl read<=0 rfd %d len %zd",
+ c->self, c->rfd, len);
+ chan_read_failed(ssh, c);
+ return 0;
+ } else if ((r = sshbuf_put(c->input, buf, len)) != 0) {
+ fatal("%s: channel %d: append: %s",
+ __func__, c->self, ssh_err(r));
+ }
}
- return buffer_len(&c->input);
+ return sshbuf_len(c->input);
}
static void
-channel_post_mux_client(Channel *c, fd_set *readset, fd_set *writeset)
+channel_post_mux_client_read(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
u_int need;
- ssize_t len;
- if (!compat20)
- fatal("%s: entered with !compat20", __func__);
+ if (c->rfd == -1 || !FD_ISSET(c->rfd, readset))
+ return;
+ if (c->istate != CHAN_INPUT_OPEN && c->istate != CHAN_INPUT_WAIT_DRAIN)
+ return;
+ if (c->mux_pause)
+ return;
- if (c->rfd != -1 && !c->mux_pause && FD_ISSET(c->rfd, readset) &&
- (c->istate == CHAN_INPUT_OPEN ||
- c->istate == CHAN_INPUT_WAIT_DRAIN)) {
- /*
- * Don't not read past the precise end of packets to
- * avoid disrupting fd passing.
- */
- if (read_mux(c, 4) < 4) /* read header */
- return;
- need = get_u32(buffer_ptr(&c->input));
+ /*
+ * Don't not read past the precise end of packets to
+ * avoid disrupting fd passing.
+ */
+ if (read_mux(ssh, c, 4) < 4) /* read header */
+ return;
+ /* XXX sshbuf_peek_u32 */
+ need = PEEK_U32(sshbuf_ptr(c->input));
#define CHANNEL_MUX_MAX_PACKET (256 * 1024)
- if (need > CHANNEL_MUX_MAX_PACKET) {
- debug2("channel %d: packet too big %u > %u",
- c->self, CHANNEL_MUX_MAX_PACKET, need);
- chan_rcvd_oclose(c);
- return;
- }
- if (read_mux(c, need + 4) < need + 4) /* read body */
- return;
- if (c->mux_rcb(c) != 0) {
- debug("channel %d: mux_rcb failed", c->self);
- chan_mark_dead(c);
- return;
- }
+ if (need > CHANNEL_MUX_MAX_PACKET) {
+ debug2("channel %d: packet too big %u > %u",
+ c->self, CHANNEL_MUX_MAX_PACKET, need);
+ chan_rcvd_oclose(ssh, c);
+ return;
+ }
+ if (read_mux(ssh, c, need + 4) < need + 4) /* read body */
+ return;
+ if (c->mux_rcb(ssh, c) != 0) {
+ debug("channel %d: mux_rcb failed", c->self);
+ chan_mark_dead(ssh, c);
+ return;
}
+}
- if (c->wfd != -1 && FD_ISSET(c->wfd, writeset) &&
- buffer_len(&c->output) > 0) {
- len = write(c->wfd, buffer_ptr(&c->output),
- buffer_len(&c->output));
- if (len < 0 && (errno == EINTR || errno == EAGAIN))
- return;
- if (len <= 0) {
- chan_mark_dead(c);
- return;
- }
- buffer_consume(&c->output, len);
+static void
+channel_post_mux_client_write(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
+{
+ ssize_t len;
+ int r;
+
+ if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) ||
+ sshbuf_len(c->output) == 0)
+ return;
+
+ len = write(c->wfd, sshbuf_ptr(c->output), sshbuf_len(c->output));
+ if (len == -1 && (errno == EINTR || errno == EAGAIN))
+ return;
+ if (len <= 0) {
+ chan_mark_dead(ssh, c);
+ return;
}
+ if ((r = sshbuf_consume(c->output, len)) != 0)
+ fatal("%s: channel %d: consume: %s", __func__,
+ c->self, ssh_err(r));
+}
+
+static void
+channel_post_mux_client(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
+{
+ channel_post_mux_client_read(ssh, c, readset, writeset);
+ channel_post_mux_client_write(ssh, c, readset, writeset);
}
static void
-channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset)
+channel_post_mux_listener(struct ssh *ssh, Channel *c,
+ fd_set *readset, fd_set *writeset)
{
Channel *nc;
struct sockaddr_storage addr;
@@ -1970,7 +2329,7 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset)
return;
}
- if (getpeereid(newsock, &euid, &egid) < 0) {
+ if (getpeereid(newsock, &euid, &egid) == -1) {
error("%s getpeereid failed: %s", __func__,
strerror(errno));
close(newsock);
@@ -1982,166 +2341,101 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset)
close(newsock);
return;
}
- nc = channel_new("multiplex client", SSH_CHANNEL_MUX_CLIENT,
+ nc = channel_new(ssh, "multiplex client", SSH_CHANNEL_MUX_CLIENT,
newsock, newsock, -1, c->local_window_max,
c->local_maxpacket, 0, "mux-control", 1);
nc->mux_rcb = c->mux_rcb;
- debug3("%s: new mux channel %d fd %d", __func__,
- nc->self, nc->sock);
+ debug3("%s: new mux channel %d fd %d", __func__, nc->self, nc->sock);
/* establish state */
- nc->mux_rcb(nc);
+ nc->mux_rcb(ssh, nc);
/* mux state transitions must not elicit protocol messages */
nc->flags |= CHAN_LOCAL;
}
-/* ARGSUSED */
-static void
-channel_post_output_drain_13(Channel *c, fd_set *readset, fd_set *writeset)
-{
- int len;
-
- /* Send buffered output data to the socket. */
- if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) {
- len = write(c->sock, buffer_ptr(&c->output),
- buffer_len(&c->output));
- if (len <= 0)
- buffer_clear(&c->output);
- else
- buffer_consume(&c->output, len);
- }
-}
-
-static void
-channel_handler_init_20(void)
-{
- channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open;
- channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
- channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
- channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
- channel_pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client;
-
- channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
- channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
- channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
- channel_post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener;
- channel_post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener;
- channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
- channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
- channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
- channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
- channel_post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener;
- channel_post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client;
-}
-
-static void
-channel_handler_init_13(void)
-{
- channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_13;
- channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open_13;
- channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining;
- channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining;
- channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
- channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
-
- channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
- channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
- channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
- channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
- channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13;
- channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
- channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
-}
-
-static void
-channel_handler_init_15(void)
-{
- channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open;
- channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
- channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
- channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
-
- channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
- channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
- channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
- channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
- channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
- channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
-}
-
static void
-channel_handler_init(void)
+channel_handler_init(struct ssh_channels *sc)
{
- int i;
-
- for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) {
- channel_pre[i] = NULL;
- channel_post[i] = NULL;
- }
- if (compat20)
- channel_handler_init_20();
- else if (compat13)
- channel_handler_init_13();
- else
- channel_handler_init_15();
+ chan_fn **pre, **post;
+
+ if ((pre = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*pre))) == NULL ||
+ (post = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*post))) == NULL)
+ fatal("%s: allocation failed", __func__);
+
+ pre[SSH_CHANNEL_OPEN] = &channel_pre_open;
+ pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
+ pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
+ pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
+ pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener;
+ pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener;
+ pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
+ pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
+ pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
+ pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
+ pre[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_pre_connecting;
+ pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener;
+ pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client;
+
+ post[SSH_CHANNEL_OPEN] = &channel_post_open;
+ post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
+ post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
+ post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener;
+ post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener;
+ post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
+ post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
+ post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
+ post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
+ post[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_post_connecting;
+ post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener;
+ post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client;
+
+ sc->channel_pre = pre;
+ sc->channel_post = post;
}
/* gc dead channels */
static void
-channel_garbage_collect(Channel *c)
+channel_garbage_collect(struct ssh *ssh, Channel *c)
{
if (c == NULL)
return;
if (c->detach_user != NULL) {
- if (!chan_is_dead(c, c->detach_close))
+ if (!chan_is_dead(ssh, c, c->detach_close))
return;
+
debug2("channel %d: gc: notify user", c->self);
- c->detach_user(c->self, NULL);
+ c->detach_user(ssh, c->self, NULL);
/* if we still have a callback */
if (c->detach_user != NULL)
return;
debug2("channel %d: gc: user detached", c->self);
}
- if (!chan_is_dead(c, 1))
+ if (!chan_is_dead(ssh, c, 1))
return;
debug2("channel %d: garbage collecting", c->self);
- channel_free(c);
+ channel_free(ssh, c);
}
+enum channel_table { CHAN_PRE, CHAN_POST };
+
static void
-channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset,
- time_t *unpause_secs)
+channel_handler(struct ssh *ssh, int table,
+ fd_set *readset, fd_set *writeset, time_t *unpause_secs)
{
- static int did_init = 0;
+ struct ssh_channels *sc = ssh->chanctxt;
+ chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post;
u_int i, oalloc;
Channel *c;
time_t now;
- if (!did_init) {
- channel_handler_init();
- did_init = 1;
- }
now = monotime();
if (unpause_secs != NULL)
*unpause_secs = 0;
- for (i = 0, oalloc = channels_alloc; i < oalloc; i++) {
- c = channels[i];
+ for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) {
+ c = sc->channels[i];
if (c == NULL)
continue;
if (c->delayed) {
- if (ftab == channel_pre)
+ if (table == CHAN_PRE)
c->delayed = 0;
else
continue;
@@ -2151,7 +2445,7 @@ channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset,
* Run handlers that are not paused.
*/
if (c->notbefore <= now)
- (*ftab[c->type])(c, readset, writeset);
+ (*ftab[c->type])(ssh, c, readset, writeset);
else if (unpause_secs != NULL) {
/*
* Collect the time that the earliest
@@ -2165,7 +2459,7 @@ channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset,
*unpause_secs = c->notbefore - now;
}
}
- channel_garbage_collect(c);
+ channel_garbage_collect(ssh, c);
}
if (unpause_secs != NULL && *unpause_secs != 0)
debug3("%s: first channel unpauses in %d seconds",
@@ -2173,16 +2467,39 @@ channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset,
}
/*
+ * Create sockets before allocating the select bitmasks.
+ * This is necessary for things that need to happen after reading
+ * the network-input but before channel_prepare_select().
+ */
+static void
+channel_before_prepare_select(struct ssh *ssh)
+{
+ struct ssh_channels *sc = ssh->chanctxt;
+ Channel *c;
+ u_int i, oalloc;
+
+ for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) {
+ c = sc->channels[i];
+ if (c == NULL)
+ continue;
+ if (c->type == SSH_CHANNEL_RDYNAMIC_OPEN)
+ channel_before_prepare_select_rdynamic(ssh, c);
+ }
+}
+
+/*
* Allocate/update select bitmasks and add any bits relevant to channels in
* select bitmasks.
*/
void
-channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
- u_int *nallocp, time_t *minwait_secs, int rekeying)
+channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp,
+ int *maxfdp, u_int *nallocp, time_t *minwait_secs)
{
u_int n, sz, nfdset;
- n = MAX(*maxfdp, channel_max_fd);
+ channel_before_prepare_select(ssh); /* might update channel_max_fd */
+
+ n = MAXIMUM(*maxfdp, ssh->chanctxt->channel_max_fd);
nfdset = howmany(n+1, NFDBITS);
/* Explicitly test here, because xrealloc isn't always called */
@@ -2192,16 +2509,16 @@ channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
/* perhaps check sz < nalloc/2 and shrink? */
if (*readsetp == NULL || sz > *nallocp) {
- *readsetp = xrealloc(*readsetp, nfdset, sizeof(fd_mask));
- *writesetp = xrealloc(*writesetp, nfdset, sizeof(fd_mask));
+ *readsetp = xreallocarray(*readsetp, nfdset, sizeof(fd_mask));
+ *writesetp = xreallocarray(*writesetp, nfdset, sizeof(fd_mask));
*nallocp = sz;
}
*maxfdp = n;
memset(*readsetp, 0, sz);
memset(*writesetp, 0, sz);
- if (!rekeying)
- channel_handler(channel_pre, *readsetp, *writesetp,
+ if (!ssh_packet_is_rekeying(ssh))
+ channel_handler(ssh, CHAN_PRE, *readsetp, *writesetp,
minwait_secs);
}
@@ -2210,21 +2527,136 @@ channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
* events pending.
*/
void
-channel_after_select(fd_set *readset, fd_set *writeset)
+channel_after_select(struct ssh *ssh, fd_set *readset, fd_set *writeset)
+{
+ channel_handler(ssh, CHAN_POST, readset, writeset, NULL);
+}
+
+/*
+ * Enqueue data for channels with open or draining c->input.
+ */
+static void
+channel_output_poll_input_open(struct ssh *ssh, Channel *c)
{
- channel_handler(channel_post, readset, writeset, NULL);
+ size_t len, plen;
+ const u_char *pkt;
+ int r;
+
+ if ((len = sshbuf_len(c->input)) == 0) {
+ if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
+ /*
+ * input-buffer is empty and read-socket shutdown:
+ * tell peer, that we will not send more data:
+ * send IEOF.
+ * hack for extended data: delay EOF if EFD still
+ * in use.
+ */
+ if (CHANNEL_EFD_INPUT_ACTIVE(c))
+ debug2("channel %d: "
+ "ibuf_empty delayed efd %d/(%zu)",
+ c->self, c->efd, sshbuf_len(c->extended));
+ else
+ chan_ibuf_empty(ssh, c);
+ }
+ return;
+ }
+
+ if (!c->have_remote_id)
+ fatal(":%s: channel %d: no remote id", __func__, c->self);
+
+ if (c->datagram) {
+ /* Check datagram will fit; drop if not */
+ if ((r = sshbuf_get_string_direct(c->input, &pkt, &plen)) != 0)
+ fatal("%s: channel %d: get datagram: %s", __func__,
+ c->self, ssh_err(r));
+ /*
+ * XXX this does tail-drop on the datagram queue which is
+ * usually suboptimal compared to head-drop. Better to have
+ * backpressure at read time? (i.e. read + discard)
+ */
+ if (plen > c->remote_window || plen > c->remote_maxpacket) {
+ debug("channel %d: datagram too big", c->self);
+ return;
+ }
+ /* Enqueue it */
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_string(ssh, pkt, plen)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ fatal("%s: channel %i: datagram: %s", __func__,
+ c->self, ssh_err(r));
+ }
+ c->remote_window -= plen;
+ return;
+ }
+
+ /* Enqueue packet for buffered data. */
+ if (len > c->remote_window)
+ len = c->remote_window;
+ if (len > c->remote_maxpacket)
+ len = c->remote_maxpacket;
+ if (len == 0)
+ return;
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_string(ssh, sshbuf_ptr(c->input), len)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ fatal("%s: channel %i: data: %s", __func__,
+ c->self, ssh_err(r));
+ }
+ if ((r = sshbuf_consume(c->input, len)) != 0)
+ fatal("%s: channel %i: consume: %s", __func__,
+ c->self, ssh_err(r));
+ c->remote_window -= len;
}
+/*
+ * Enqueue data for channels with open c->extended in read mode.
+ */
+static void
+channel_output_poll_extended_read(struct ssh *ssh, Channel *c)
+{
+ size_t len;
+ int r;
+
+ if ((len = sshbuf_len(c->extended)) == 0)
+ return;
+
+ debug2("channel %d: rwin %u elen %zu euse %d", c->self,
+ c->remote_window, sshbuf_len(c->extended), c->extended_usage);
+ if (len > c->remote_window)
+ len = c->remote_window;
+ if (len > c->remote_maxpacket)
+ len = c->remote_maxpacket;
+ if (len == 0)
+ return;
+ if (!c->have_remote_id)
+ fatal(":%s: channel %d: no remote id", __func__, c->self);
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_u32(ssh, SSH2_EXTENDED_DATA_STDERR)) != 0 ||
+ (r = sshpkt_put_string(ssh, sshbuf_ptr(c->extended), len)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ fatal("%s: channel %i: data: %s", __func__,
+ c->self, ssh_err(r));
+ }
+ if ((r = sshbuf_consume(c->extended, len)) != 0)
+ fatal("%s: channel %i: consume: %s", __func__,
+ c->self, ssh_err(r));
+ c->remote_window -= len;
+ debug2("channel %d: sent ext data %zu", c->self, len);
+}
/* If there is data to send to the connection, enqueue some of it now. */
void
-channel_output_poll(void)
+channel_output_poll(struct ssh *ssh)
{
+ struct ssh_channels *sc = ssh->chanctxt;
Channel *c;
- u_int i, len;
+ u_int i;
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
+ for (i = 0; i < sc->channels_alloc; i++) {
+ c = sc->channels[i];
if (c == NULL)
continue;
@@ -2232,354 +2664,525 @@ channel_output_poll(void)
* We are only interested in channels that can have buffered
* incoming data.
*/
- if (compat13) {
- if (c->type != SSH_CHANNEL_OPEN &&
- c->type != SSH_CHANNEL_INPUT_DRAINING)
- continue;
- } else {
- if (c->type != SSH_CHANNEL_OPEN)
- continue;
- }
- if (compat20 &&
- (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) {
+ if (c->type != SSH_CHANNEL_OPEN)
+ continue;
+ if ((c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) {
/* XXX is this true? */
- debug3("channel %d: will not send data after close", c->self);
+ debug3("channel %d: will not send data after close",
+ c->self);
continue;
}
/* Get the amount of buffered data for this channel. */
- if ((c->istate == CHAN_INPUT_OPEN ||
- c->istate == CHAN_INPUT_WAIT_DRAIN) &&
- (len = buffer_len(&c->input)) > 0) {
- if (c->datagram) {
- if (len > 0) {
- u_char *data;
- u_int dlen;
-
- data = buffer_get_string(&c->input,
- &dlen);
- if (dlen > c->remote_window ||
- dlen > c->remote_maxpacket) {
- debug("channel %d: datagram "
- "too big for channel",
- c->self);
- free(data);
- continue;
- }
- packet_start(SSH2_MSG_CHANNEL_DATA);
- packet_put_int(c->remote_id);
- packet_put_string(data, dlen);
- packet_send();
- c->remote_window -= dlen + 4;
- free(data);
- }
- continue;
- }
- /*
- * Send some data for the other side over the secure
- * connection.
- */
- if (compat20) {
- if (len > c->remote_window)
- len = c->remote_window;
- if (len > c->remote_maxpacket)
- len = c->remote_maxpacket;
- } else {
- if (packet_is_interactive()) {
- if (len > 1024)
- len = 512;
- } else {
- /* Keep the packets at reasonable size. */
- if (len > packet_get_maxsize()/2)
- len = packet_get_maxsize()/2;
- }
- }
- if (len > 0) {
- packet_start(compat20 ?
- SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA);
- packet_put_int(c->remote_id);
- packet_put_string(buffer_ptr(&c->input), len);
- packet_send();
- buffer_consume(&c->input, len);
- c->remote_window -= len;
- }
- } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
- if (compat13)
- fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");
- /*
- * input-buffer is empty and read-socket shutdown:
- * tell peer, that we will not send more data: send IEOF.
- * hack for extended data: delay EOF if EFD still in use.
- */
- if (CHANNEL_EFD_INPUT_ACTIVE(c))
- debug2("channel %d: ibuf_empty delayed efd %d/(%d)",
- c->self, c->efd, buffer_len(&c->extended));
+ if (c->istate == CHAN_INPUT_OPEN ||
+ c->istate == CHAN_INPUT_WAIT_DRAIN)
+ channel_output_poll_input_open(ssh, c);
+ /* Send extended data, i.e. stderr */
+ if (!(c->flags & CHAN_EOF_SENT) &&
+ c->extended_usage == CHAN_EXTENDED_READ)
+ channel_output_poll_extended_read(ssh, c);
+ }
+}
+
+/* -- mux proxy support */
+
+/*
+ * When multiplexing channel messages for mux clients we have to deal
+ * with downstream messages from the mux client and upstream messages
+ * from the ssh server:
+ * 1) Handling downstream messages is straightforward and happens
+ * in channel_proxy_downstream():
+ * - We forward all messages (mostly) unmodified to the server.
+ * - However, in order to route messages from upstream to the correct
+ * downstream client, we have to replace the channel IDs used by the
+ * mux clients with a unique channel ID because the mux clients might
+ * use conflicting channel IDs.
+ * - so we inspect and change both SSH2_MSG_CHANNEL_OPEN and
+ * SSH2_MSG_CHANNEL_OPEN_CONFIRMATION messages, create a local
+ * SSH_CHANNEL_MUX_PROXY channel and replace the mux clients ID
+ * with the newly allocated channel ID.
+ * 2) Upstream messages are received by matching SSH_CHANNEL_MUX_PROXY
+ * channels and processed by channel_proxy_upstream(). The local channel ID
+ * is then translated back to the original mux client ID.
+ * 3) In both cases we need to keep track of matching SSH2_MSG_CHANNEL_CLOSE
+ * messages so we can clean up SSH_CHANNEL_MUX_PROXY channels.
+ * 4) The SSH_CHANNEL_MUX_PROXY channels also need to closed when the
+ * downstream mux client are removed.
+ * 5) Handling SSH2_MSG_CHANNEL_OPEN messages from the upstream server
+ * requires more work, because they are not addressed to a specific
+ * channel. E.g. client_request_forwarded_tcpip() needs to figure
+ * out whether the request is addressed to the local client or a
+ * specific downstream client based on the listen-address/port.
+ * 6) Agent and X11-Forwarding have a similar problem and are currently
+ * not supported as the matching session/channel cannot be identified
+ * easily.
+ */
+
+/*
+ * receive packets from downstream mux clients:
+ * channel callback fired on read from mux client, creates
+ * SSH_CHANNEL_MUX_PROXY channels and translates channel IDs
+ * on channel creation.
+ */
+int
+channel_proxy_downstream(struct ssh *ssh, Channel *downstream)
+{
+ Channel *c = NULL;
+ struct sshbuf *original = NULL, *modified = NULL;
+ const u_char *cp;
+ char *ctype = NULL, *listen_host = NULL;
+ u_char type;
+ size_t have;
+ int ret = -1, r;
+ u_int id, remote_id, listen_port;
+
+ /* sshbuf_dump(downstream->input, stderr); */
+ if ((r = sshbuf_get_string_direct(downstream->input, &cp, &have))
+ != 0) {
+ error("%s: malformed message: %s", __func__, ssh_err(r));
+ return -1;
+ }
+ if (have < 2) {
+ error("%s: short message", __func__);
+ return -1;
+ }
+ type = cp[1];
+ /* skip padlen + type */
+ cp += 2;
+ have -= 2;
+ if (ssh_packet_log_type(type))
+ debug3("%s: channel %u: down->up: type %u", __func__,
+ downstream->self, type);
+
+ switch (type) {
+ case SSH2_MSG_CHANNEL_OPEN:
+ if ((original = sshbuf_from(cp, have)) == NULL ||
+ (modified = sshbuf_new()) == NULL) {
+ error("%s: alloc", __func__);
+ goto out;
+ }
+ if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0 ||
+ (r = sshbuf_get_u32(original, &id)) != 0) {
+ error("%s: parse error %s", __func__, ssh_err(r));
+ goto out;
+ }
+ c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY,
+ -1, -1, -1, 0, 0, 0, ctype, 1);
+ c->mux_ctx = downstream; /* point to mux client */
+ c->mux_downstream_id = id; /* original downstream id */
+ if ((r = sshbuf_put_cstring(modified, ctype)) != 0 ||
+ (r = sshbuf_put_u32(modified, c->self)) != 0 ||
+ (r = sshbuf_putb(modified, original)) != 0) {
+ error("%s: compose error %s", __func__, ssh_err(r));
+ channel_free(ssh, c);
+ goto out;
+ }
+ break;
+ case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
+ /*
+ * Almost the same as SSH2_MSG_CHANNEL_OPEN, except then we
+ * need to parse 'remote_id' instead of 'ctype'.
+ */
+ if ((original = sshbuf_from(cp, have)) == NULL ||
+ (modified = sshbuf_new()) == NULL) {
+ error("%s: alloc", __func__);
+ goto out;
+ }
+ if ((r = sshbuf_get_u32(original, &remote_id)) != 0 ||
+ (r = sshbuf_get_u32(original, &id)) != 0) {
+ error("%s: parse error %s", __func__, ssh_err(r));
+ goto out;
+ }
+ c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY,
+ -1, -1, -1, 0, 0, 0, "mux-down-connect", 1);
+ c->mux_ctx = downstream; /* point to mux client */
+ c->mux_downstream_id = id;
+ c->remote_id = remote_id;
+ c->have_remote_id = 1;
+ if ((r = sshbuf_put_u32(modified, remote_id)) != 0 ||
+ (r = sshbuf_put_u32(modified, c->self)) != 0 ||
+ (r = sshbuf_putb(modified, original)) != 0) {
+ error("%s: compose error %s", __func__, ssh_err(r));
+ channel_free(ssh, c);
+ goto out;
+ }
+ break;
+ case SSH2_MSG_GLOBAL_REQUEST:
+ if ((original = sshbuf_from(cp, have)) == NULL) {
+ error("%s: alloc", __func__);
+ goto out;
+ }
+ if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0) {
+ error("%s: parse error %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if (strcmp(ctype, "tcpip-forward") != 0) {
+ error("%s: unsupported request %s", __func__, ctype);
+ goto out;
+ }
+ if ((r = sshbuf_get_u8(original, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(original, &listen_host, NULL)) != 0 ||
+ (r = sshbuf_get_u32(original, &listen_port)) != 0) {
+ error("%s: parse error %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if (listen_port > 65535) {
+ error("%s: tcpip-forward for %s: bad port %u",
+ __func__, listen_host, listen_port);
+ goto out;
+ }
+ /* Record that connection to this host/port is permitted. */
+ permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, "<mux>", -1,
+ listen_host, NULL, (int)listen_port, downstream);
+ listen_host = NULL;
+ break;
+ case SSH2_MSG_CHANNEL_CLOSE:
+ if (have < 4)
+ break;
+ remote_id = PEEK_U32(cp);
+ if ((c = channel_by_remote_id(ssh, remote_id)) != NULL) {
+ if (c->flags & CHAN_CLOSE_RCVD)
+ channel_free(ssh, c);
else
- chan_ibuf_empty(c);
+ c->flags |= CHAN_CLOSE_SENT;
}
- /* Send extended data, i.e. stderr */
- if (compat20 &&
- !(c->flags & CHAN_EOF_SENT) &&
- c->remote_window > 0 &&
- (len = buffer_len(&c->extended)) > 0 &&
- c->extended_usage == CHAN_EXTENDED_READ) {
- debug2("channel %d: rwin %u elen %u euse %d",
- c->self, c->remote_window, buffer_len(&c->extended),
- c->extended_usage);
- if (len > c->remote_window)
- len = c->remote_window;
- if (len > c->remote_maxpacket)
- len = c->remote_maxpacket;
- packet_start(SSH2_MSG_CHANNEL_EXTENDED_DATA);
- packet_put_int(c->remote_id);
- packet_put_int(SSH2_EXTENDED_DATA_STDERR);
- packet_put_string(buffer_ptr(&c->extended), len);
- packet_send();
- buffer_consume(&c->extended, len);
- c->remote_window -= len;
- debug2("channel %d: sent ext data %d", c->self, len);
+ break;
+ }
+ if (modified) {
+ if ((r = sshpkt_start(ssh, type)) != 0 ||
+ (r = sshpkt_putb(ssh, modified)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ error("%s: send %s", __func__, ssh_err(r));
+ goto out;
+ }
+ } else {
+ if ((r = sshpkt_start(ssh, type)) != 0 ||
+ (r = sshpkt_put(ssh, cp, have)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ error("%s: send %s", __func__, ssh_err(r));
+ goto out;
}
}
+ ret = 0;
+ out:
+ free(ctype);
+ free(listen_host);
+ sshbuf_free(original);
+ sshbuf_free(modified);
+ return ret;
}
+/*
+ * receive packets from upstream server and de-multiplex packets
+ * to correct downstream:
+ * implemented as a helper for channel input handlers,
+ * replaces local (proxy) channel ID with downstream channel ID.
+ */
+int
+channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh)
+{
+ struct sshbuf *b = NULL;
+ Channel *downstream;
+ const u_char *cp = NULL;
+ size_t len;
+ int r;
+
+ /*
+ * When receiving packets from the peer we need to check whether we
+ * need to forward the packets to the mux client. In this case we
+ * restore the original channel id and keep track of CLOSE messages,
+ * so we can cleanup the channel.
+ */
+ if (c == NULL || c->type != SSH_CHANNEL_MUX_PROXY)
+ return 0;
+ if ((downstream = c->mux_ctx) == NULL)
+ return 0;
+ switch (type) {
+ case SSH2_MSG_CHANNEL_CLOSE:
+ case SSH2_MSG_CHANNEL_DATA:
+ case SSH2_MSG_CHANNEL_EOF:
+ case SSH2_MSG_CHANNEL_EXTENDED_DATA:
+ case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
+ case SSH2_MSG_CHANNEL_OPEN_FAILURE:
+ case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
+ case SSH2_MSG_CHANNEL_SUCCESS:
+ case SSH2_MSG_CHANNEL_FAILURE:
+ case SSH2_MSG_CHANNEL_REQUEST:
+ break;
+ default:
+ debug2("%s: channel %u: unsupported type %u", __func__,
+ c->self, type);
+ return 0;
+ }
+ if ((b = sshbuf_new()) == NULL) {
+ error("%s: alloc reply", __func__);
+ goto out;
+ }
+ /* get remaining payload (after id) */
+ cp = sshpkt_ptr(ssh, &len);
+ if (cp == NULL) {
+ error("%s: no packet", __func__);
+ goto out;
+ }
+ /* translate id and send to muxclient */
+ if ((r = sshbuf_put_u8(b, 0)) != 0 || /* padlen */
+ (r = sshbuf_put_u8(b, type)) != 0 ||
+ (r = sshbuf_put_u32(b, c->mux_downstream_id)) != 0 ||
+ (r = sshbuf_put(b, cp, len)) != 0 ||
+ (r = sshbuf_put_stringb(downstream->output, b)) != 0) {
+ error("%s: compose for muxclient %s", __func__, ssh_err(r));
+ goto out;
+ }
+ /* sshbuf_dump(b, stderr); */
+ if (ssh_packet_log_type(type))
+ debug3("%s: channel %u: up->down: type %u", __func__, c->self,
+ type);
+ out:
+ /* update state */
+ switch (type) {
+ case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
+ /* record remote_id for SSH2_MSG_CHANNEL_CLOSE */
+ if (cp && len > 4) {
+ c->remote_id = PEEK_U32(cp);
+ c->have_remote_id = 1;
+ }
+ break;
+ case SSH2_MSG_CHANNEL_CLOSE:
+ if (c->flags & CHAN_CLOSE_SENT)
+ channel_free(ssh, c);
+ else
+ c->flags |= CHAN_CLOSE_RCVD;
+ break;
+ }
+ sshbuf_free(b);
+ return 1;
+}
/* -- protocol input */
-/* ARGSUSED */
+/* Parse a channel ID from the current packet */
+static int
+channel_parse_id(struct ssh *ssh, const char *where, const char *what)
+{
+ u_int32_t id;
+ int r;
+
+ if ((r = sshpkt_get_u32(ssh, &id)) != 0) {
+ error("%s: parse id: %s", where, ssh_err(r));
+ ssh_packet_disconnect(ssh, "Invalid %s message", what);
+ }
+ if (id > INT_MAX) {
+ error("%s: bad channel id %u: %s", where, id, ssh_err(r));
+ ssh_packet_disconnect(ssh, "Invalid %s channel id", what);
+ }
+ return (int)id;
+}
+
+/* Lookup a channel from an ID in the current packet */
+static Channel *
+channel_from_packet_id(struct ssh *ssh, const char *where, const char *what)
+{
+ int id = channel_parse_id(ssh, where, what);
+ Channel *c;
+
+ if ((c = channel_lookup(ssh, id)) == NULL) {
+ ssh_packet_disconnect(ssh,
+ "%s packet referred to nonexistent channel %d", what, id);
+ }
+ return c;
+}
+
int
-channel_input_data(int type, u_int32_t seq, void *ctxt)
+channel_input_data(int type, u_int32_t seq, struct ssh *ssh)
{
- int id;
const u_char *data;
- u_int data_len, win_len;
- Channel *c;
+ size_t data_len, win_len;
+ Channel *c = channel_from_packet_id(ssh, __func__, "data");
+ int r;
- /* Get the channel number and verify it. */
- id = packet_get_int();
- c = channel_lookup(id);
- if (c == NULL)
- packet_disconnect("Received data for nonexistent channel %d.", id);
+ if (channel_proxy_upstream(c, type, seq, ssh))
+ return 0;
/* Ignore any data for non-open channels (might happen on close) */
if (c->type != SSH_CHANNEL_OPEN &&
+ c->type != SSH_CHANNEL_RDYNAMIC_OPEN &&
+ c->type != SSH_CHANNEL_RDYNAMIC_FINISH &&
c->type != SSH_CHANNEL_X11_OPEN)
return 0;
/* Get the data. */
- data = packet_get_string_ptr(&data_len);
+ 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));
+
win_len = data_len;
if (c->datagram)
win_len += 4; /* string length header */
/*
- * Ignore data for protocol > 1.3 if output end is no longer open.
- * For protocol 2 the sending side is reducing its window as it sends
- * data, so we must 'fake' consumption of the data in order to ensure
- * that window updates are sent back. Otherwise the connection might
- * deadlock.
+ * The sending side reduces its window as it sends data, so we
+ * must 'fake' consumption of the data in order to ensure that window
+ * updates are sent back. Otherwise the connection might deadlock.
*/
- if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN) {
- if (compat20) {
- c->local_window -= win_len;
- c->local_consumed += win_len;
- }
+ if (c->ostate != CHAN_OUTPUT_OPEN) {
+ c->local_window -= win_len;
+ c->local_consumed += win_len;
return 0;
}
- if (compat20) {
- if (win_len > c->local_maxpacket) {
- logit("channel %d: rcvd big packet %d, maxpack %d",
- c->self, win_len, c->local_maxpacket);
- }
- if (win_len > c->local_window) {
- logit("channel %d: rcvd too much data %d, win %d",
- c->self, win_len, c->local_window);
- return 0;
- }
- c->local_window -= win_len;
+ if (win_len > c->local_maxpacket) {
+ logit("channel %d: rcvd big packet %zu, maxpack %u",
+ c->self, win_len, c->local_maxpacket);
+ return 0;
}
- if (c->datagram)
- buffer_put_string(&c->output, data, data_len);
- else
- buffer_append(&c->output, data, data_len);
- packet_check_eom();
+ if (win_len > c->local_window) {
+ logit("channel %d: rcvd too much data %zu, win %u",
+ c->self, win_len, c->local_window);
+ return 0;
+ }
+ c->local_window -= win_len;
+
+ if (c->datagram) {
+ if ((r = sshbuf_put_string(c->output, data, data_len)) != 0)
+ fatal("%s: channel %d: append datagram: %s",
+ __func__, c->self, ssh_err(r));
+ } else if ((r = sshbuf_put(c->output, data, data_len)) != 0)
+ fatal("%s: channel %d: append data: %s",
+ __func__, c->self, ssh_err(r));
+
return 0;
}
-/* ARGSUSED */
int
-channel_input_extended_data(int type, u_int32_t seq, void *ctxt)
+channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh)
{
- int id;
- char *data;
- u_int data_len, tcode;
- Channel *c;
-
- /* Get the channel number and verify it. */
- id = packet_get_int();
- c = channel_lookup(id);
+ const u_char *data;
+ size_t data_len;
+ u_int32_t tcode;
+ Channel *c = channel_from_packet_id(ssh, __func__, "extended data");
+ int r;
- if (c == NULL)
- packet_disconnect("Received extended_data for bad channel %d.", id);
+ if (channel_proxy_upstream(c, type, seq, ssh))
+ return 0;
if (c->type != SSH_CHANNEL_OPEN) {
- logit("channel %d: ext data for non open", id);
+ logit("channel %d: ext data for non open", c->self);
return 0;
}
if (c->flags & CHAN_EOF_RCVD) {
if (datafellows & SSH_BUG_EXTEOF)
- debug("channel %d: accepting ext data after eof", id);
+ debug("channel %d: accepting ext data after eof",
+ c->self);
else
- packet_disconnect("Received extended_data after EOF "
- "on channel %d.", id);
+ ssh_packet_disconnect(ssh, "Received extended_data "
+ "after EOF on channel %d.", c->self);
+ }
+
+ if ((r = sshpkt_get_u32(ssh, &tcode)) != 0) {
+ error("%s: parse tcode: %s", __func__, ssh_err(r));
+ ssh_packet_disconnect(ssh, "Invalid extended_data message");
}
- tcode = packet_get_int();
if (c->efd == -1 ||
c->extended_usage != CHAN_EXTENDED_WRITE ||
tcode != SSH2_EXTENDED_DATA_STDERR) {
logit("channel %d: bad ext data", c->self);
return 0;
}
- data = packet_get_string(&data_len);
- packet_check_eom();
+ if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0) {
+ error("%s: parse data: %s", __func__, ssh_err(r));
+ ssh_packet_disconnect(ssh, "Invalid extended_data message");
+ }
+
if (data_len > c->local_window) {
- logit("channel %d: rcvd too much extended_data %d, win %d",
+ logit("channel %d: rcvd too much extended_data %zu, win %u",
c->self, data_len, c->local_window);
- free(data);
return 0;
}
- debug2("channel %d: rcvd ext data %d", c->self, data_len);
+ debug2("channel %d: rcvd ext data %zu", c->self, data_len);
+ /* XXX sshpkt_getb? */
+ if ((r = sshbuf_put(c->extended, data, data_len)) != 0)
+ error("%s: append: %s", __func__, ssh_err(r));
c->local_window -= data_len;
- buffer_append(&c->extended, data, data_len);
- free(data);
return 0;
}
-/* ARGSUSED */
int
-channel_input_ieof(int type, u_int32_t seq, void *ctxt)
+channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh)
{
- int id;
- Channel *c;
+ Channel *c = channel_from_packet_id(ssh, __func__, "ieof");
+ int r;
- id = packet_get_int();
- packet_check_eom();
- c = channel_lookup(id);
- if (c == NULL)
- packet_disconnect("Received ieof for nonexistent channel %d.", id);
- chan_rcvd_ieof(c);
+ if ((r = sshpkt_get_end(ssh)) != 0) {
+ error("%s: parse data: %s", __func__, ssh_err(r));
+ ssh_packet_disconnect(ssh, "Invalid ieof message");
+ }
+
+ if (channel_proxy_upstream(c, type, seq, ssh))
+ return 0;
+ chan_rcvd_ieof(ssh, c);
/* XXX force input close */
if (c->force_drain && c->istate == CHAN_INPUT_OPEN) {
debug("channel %d: FORCE input drain", c->self);
c->istate = CHAN_INPUT_WAIT_DRAIN;
- if (buffer_len(&c->input) == 0)
- chan_ibuf_empty(c);
+ if (sshbuf_len(c->input) == 0)
+ chan_ibuf_empty(ssh, c);
}
return 0;
}
-/* ARGSUSED */
int
-channel_input_close(int type, u_int32_t seq, void *ctxt)
+channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh)
{
- int id;
- Channel *c;
-
- id = packet_get_int();
- packet_check_eom();
- c = channel_lookup(id);
- if (c == NULL)
- packet_disconnect("Received close for nonexistent channel %d.", id);
-
- /*
- * Send a confirmation that we have closed the channel and no more
- * data is coming for it.
- */
- packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);
- packet_put_int(c->remote_id);
- packet_send();
+ Channel *c = channel_from_packet_id(ssh, __func__, "oclose");
+ int r;
- /*
- * If the channel is in closed state, we have sent a close request,
- * and the other side will eventually respond with a confirmation.
- * Thus, we cannot free the channel here, because then there would be
- * no-one to receive the confirmation. The channel gets freed when
- * the confirmation arrives.
- */
- if (c->type != SSH_CHANNEL_CLOSED) {
- /*
- * Not a closed channel - mark it as draining, which will
- * cause it to be freed later.
- */
- buffer_clear(&c->input);
- c->type = SSH_CHANNEL_OUTPUT_DRAINING;
+ 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));
+ ssh_packet_disconnect(ssh, "Invalid oclose message");
}
+ chan_rcvd_oclose(ssh, c);
return 0;
}
-/* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */
-/* ARGSUSED */
-int
-channel_input_oclose(int type, u_int32_t seq, void *ctxt)
-{
- int id = packet_get_int();
- Channel *c = channel_lookup(id);
-
- packet_check_eom();
- if (c == NULL)
- packet_disconnect("Received oclose for nonexistent channel %d.", id);
- chan_rcvd_oclose(c);
- return 0;
-}
-
-/* ARGSUSED */
-int
-channel_input_close_confirmation(int type, u_int32_t seq, void *ctxt)
-{
- int id = packet_get_int();
- Channel *c = channel_lookup(id);
-
- packet_check_eom();
- if (c == NULL)
- packet_disconnect("Received close confirmation for "
- "out-of-range channel %d.", id);
- if (c->type != SSH_CHANNEL_CLOSED && c->type != SSH_CHANNEL_ABANDONED)
- packet_disconnect("Received close confirmation for "
- "non-closed channel %d (type %d).", id, c->type);
- channel_free(c);
- return 0;
-}
-
-/* ARGSUSED */
int
-channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt)
+channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh)
{
- int id, remote_id;
- Channel *c;
+ Channel *c = channel_from_packet_id(ssh, __func__, "open confirmation");
+ u_int32_t remote_window, remote_maxpacket;
+ int r;
- id = packet_get_int();
- c = channel_lookup(id);
+ if (channel_proxy_upstream(c, type, seq, ssh))
+ return 0;
+ if (c->type != SSH_CHANNEL_OPENING)
+ ssh_packet_disconnect(ssh, "Received open confirmation for "
+ "non-opening channel %d.", c->self);
+ /*
+ * Record the remote channel number and mark that the channel
+ * is now open.
+ */
+ if ((r = sshpkt_get_u32(ssh, &c->remote_id)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &remote_window)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0) {
+ error("%s: window/maxpacket: %s", __func__, ssh_err(r));
+ ssh_packet_disconnect(ssh, "Invalid open confirmation message");
+ }
- if (c==NULL || c->type != SSH_CHANNEL_OPENING)
- packet_disconnect("Received open confirmation for "
- "non-opening channel %d.", id);
- remote_id = packet_get_int();
- /* Record the remote channel number and mark that the channel is now open. */
- c->remote_id = remote_id;
+ c->have_remote_id = 1;
+ c->remote_window = remote_window;
+ c->remote_maxpacket = remote_maxpacket;
c->type = SSH_CHANNEL_OPEN;
-
- if (compat20) {
- c->remote_window = packet_get_int();
- c->remote_maxpacket = packet_get_int();
- if (c->open_confirm) {
- debug2("callback start");
- c->open_confirm(c->self, 1, c->open_confirm_ctx);
- debug2("callback done");
- }
- debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
- c->remote_window, c->remote_maxpacket);
+ if (c->open_confirm) {
+ debug2("%s: channel %d: callback start", __func__, c->self);
+ c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx);
+ debug2("%s: channel %d: callback done", __func__, c->self);
}
- packet_check_eom();
+ debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
+ c->remote_window, c->remote_maxpacket);
return 0;
}
@@ -2599,135 +3202,107 @@ reason2txt(int reason)
return "unknown reason";
}
-/* ARGSUSED */
int
-channel_input_open_failure(int type, u_int32_t seq, void *ctxt)
+channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh)
{
- int id, reason;
- char *msg = NULL, *lang = NULL;
- Channel *c;
+ Channel *c = channel_from_packet_id(ssh, __func__, "open failure");
+ u_int32_t reason;
+ char *msg = NULL;
+ int r;
- id = packet_get_int();
- c = channel_lookup(id);
-
- if (c==NULL || c->type != SSH_CHANNEL_OPENING)
- packet_disconnect("Received open failure for "
- "non-opening channel %d.", id);
- if (compat20) {
- reason = packet_get_int();
- if (!(datafellows & SSH_BUG_OPENFAILURE)) {
- msg = packet_get_string(NULL);
- lang = packet_get_string(NULL);
- }
- logit("channel %d: open failed: %s%s%s", id,
- reason2txt(reason), msg ? ": ": "", msg ? msg : "");
- free(msg);
- free(lang);
- if (c->open_confirm) {
- debug2("callback start");
- c->open_confirm(c->self, 0, c->open_confirm_ctx);
- debug2("callback done");
- }
+ if (channel_proxy_upstream(c, type, seq, ssh))
+ return 0;
+ if (c->type != SSH_CHANNEL_OPENING)
+ ssh_packet_disconnect(ssh, "Received open failure for "
+ "non-opening channel %d.", c->self);
+ if ((r = sshpkt_get_u32(ssh, &reason)) != 0) {
+ error("%s: reason: %s", __func__, ssh_err(r));
+ 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));
+ 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);
+ c->open_confirm(ssh, c->self, 0, c->open_confirm_ctx);
+ debug2("%s: channel %d: callback done", __func__, c->self);
}
- packet_check_eom();
/* Schedule the channel for cleanup/deletion. */
- chan_mark_dead(c);
+ chan_mark_dead(ssh, c);
return 0;
}
-/* ARGSUSED */
int
-channel_input_window_adjust(int type, u_int32_t seq, void *ctxt)
+channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh)
{
+ int id = channel_parse_id(ssh, __func__, "window adjust");
Channel *c;
- int id;
- u_int adjust;
+ u_int32_t adjust;
+ u_int new_rwin;
+ int r;
- if (!compat20)
- return 0;
-
- /* Get the channel number and verify it. */
- id = packet_get_int();
- c = channel_lookup(id);
-
- if (c == NULL) {
+ if ((c = channel_lookup(ssh, id)) == NULL) {
logit("Received window adjust for non-open channel %d.", id);
return 0;
}
- adjust = packet_get_int();
- packet_check_eom();
- debug2("channel %d: rcvd adjust %u", id, adjust);
- c->remote_window += adjust;
- return 0;
-}
-
-/* ARGSUSED */
-int
-channel_input_port_open(int type, u_int32_t seq, void *ctxt)
-{
- Channel *c = NULL;
- u_short host_port;
- char *host, *originator_string;
- int remote_id;
- remote_id = packet_get_int();
- host = packet_get_string(NULL);
- host_port = packet_get_int();
-
- if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) {
- originator_string = packet_get_string(NULL);
- } else {
- originator_string = xstrdup("unknown (remote did not supply name)");
+ if (channel_proxy_upstream(c, type, seq, ssh))
+ return 0;
+ if ((r = sshpkt_get_u32(ssh, &adjust)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0) {
+ error("%s: adjust: %s", __func__, ssh_err(r));
+ ssh_packet_disconnect(ssh, "Invalid window adjust message");
}
- packet_check_eom();
- c = channel_connect_to_port(host, host_port,
- "connected socket", originator_string);
- free(originator_string);
- free(host);
- if (c == NULL) {
- packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(remote_id);
- packet_send();
- } else
- c->remote_id = remote_id;
+ debug2("channel %d: rcvd adjust %u", c->self, adjust);
+ if ((new_rwin = c->remote_window + adjust) < c->remote_window) {
+ fatal("channel %d: adjust %u overflows remote window %u",
+ c->self, adjust, c->remote_window);
+ }
+ c->remote_window = new_rwin;
return 0;
}
-/* ARGSUSED */
int
-channel_input_status_confirm(int type, u_int32_t seq, void *ctxt)
+channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh)
{
+ int id = channel_parse_id(ssh, __func__, "status confirm");
Channel *c;
struct channel_confirm *cc;
- int id;
/* Reset keepalive timeout */
- packet_set_alive_timeouts(0);
-
- id = packet_get_int();
- packet_check_eom();
+ ssh_packet_set_alive_timeouts(ssh, 0);
- debug2("channel_input_status_confirm: type %d id %d", type, id);
+ debug2("%s: type %d id %d", __func__, type, id);
- if ((c = channel_lookup(id)) == NULL) {
- logit("channel_input_status_confirm: %d: unknown", id);
+ if ((c = channel_lookup(ssh, id)) == NULL) {
+ logit("%s: %d: unknown", __func__, id);
+ return 0;
+ }
+ if (channel_proxy_upstream(c, type, seq, ssh))
return 0;
- }
+ if (sshpkt_get_end(ssh) != 0)
+ ssh_packet_disconnect(ssh, "Invalid status confirm message");
if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL)
return 0;
- cc->cb(type, c, cc->ctx);
+ cc->cb(ssh, type, c, cc->ctx);
TAILQ_REMOVE(&c->status_confirms, cc, entry);
- explicit_bzero(cc, sizeof(*cc));
- free(cc);
+ freezero(cc, sizeof(*cc));
return 0;
}
/* -- tcp forwarding */
void
-channel_set_af(int af)
+channel_set_af(struct ssh *ssh, int af)
{
- IPv4or6 = af;
+ ssh->chanctxt->IPv4or6 = af;
}
@@ -2747,7 +3322,7 @@ channel_set_af(int af)
* "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set
*/
static const char *
-channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
+channel_fwd_bind_addr(struct ssh *ssh, const char *listen_addr, int *wildcardp,
int is_client, struct ForwardOptions *fwd_opts)
{
const char *addr = NULL;
@@ -2770,14 +3345,20 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
if (*listen_addr != '\0' &&
strcmp(listen_addr, "0.0.0.0") != 0 &&
strcmp(listen_addr, "*") != 0) {
- packet_send_debug("Forwarding listen address "
+ ssh_packet_send_debug(ssh,
+ "Forwarding listen address "
"\"%s\" overridden by server "
"GatewayPorts", listen_addr);
}
} else if (strcmp(listen_addr, "localhost") != 0 ||
strcmp(listen_addr, "127.0.0.1") == 0 ||
strcmp(listen_addr, "::1") == 0) {
- /* Accept localhost address when GatewayPorts=yes */
+ /*
+ * Accept explicit localhost address when
+ * GatewayPorts=yes. The "localhost" hostname is
+ * deliberately skipped here so it will listen on all
+ * available local address families.
+ */
addr = listen_addr;
}
} else if (strcmp(listen_addr, "127.0.0.1") == 0 ||
@@ -2795,8 +3376,9 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
}
static int
-channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
- int *allocated_listen_port, struct ForwardOptions *fwd_opts)
+channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type,
+ struct Forward *fwd, int *allocated_listen_port,
+ struct ForwardOptions *fwd_opts)
{
Channel *c;
int sock, r, success = 0, wildcard = 0, is_client;
@@ -2805,21 +3387,25 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
in_port_t *lport_p;
- host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
- fwd->listen_host : fwd->connect_host;
is_client = (type == SSH_CHANNEL_PORT_LISTENER);
- if (host == NULL) {
- error("No forward host name.");
- return 0;
- }
- if (strlen(host) >= NI_MAXHOST) {
- error("Forward host name too long.");
- return 0;
+ if (is_client && fwd->connect_path != NULL) {
+ host = fwd->connect_path;
+ } else {
+ host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
+ fwd->listen_host : fwd->connect_host;
+ if (host == NULL) {
+ error("No forward host name.");
+ return 0;
+ }
+ if (strlen(host) >= NI_MAXHOST) {
+ error("Forward host name too long.");
+ return 0;
+ }
}
/* Determine the bind address, cf. channel_fwd_bind_addr() comment */
- addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard,
+ addr = channel_fwd_bind_addr(ssh, fwd->listen_host, &wildcard,
is_client, fwd_opts);
debug3("%s: type %d wildcard %d addr %s", __func__,
type, wildcard, (addr == NULL) ? "NULL" : addr);
@@ -2829,14 +3415,14 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
* set to NULL and hints.ai_flags is not AI_PASSIVE
*/
memset(&hints, 0, sizeof(hints));
- hints.ai_family = IPv4or6;
+ hints.ai_family = ssh->chanctxt->IPv4or6;
hints.ai_flags = wildcard ? AI_PASSIVE : 0;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", fwd->listen_port);
if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
if (addr == NULL) {
/* This really shouldn't happen */
- packet_disconnect("getaddrinfo: fatal error: %s",
+ ssh_packet_disconnect(ssh, "getaddrinfo: fatal error: %s",
ssh_gai_strerror(r));
} else {
error("%s: getaddrinfo(%.64s): %s", __func__, addr,
@@ -2863,24 +3449,27 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
* If allocating a port for -R forwards, then use the
* same port for all address families.
*/
- if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
- allocated_listen_port != NULL && *allocated_listen_port > 0)
+ if (type == SSH_CHANNEL_RPORT_LISTENER &&
+ fwd->listen_port == 0 && allocated_listen_port != NULL &&
+ *allocated_listen_port > 0)
*lport_p = htons(*allocated_listen_port);
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
- strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
+ strport, sizeof(strport),
+ NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
error("%s: getnameinfo failed", __func__);
continue;
}
/* Create a port to listen for the host. */
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (sock < 0) {
+ if (sock == -1) {
/* this is no error since kernel may not support ipv6 */
- verbose("socket: %.100s", strerror(errno));
+ verbose("socket [%s]:%s: %.100s", ntop, strport,
+ strerror(errno));
continue;
}
- channel_set_reuseaddr(sock);
+ set_reuseaddr(sock);
if (ai->ai_family == AF_INET6)
sock_set_v6only(sock);
@@ -2888,19 +3477,26 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
ntop, strport);
/* Bind the socket to the address. */
- if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
- /* address can be in use ipv6 address is already bound */
+ if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
+ /*
+ * address can be in if use ipv6 address is
+ * already bound
+ */
if (!ai->ai_next)
- error("bind: %.100s", strerror(errno));
+ error("bind [%s]:%s: %.100s",
+ ntop, strport, strerror(errno));
else
- verbose("bind: %.100s", strerror(errno));
+ verbose("bind [%s]:%s: %.100s",
+ ntop, strport, strerror(errno));
close(sock);
continue;
}
/* Start listening for connections on the socket. */
- if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
+ if (listen(sock, SSH_LISTEN_BACKLOG) == -1) {
error("listen: %.100s", strerror(errno));
+ error("listen [%s]:%s: %.100s", ntop, strport,
+ strerror(errno));
close(sock);
continue;
}
@@ -2909,16 +3505,17 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
* fwd->listen_port == 0 requests a dynamically allocated port -
* record what we got.
*/
- if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
+ if (type == SSH_CHANNEL_RPORT_LISTENER &&
+ fwd->listen_port == 0 &&
allocated_listen_port != NULL &&
*allocated_listen_port == 0) {
- *allocated_listen_port = get_sock_port(sock, 1);
+ *allocated_listen_port = get_local_port(sock);
debug("Allocated listen port %d",
*allocated_listen_port);
}
/* Allocate a channel number for the socket. */
- c = channel_new("port listener", type, sock, sock, -1,
+ c = channel_new(ssh, "port listener", type, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, "port listener", 1);
c->path = xstrdup(host);
@@ -2939,8 +3536,8 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
}
static int
-channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd,
- struct ForwardOptions *fwd_opts)
+channel_setup_fwd_listener_streamlocal(struct ssh *ssh, int type,
+ struct Forward *fwd, struct ForwardOptions *fwd_opts)
{
struct sockaddr_un sunaddr;
const char *path;
@@ -3002,7 +3599,7 @@ channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd,
debug("Local forwarding listening on path %s.", fwd->listen_path);
/* Allocate a channel number for the socket. */
- c = channel_new("unix listener", type, sock, sock, -1,
+ c = channel_new(ssh, "unix listener", type, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, "unix listener", 1);
c->path = xstrdup(path);
@@ -3013,66 +3610,71 @@ channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd,
}
static int
-channel_cancel_rport_listener_tcpip(const char *host, u_short port)
+channel_cancel_rport_listener_tcpip(struct ssh *ssh,
+ const char *host, u_short port)
{
u_int i;
int found = 0;
- for (i = 0; i < channels_alloc; i++) {
- Channel *c = channels[i];
+ for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
+ Channel *c = ssh->chanctxt->channels[i];
if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER)
continue;
if (strcmp(c->path, host) == 0 && c->listening_port == port) {
debug2("%s: close channel %d", __func__, i);
- channel_free(c);
+ channel_free(ssh, c);
found = 1;
}
}
- return (found);
+ return found;
}
static int
-channel_cancel_rport_listener_streamlocal(const char *path)
+channel_cancel_rport_listener_streamlocal(struct ssh *ssh, const char *path)
{
u_int i;
int found = 0;
- for (i = 0; i < channels_alloc; i++) {
- Channel *c = channels[i];
+ for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
+ Channel *c = ssh->chanctxt->channels[i];
if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER)
continue;
if (c->path == NULL)
continue;
if (strcmp(c->path, path) == 0) {
debug2("%s: close channel %d", __func__, i);
- channel_free(c);
+ channel_free(ssh, c);
found = 1;
}
}
- return (found);
+ return found;
}
int
-channel_cancel_rport_listener(struct Forward *fwd)
+channel_cancel_rport_listener(struct ssh *ssh, struct Forward *fwd)
{
- if (fwd->listen_path != NULL)
- return channel_cancel_rport_listener_streamlocal(fwd->listen_path);
- else
- return channel_cancel_rport_listener_tcpip(fwd->listen_host, fwd->listen_port);
+ if (fwd->listen_path != NULL) {
+ return channel_cancel_rport_listener_streamlocal(ssh,
+ fwd->listen_path);
+ } else {
+ return channel_cancel_rport_listener_tcpip(ssh,
+ fwd->listen_host, fwd->listen_port);
+ }
}
static int
-channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport,
- int cport, struct ForwardOptions *fwd_opts)
+channel_cancel_lport_listener_tcpip(struct ssh *ssh,
+ const char *lhost, u_short lport, int cport,
+ struct ForwardOptions *fwd_opts)
{
u_int i;
int found = 0;
- const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts);
+ const char *addr = channel_fwd_bind_addr(ssh, lhost, NULL, 1, fwd_opts);
- for (i = 0; i < channels_alloc; i++) {
- Channel *c = channels[i];
+ for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
+ Channel *c = ssh->chanctxt->channels[i];
if (c == NULL || c->type != SSH_CHANNEL_PORT_LISTENER)
continue;
if (c->listening_port != lport)
@@ -3090,16 +3692,16 @@ channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport,
continue;
if (addr == NULL || strcmp(c->listening_addr, addr) == 0) {
debug2("%s: close channel %d", __func__, i);
- channel_free(c);
+ channel_free(ssh, c);
found = 1;
}
}
- return (found);
+ return found;
}
static int
-channel_cancel_lport_listener_streamlocal(const char *path)
+channel_cancel_lport_listener_streamlocal(struct ssh *ssh, const char *path)
{
u_int i;
int found = 0;
@@ -3109,54 +3711,143 @@ channel_cancel_lport_listener_streamlocal(const char *path)
return 0;
}
- for (i = 0; i < channels_alloc; i++) {
- Channel *c = channels[i];
+ for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
+ Channel *c = ssh->chanctxt->channels[i];
if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER)
continue;
if (c->listening_addr == NULL)
continue;
if (strcmp(c->listening_addr, path) == 0) {
debug2("%s: close channel %d", __func__, i);
- channel_free(c);
+ channel_free(ssh, c);
found = 1;
}
}
- return (found);
+ return found;
}
int
-channel_cancel_lport_listener(struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts)
+channel_cancel_lport_listener(struct ssh *ssh,
+ struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts)
{
- if (fwd->listen_path != NULL)
- return channel_cancel_lport_listener_streamlocal(fwd->listen_path);
- else
- return channel_cancel_lport_listener_tcpip(fwd->listen_host, fwd->listen_port, cport, fwd_opts);
+ if (fwd->listen_path != NULL) {
+ return channel_cancel_lport_listener_streamlocal(ssh,
+ fwd->listen_path);
+ } else {
+ return channel_cancel_lport_listener_tcpip(ssh,
+ fwd->listen_host, fwd->listen_port, cport, fwd_opts);
+ }
}
-/* protocol local port fwd, used by ssh (and sshd in v1) */
+/* protocol local port fwd, used by ssh */
int
-channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts)
+channel_setup_local_fwd_listener(struct ssh *ssh,
+ struct Forward *fwd, struct ForwardOptions *fwd_opts)
{
if (fwd->listen_path != NULL) {
- return channel_setup_fwd_listener_streamlocal(
+ return channel_setup_fwd_listener_streamlocal(ssh,
SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts);
} else {
- return channel_setup_fwd_listener_tcpip(SSH_CHANNEL_PORT_LISTENER,
- fwd, NULL, fwd_opts);
+ return channel_setup_fwd_listener_tcpip(ssh,
+ SSH_CHANNEL_PORT_LISTENER, fwd, NULL, fwd_opts);
}
}
+/* Matches a remote forwarding permission against a requested forwarding */
+static int
+remote_open_match(struct permission *allowed_open, struct Forward *fwd)
+{
+ int ret;
+ char *lhost;
+
+ /* XXX add ACLs for streamlocal */
+ if (fwd->listen_path != NULL)
+ return 1;
+
+ if (fwd->listen_host == NULL || allowed_open->listen_host == NULL)
+ return 0;
+
+ if (allowed_open->listen_port != FWD_PERMIT_ANY_PORT &&
+ allowed_open->listen_port != fwd->listen_port)
+ return 0;
+
+ /* Match hostnames case-insensitively */
+ lhost = xstrdup(fwd->listen_host);
+ lowercase(lhost);
+ ret = match_pattern(lhost, allowed_open->listen_host);
+ free(lhost);
+
+ return ret;
+}
+
+/* Checks whether a requested remote forwarding is permitted */
+static int
+check_rfwd_permission(struct ssh *ssh, struct Forward *fwd)
+{
+ struct ssh_channels *sc = ssh->chanctxt;
+ struct permission_set *pset = &sc->remote_perms;
+ u_int i, permit, permit_adm = 1;
+ struct permission *perm;
+
+ /* XXX apply GatewayPorts override before checking? */
+
+ permit = pset->all_permitted;
+ if (!permit) {
+ for (i = 0; i < pset->num_permitted_user; i++) {
+ perm = &pset->permitted_user[i];
+ if (remote_open_match(perm, fwd)) {
+ permit = 1;
+ break;
+ }
+ }
+ }
+
+ if (pset->num_permitted_admin > 0) {
+ permit_adm = 0;
+ for (i = 0; i < pset->num_permitted_admin; i++) {
+ perm = &pset->permitted_admin[i];
+ if (remote_open_match(perm, fwd)) {
+ permit_adm = 1;
+ break;
+ }
+ }
+ }
+
+ return permit && permit_adm;
+}
+
/* protocol v2 remote port fwd, used by sshd */
int
-channel_setup_remote_fwd_listener(struct Forward *fwd,
+channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd,
int *allocated_listen_port, struct ForwardOptions *fwd_opts)
{
+ if (!check_rfwd_permission(ssh, fwd)) {
+ ssh_packet_send_debug(ssh, "port forwarding refused");
+ if (fwd->listen_path != NULL)
+ /* XXX always allowed, see remote_open_match() */
+ logit("Received request from %.100s port %d to "
+ "remote forward to path \"%.100s\", "
+ "but the request was denied.",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+ fwd->listen_path);
+ else if(fwd->listen_host != NULL)
+ logit("Received request from %.100s port %d to "
+ "remote forward to host %.100s port %d, "
+ "but the request was denied.",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+ fwd->listen_host, fwd->listen_port );
+ else
+ logit("Received request from %.100s port %d to remote "
+ "forward, but the request was denied.",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
+ return 0;
+ }
if (fwd->listen_path != NULL) {
- return channel_setup_fwd_listener_streamlocal(
+ return channel_setup_fwd_listener_streamlocal(ssh,
SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts);
} else {
- return channel_setup_fwd_listener_tcpip(
+ return channel_setup_fwd_listener_tcpip(ssh,
SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port,
fwd_opts);
}
@@ -3170,15 +3861,9 @@ static const char *
channel_rfwd_bind_host(const char *listen_host)
{
if (listen_host == NULL) {
- if (datafellows & SSH_BUG_RFWD_ADDR)
- return "127.0.0.1";
- else
- return "localhost";
+ return "localhost";
} else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0) {
- if (datafellows & SSH_BUG_RFWD_ADDR)
- return "0.0.0.0";
- else
- return "";
+ return "";
} else
return listen_host;
}
@@ -3187,87 +3872,68 @@ channel_rfwd_bind_host(const char *listen_host)
* Initiate forwarding of connections to port "port" on remote host through
* the secure channel to host:port from local side.
* Returns handle (index) for updating the dynamic listen port with
- * channel_update_permitted_opens().
+ * channel_update_permission().
*/
int
-channel_request_remote_forwarding(struct Forward *fwd)
+channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
{
- int type, success = 0, idx = -1;
+ int r, success = 0, idx = -1;
+ char *host_to_connect, *listen_host, *listen_path;
+ int port_to_connect, listen_port;
/* Send the forward request to the remote side. */
- if (compat20) {
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- if (fwd->listen_path != NULL) {
- packet_put_cstring("streamlocal-forward@openssh.com");
- packet_put_char(1); /* boolean: want reply */
- packet_put_cstring(fwd->listen_path);
- } else {
- packet_put_cstring("tcpip-forward");
- packet_put_char(1); /* boolean: want reply */
- packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host));
- packet_put_int(fwd->listen_port);
- }
- packet_send();
- packet_write_wait();
- /* Assume that server accepts the request */
- success = 1;
- } else if (fwd->listen_path == NULL) {
- packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
- packet_put_int(fwd->listen_port);
- packet_put_cstring(fwd->connect_host);
- packet_put_int(fwd->connect_port);
- packet_send();
- packet_write_wait();
-
- /* Wait for response from the remote side. */
- type = packet_read();
- switch (type) {
- case SSH_SMSG_SUCCESS:
- success = 1;
- break;
- case SSH_SMSG_FAILURE:
- break;
- default:
- /* Unknown packet */
- packet_disconnect("Protocol error for port forward request:"
- "received packet type %d.", type);
- }
+ if (fwd->listen_path != NULL) {
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh,
+ "streamlocal-forward@openssh.com")) != 0 ||
+ (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */
+ (r = sshpkt_put_cstring(ssh, fwd->listen_path)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ fatal("%s: request streamlocal: %s",
+ __func__, ssh_err(r));
} else {
- logit("Warning: Server does not support remote stream local forwarding.");
- }
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "tcpip-forward")) != 0 ||
+ (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */
+ (r = sshpkt_put_cstring(ssh,
+ channel_rfwd_bind_host(fwd->listen_host))) != 0 ||
+ (r = sshpkt_put_u32(ssh, fwd->listen_port)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ fatal("%s: request tcpip-forward: %s",
+ __func__, ssh_err(r));
+ }
+ /* Assume that server accepts the request */
+ success = 1;
if (success) {
/* Record that connection to this host/port is permitted. */
- permitted_opens = xrealloc(permitted_opens,
- num_permitted_opens + 1, sizeof(*permitted_opens));
- idx = num_permitted_opens++;
+ host_to_connect = listen_host = listen_path = NULL;
+ port_to_connect = listen_port = 0;
if (fwd->connect_path != NULL) {
- permitted_opens[idx].host_to_connect =
- xstrdup(fwd->connect_path);
- permitted_opens[idx].port_to_connect =
- PORT_STREAMLOCAL;
+ host_to_connect = xstrdup(fwd->connect_path);
+ port_to_connect = PORT_STREAMLOCAL;
} else {
- permitted_opens[idx].host_to_connect =
- xstrdup(fwd->connect_host);
- permitted_opens[idx].port_to_connect =
- fwd->connect_port;
+ host_to_connect = xstrdup(fwd->connect_host);
+ port_to_connect = fwd->connect_port;
}
if (fwd->listen_path != NULL) {
- permitted_opens[idx].listen_host = NULL;
- permitted_opens[idx].listen_path =
- xstrdup(fwd->listen_path);
- permitted_opens[idx].listen_port = PORT_STREAMLOCAL;
+ listen_path = xstrdup(fwd->listen_path);
+ listen_port = PORT_STREAMLOCAL;
} else {
- permitted_opens[idx].listen_host =
- fwd->listen_host ? xstrdup(fwd->listen_host) : NULL;
- permitted_opens[idx].listen_path = NULL;
- permitted_opens[idx].listen_port = fwd->listen_port;
+ if (fwd->listen_host != NULL)
+ listen_host = xstrdup(fwd->listen_host);
+ listen_port = fwd->listen_port;
}
+ idx = permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL,
+ host_to_connect, port_to_connect,
+ listen_host, listen_path, listen_port, NULL);
}
- return (idx);
+ return idx;
}
static int
-open_match(ForwardPermission *allowed_open, const char *requestedhost,
+open_match(struct permission *allowed_open, const char *requestedhost,
int requestedport)
{
if (allowed_open->host_to_connect == NULL)
@@ -3275,7 +3941,8 @@ open_match(ForwardPermission *allowed_open, const char *requestedhost,
if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT &&
allowed_open->port_to_connect != requestedport)
return 0;
- if (strcmp(allowed_open->host_to_connect, requestedhost) != 0)
+ if (strcmp(allowed_open->host_to_connect, FWD_PERMIT_ANY_HOST) != 0 &&
+ strcmp(allowed_open->host_to_connect, requestedhost) != 0)
return 0;
return 1;
}
@@ -3287,7 +3954,7 @@ open_match(ForwardPermission *allowed_open, const char *requestedhost,
* and what we've sent to the remote server (channel_rfwd_bind_host)
*/
static int
-open_listen_match_tcpip(ForwardPermission *allowed_open,
+open_listen_match_tcpip(struct permission *allowed_open,
const char *requestedhost, u_short requestedport, int translate)
{
const char *allowed_host;
@@ -3302,14 +3969,14 @@ open_listen_match_tcpip(ForwardPermission *allowed_open,
allowed_host = translate ?
channel_rfwd_bind_host(allowed_open->listen_host) :
allowed_open->listen_host;
- if (allowed_host == NULL ||
+ if (allowed_host == NULL || requestedhost == NULL ||
strcmp(allowed_host, requestedhost) != 0)
return 0;
return 1;
}
static int
-open_listen_match_streamlocal(ForwardPermission *allowed_open,
+open_listen_match_streamlocal(struct permission *allowed_open,
const char *requestedpath)
{
if (allowed_open->host_to_connect == NULL)
@@ -3327,35 +3994,34 @@ open_listen_match_streamlocal(ForwardPermission *allowed_open,
* local side.
*/
static int
-channel_request_rforward_cancel_tcpip(const char *host, u_short port)
+channel_request_rforward_cancel_tcpip(struct ssh *ssh,
+ const char *host, u_short port)
{
- int i;
-
- if (!compat20)
- return -1;
+ struct ssh_channels *sc = ssh->chanctxt;
+ struct permission_set *pset = &sc->local_perms;
+ int r;
+ u_int i;
+ struct permission *perm = NULL;
- for (i = 0; i < num_permitted_opens; i++) {
- if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0))
+ for (i = 0; i < pset->num_permitted_user; i++) {
+ perm = &pset->permitted_user[i];
+ if (open_listen_match_tcpip(perm, host, port, 0))
break;
+ perm = NULL;
}
- if (i >= num_permitted_opens) {
+ if (perm == NULL) {
debug("%s: requested forward not found", __func__);
return -1;
}
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring("cancel-tcpip-forward");
- packet_put_char(0);
- packet_put_cstring(channel_rfwd_bind_host(host));
- packet_put_int(port);
- packet_send();
-
- permitted_opens[i].listen_port = 0;
- permitted_opens[i].port_to_connect = 0;
- free(permitted_opens[i].host_to_connect);
- permitted_opens[i].host_to_connect = NULL;
- free(permitted_opens[i].listen_host);
- permitted_opens[i].listen_host = NULL;
- permitted_opens[i].listen_path = NULL;
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "cancel-tcpip-forward")) != 0 ||
+ (r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */
+ (r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(host))) != 0 ||
+ (r = sshpkt_put_u32(ssh, port)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: send cancel: %s", __func__, ssh_err(r));
+
+ fwd_perm_clear(perm); /* unregister */
return 0;
}
@@ -3365,34 +4031,33 @@ channel_request_rforward_cancel_tcpip(const char *host, u_short port)
* path from local side.
*/
static int
-channel_request_rforward_cancel_streamlocal(const char *path)
+channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path)
{
- int i;
-
- if (!compat20)
- return -1;
+ struct ssh_channels *sc = ssh->chanctxt;
+ struct permission_set *pset = &sc->local_perms;
+ int r;
+ u_int i;
+ struct permission *perm = NULL;
- for (i = 0; i < num_permitted_opens; i++) {
- if (open_listen_match_streamlocal(&permitted_opens[i], path))
+ for (i = 0; i < pset->num_permitted_user; i++) {
+ perm = &pset->permitted_user[i];
+ if (open_listen_match_streamlocal(perm, path))
break;
+ perm = NULL;
}
- if (i >= num_permitted_opens) {
+ if (perm == NULL) {
debug("%s: requested forward not found", __func__);
return -1;
}
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring("cancel-streamlocal-forward@openssh.com");
- packet_put_char(0);
- packet_put_cstring(path);
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh,
+ "cancel-streamlocal-forward@openssh.com")) != 0 ||
+ (r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */
+ (r = sshpkt_put_cstring(ssh, path)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: send cancel: %s", __func__, ssh_err(r));
- permitted_opens[i].listen_port = 0;
- permitted_opens[i].port_to_connect = 0;
- free(permitted_opens[i].host_to_connect);
- permitted_opens[i].host_to_connect = NULL;
- permitted_opens[i].listen_host = NULL;
- free(permitted_opens[i].listen_path);
- permitted_opens[i].listen_path = NULL;
+ fwd_perm_clear(perm); /* unregister */
return 0;
}
@@ -3401,83 +4066,77 @@ channel_request_rforward_cancel_streamlocal(const char *path)
* Request cancellation of remote forwarding of a connection from local side.
*/
int
-channel_request_rforward_cancel(struct Forward *fwd)
+channel_request_rforward_cancel(struct ssh *ssh, struct Forward *fwd)
{
if (fwd->listen_path != NULL) {
- return (channel_request_rforward_cancel_streamlocal(
- fwd->listen_path));
+ return channel_request_rforward_cancel_streamlocal(ssh,
+ fwd->listen_path);
} else {
- return (channel_request_rforward_cancel_tcpip(fwd->listen_host,
- fwd->listen_port ? fwd->listen_port : fwd->allocated_port));
+ return channel_request_rforward_cancel_tcpip(ssh,
+ fwd->listen_host,
+ fwd->listen_port ? fwd->listen_port : fwd->allocated_port);
}
}
/*
- * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
- * listening for the port, and sends back a success reply (or disconnect
- * message if there was an error).
+ * Permits opening to any host/port if permitted_user[] is empty. This is
+ * usually called by the server, because the user could connect to any port
+ * anyway, and the server has no way to know but to trust the client anyway.
*/
-int
-channel_input_port_forward_request(int is_root, struct ForwardOptions *fwd_opts)
+void
+channel_permit_all(struct ssh *ssh, int where)
{
- int success = 0;
- struct Forward fwd;
+ struct permission_set *pset = permission_set_get(ssh, where);
- /* Get arguments from the packet. */
- memset(&fwd, 0, sizeof(fwd));
- fwd.listen_port = packet_get_int();
- fwd.connect_host = packet_get_string(NULL);
- fwd.connect_port = packet_get_int();
+ if (pset->num_permitted_user == 0)
+ pset->all_permitted = 1;
+}
+
+/*
+ * Permit the specified host/port for forwarding.
+ */
+void
+channel_add_permission(struct ssh *ssh, int who, int where,
+ char *host, int port)
+{
+ int local = where == FORWARD_LOCAL;
+ struct permission_set *pset = permission_set_get(ssh, where);
-#ifndef HAVE_CYGWIN
+ debug("allow %s forwarding to host %s port %d",
+ fwd_ident(who, where), host, port);
/*
- * Check that an unprivileged user is not trying to forward a
- * privileged port.
+ * Remote forwards set listen_host/port, local forwards set
+ * host/port_to_connect.
*/
- if (fwd.listen_port < IPPORT_RESERVED && !is_root)
- packet_disconnect(
- "Requested forwarding of port %d but user is not root.",
- fwd.listen_port);
- if (fwd.connect_port == 0)
- packet_disconnect("Dynamic forwarding denied.");
-#endif
-
- /* Initiate forwarding */
- success = channel_setup_local_fwd_listener(&fwd, fwd_opts);
-
- /* Free the argument string. */
- free(fwd.connect_host);
-
- return (success ? 0 : -1);
+ permission_set_add(ssh, who, where,
+ local ? host : 0, local ? port : 0,
+ local ? NULL : host, NULL, local ? 0 : port, NULL);
+ pset->all_permitted = 0;
}
/*
- * Permits opening to any host/port if permitted_opens[] is empty. This is
- * usually called by the server, because the user could connect to any port
- * anyway, and the server has no way to know but to trust the client anyway.
+ * Administratively disable forwarding.
*/
void
-channel_permit_all_opens(void)
+channel_disable_admin(struct ssh *ssh, int where)
{
- if (num_permitted_opens == 0)
- all_opens_permitted = 1;
+ channel_clear_permission(ssh, FORWARD_ADM, where);
+ permission_set_add(ssh, FORWARD_ADM, where,
+ NULL, 0, NULL, NULL, 0, NULL);
}
+/*
+ * Clear a list of permitted opens.
+ */
void
-channel_add_permitted_opens(char *host, int port)
+channel_clear_permission(struct ssh *ssh, int who, int where)
{
- debug("allow port forwarding to host %s port %d", host, port);
+ struct permission **permp;
+ u_int *npermp;
- permitted_opens = xrealloc(permitted_opens,
- num_permitted_opens + 1, sizeof(*permitted_opens));
- permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);
- permitted_opens[num_permitted_opens].port_to_connect = port;
- permitted_opens[num_permitted_opens].listen_host = NULL;
- permitted_opens[num_permitted_opens].listen_path = NULL;
- permitted_opens[num_permitted_opens].listen_port = 0;
- num_permitted_opens++;
-
- all_opens_permitted = 0;
+ permission_set_get_array(ssh, who, where, &permp, &npermp);
+ *permp = xrecallocarray(*permp, *npermp, 0, sizeof(**permp));
+ *npermp = 0;
}
/*
@@ -3486,105 +4145,26 @@ channel_add_permitted_opens(char *host, int port)
* passed then they entry will be invalidated.
*/
void
-channel_update_permitted_opens(int idx, int newport)
+channel_update_permission(struct ssh *ssh, int idx, int newport)
{
- if (idx < 0 || idx >= num_permitted_opens) {
- debug("channel_update_permitted_opens: index out of range:"
- " %d num_permitted_opens %d", idx, num_permitted_opens);
+ struct permission_set *pset = &ssh->chanctxt->local_perms;
+
+ if (idx < 0 || (u_int)idx >= pset->num_permitted_user) {
+ debug("%s: index out of range: %d num_permitted_user %d",
+ __func__, idx, pset->num_permitted_user);
return;
}
debug("%s allowed port %d for forwarding to host %s port %d",
newport > 0 ? "Updating" : "Removing",
newport,
- permitted_opens[idx].host_to_connect,
- permitted_opens[idx].port_to_connect);
- if (newport >= 0) {
- permitted_opens[idx].listen_port =
+ pset->permitted_user[idx].host_to_connect,
+ pset->permitted_user[idx].port_to_connect);
+ if (newport <= 0)
+ fwd_perm_clear(&pset->permitted_user[idx]);
+ else {
+ pset->permitted_user[idx].listen_port =
(datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport;
- } else {
- permitted_opens[idx].listen_port = 0;
- permitted_opens[idx].port_to_connect = 0;
- free(permitted_opens[idx].host_to_connect);
- permitted_opens[idx].host_to_connect = NULL;
- free(permitted_opens[idx].listen_host);
- permitted_opens[idx].listen_host = NULL;
- free(permitted_opens[idx].listen_path);
- permitted_opens[idx].listen_path = NULL;
- }
-}
-
-int
-channel_add_adm_permitted_opens(char *host, int port)
-{
- debug("config allows port forwarding to host %s port %d", host, port);
-
- permitted_adm_opens = xrealloc(permitted_adm_opens,
- num_adm_permitted_opens + 1, sizeof(*permitted_adm_opens));
- permitted_adm_opens[num_adm_permitted_opens].host_to_connect
- = xstrdup(host);
- permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;
- permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL;
- permitted_adm_opens[num_adm_permitted_opens].listen_path = NULL;
- permitted_adm_opens[num_adm_permitted_opens].listen_port = 0;
- return ++num_adm_permitted_opens;
-}
-
-void
-channel_disable_adm_local_opens(void)
-{
- channel_clear_adm_permitted_opens();
- permitted_adm_opens = xmalloc(sizeof(*permitted_adm_opens));
- permitted_adm_opens[num_adm_permitted_opens].host_to_connect = NULL;
- num_adm_permitted_opens = 1;
-}
-
-void
-channel_clear_permitted_opens(void)
-{
- int i;
-
- for (i = 0; i < num_permitted_opens; i++) {
- free(permitted_opens[i].host_to_connect);
- free(permitted_opens[i].listen_host);
- free(permitted_opens[i].listen_path);
- }
- free(permitted_opens);
- permitted_opens = NULL;
- num_permitted_opens = 0;
-}
-
-void
-channel_clear_adm_permitted_opens(void)
-{
- int i;
-
- for (i = 0; i < num_adm_permitted_opens; i++) {
- free(permitted_adm_opens[i].host_to_connect);
- free(permitted_adm_opens[i].listen_host);
- free(permitted_adm_opens[i].listen_path);
- }
- free(permitted_adm_opens);
- permitted_adm_opens = NULL;
- num_adm_permitted_opens = 0;
-}
-
-void
-channel_print_adm_permitted_opens(void)
-{
- int i;
-
- printf("permitopen");
- if (num_adm_permitted_opens == 0) {
- printf(" any\n");
- return;
}
- for (i = 0; i < num_adm_permitted_opens; i++)
- if (permitted_adm_opens[i].host_to_connect == NULL)
- printf(" none");
- else
- printf(" %s:%d", permitted_adm_opens[i].host_to_connect,
- permitted_adm_opens[i].port_to_connect);
- printf("\n");
}
/* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */
@@ -3606,7 +4186,8 @@ connect_next(struct channel_connect *cctx)
{
int sock, saved_errno;
struct sockaddr_un *sunaddr;
- char ntop[NI_MAXHOST], strport[MAX(NI_MAXSERV,sizeof(sunaddr->sun_path))];
+ char ntop[NI_MAXHOST];
+ char strport[MAXIMUM(NI_MAXSERV, sizeof(sunaddr->sun_path))];
for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
switch (cctx->ai->ai_family) {
@@ -3671,18 +4252,19 @@ channel_connect_ctx_free(struct channel_connect *cctx)
memset(cctx, 0, sizeof(*cctx));
}
-/* Return CONNECTING channel to remote host:port or local socket path */
-static Channel *
-connect_to(const char *name, int port, char *ctype, char *rname)
+/*
+ * Return connecting socket to remote host:port or local socket path,
+ * passing back the failure reason if appropriate.
+ */
+static int
+connect_to_helper(struct ssh *ssh, const char *name, int port, int socktype,
+ char *ctype, char *rname, struct channel_connect *cctx,
+ int *reason, const char **errmsg)
{
struct addrinfo hints;
int gaierr;
int sock = -1;
char strport[NI_MAXSERV];
- struct channel_connect cctx;
- Channel *c;
-
- memset(&cctx, 0, sizeof(cctx));
if (port == PORT_STREAMLOCAL) {
struct sockaddr_un *sunaddr;
@@ -3690,7 +4272,7 @@ connect_to(const char *name, int port, char *ctype, char *rname)
if (strlen(name) > sizeof(sunaddr->sun_path)) {
error("%.100s: %.100s", name, strerror(ENAMETOOLONG));
- return (NULL);
+ return -1;
}
/*
@@ -3703,52 +4285,92 @@ connect_to(const char *name, int port, char *ctype, char *rname)
ai->ai_addr = (struct sockaddr *)(ai + 1);
ai->ai_addrlen = sizeof(*sunaddr);
ai->ai_family = AF_UNIX;
- ai->ai_socktype = SOCK_STREAM;
+ ai->ai_socktype = socktype;
ai->ai_protocol = PF_UNSPEC;
sunaddr = (struct sockaddr_un *)ai->ai_addr;
sunaddr->sun_family = AF_UNIX;
strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path));
- cctx.aitop = ai;
+ cctx->aitop = ai;
} else {
memset(&hints, 0, sizeof(hints));
- hints.ai_family = IPv4or6;
- hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = ssh->chanctxt->IPv4or6;
+ hints.ai_socktype = socktype;
snprintf(strport, sizeof strport, "%d", port);
- if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) != 0) {
+ if ((gaierr = getaddrinfo(name, strport, &hints, &cctx->aitop))
+ != 0) {
+ if (errmsg != NULL)
+ *errmsg = ssh_gai_strerror(gaierr);
+ if (reason != NULL)
+ *reason = SSH2_OPEN_CONNECT_FAILED;
error("connect_to %.100s: unknown host (%s)", name,
ssh_gai_strerror(gaierr));
- return NULL;
+ return -1;
}
}
- cctx.host = xstrdup(name);
- cctx.port = port;
- cctx.ai = cctx.aitop;
+ cctx->host = xstrdup(name);
+ cctx->port = port;
+ cctx->ai = cctx->aitop;
- if ((sock = connect_next(&cctx)) == -1) {
+ if ((sock = connect_next(cctx)) == -1) {
error("connect to %.100s port %d failed: %s",
name, port, strerror(errno));
+ return -1;
+ }
+
+ return sock;
+}
+
+/* Return CONNECTING channel to remote host:port or local socket path */
+static Channel *
+connect_to(struct ssh *ssh, const char *host, int port,
+ char *ctype, char *rname)
+{
+ struct channel_connect cctx;
+ Channel *c;
+ int sock;
+
+ memset(&cctx, 0, sizeof(cctx));
+ sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname,
+ &cctx, NULL, NULL);
+ if (sock == -1) {
channel_connect_ctx_free(&cctx);
return NULL;
}
- c = channel_new(ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1,
+ c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
+ c->host_port = port;
+ c->path = xstrdup(host);
c->connect_ctx = cctx;
+
return c;
}
+/*
+ * returns either the newly connected channel or the downstream channel
+ * that needs to deal with this connection.
+ */
Channel *
-channel_connect_by_listen_address(const char *listen_host,
+channel_connect_by_listen_address(struct ssh *ssh, const char *listen_host,
u_short listen_port, char *ctype, char *rname)
{
- int i;
-
- for (i = 0; i < num_permitted_opens; i++) {
- if (open_listen_match_tcpip(&permitted_opens[i], listen_host,
- listen_port, 1)) {
- return connect_to(
- permitted_opens[i].host_to_connect,
- permitted_opens[i].port_to_connect, ctype, rname);
+ struct ssh_channels *sc = ssh->chanctxt;
+ struct permission_set *pset = &sc->local_perms;
+ u_int i;
+ struct permission *perm;
+
+ for (i = 0; i < pset->num_permitted_user; i++) {
+ perm = &pset->permitted_user[i];
+ if (open_listen_match_tcpip(perm,
+ listen_host, listen_port, 1)) {
+ if (perm->downstream)
+ return perm->downstream;
+ if (perm->port_to_connect == 0)
+ return rdynamic_connect_prepare(ssh,
+ ctype, rname);
+ return connect_to(ssh,
+ perm->host_to_connect, perm->port_to_connect,
+ ctype, rname);
}
}
error("WARNING: Server requests forwarding for unknown listen_port %d",
@@ -3757,15 +4379,20 @@ channel_connect_by_listen_address(const char *listen_host,
}
Channel *
-channel_connect_by_listen_path(const char *path, char *ctype, char *rname)
+channel_connect_by_listen_path(struct ssh *ssh, const char *path,
+ char *ctype, char *rname)
{
- int i;
-
- for (i = 0; i < num_permitted_opens; i++) {
- if (open_listen_match_streamlocal(&permitted_opens[i], path)) {
- return connect_to(
- permitted_opens[i].host_to_connect,
- permitted_opens[i].port_to_connect, ctype, rname);
+ struct ssh_channels *sc = ssh->chanctxt;
+ struct permission_set *pset = &sc->local_perms;
+ u_int i;
+ struct permission *perm;
+
+ for (i = 0; i < pset->num_permitted_user; i++) {
+ perm = &pset->permitted_user[i];
+ if (open_listen_match_streamlocal(perm, path)) {
+ return connect_to(ssh,
+ perm->host_to_connect, perm->port_to_connect,
+ ctype, rname);
}
}
error("WARNING: Server requests forwarding for unknown path %.100s",
@@ -3775,58 +4402,95 @@ channel_connect_by_listen_path(const char *path, char *ctype, char *rname)
/* Check if connecting to that port is permitted and connect. */
Channel *
-channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname)
+channel_connect_to_port(struct ssh *ssh, const char *host, u_short port,
+ char *ctype, char *rname, int *reason, const char **errmsg)
{
- int i, permit, permit_adm = 1;
+ struct ssh_channels *sc = ssh->chanctxt;
+ struct permission_set *pset = &sc->local_perms;
+ struct channel_connect cctx;
+ Channel *c;
+ u_int i, permit, permit_adm = 1;
+ int sock;
+ struct permission *perm;
- permit = all_opens_permitted;
+ permit = pset->all_permitted;
if (!permit) {
- for (i = 0; i < num_permitted_opens; i++)
- if (open_match(&permitted_opens[i], host, port)) {
+ for (i = 0; i < pset->num_permitted_user; i++) {
+ perm = &pset->permitted_user[i];
+ if (open_match(perm, host, port)) {
permit = 1;
break;
}
+ }
}
- if (num_adm_permitted_opens > 0) {
+ if (pset->num_permitted_admin > 0) {
permit_adm = 0;
- for (i = 0; i < num_adm_permitted_opens; i++)
- if (open_match(&permitted_adm_opens[i], host, port)) {
+ for (i = 0; i < pset->num_permitted_admin; i++) {
+ perm = &pset->permitted_admin[i];
+ if (open_match(perm, host, port)) {
permit_adm = 1;
break;
}
+ }
}
if (!permit || !permit_adm) {
- logit("Received request to connect to host %.100s port %d, "
- "but the request was denied.", host, port);
+ logit("Received request from %.100s port %d to connect to "
+ "host %.100s port %d, but the request was denied.",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), host, port);
+ if (reason != NULL)
+ *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
+ return NULL;
+ }
+
+ memset(&cctx, 0, sizeof(cctx));
+ sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname,
+ &cctx, reason, errmsg);
+ if (sock == -1) {
+ channel_connect_ctx_free(&cctx);
return NULL;
}
- return connect_to(host, port, ctype, rname);
+
+ c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1,
+ CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
+ c->host_port = port;
+ c->path = xstrdup(host);
+ c->connect_ctx = cctx;
+
+ return c;
}
/* Check if connecting to that path is permitted and connect. */
Channel *
-channel_connect_to_path(const char *path, char *ctype, char *rname)
+channel_connect_to_path(struct ssh *ssh, const char *path,
+ char *ctype, char *rname)
{
- int i, permit, permit_adm = 1;
+ struct ssh_channels *sc = ssh->chanctxt;
+ struct permission_set *pset = &sc->local_perms;
+ u_int i, permit, permit_adm = 1;
+ struct permission *perm;
- permit = all_opens_permitted;
+ permit = pset->all_permitted;
if (!permit) {
- for (i = 0; i < num_permitted_opens; i++)
- if (open_match(&permitted_opens[i], path, PORT_STREAMLOCAL)) {
+ for (i = 0; i < pset->num_permitted_user; i++) {
+ perm = &pset->permitted_user[i];
+ if (open_match(perm, path, PORT_STREAMLOCAL)) {
permit = 1;
break;
}
+ }
}
- if (num_adm_permitted_opens > 0) {
+ if (pset->num_permitted_admin > 0) {
permit_adm = 0;
- for (i = 0; i < num_adm_permitted_opens; i++)
- if (open_match(&permitted_adm_opens[i], path, PORT_STREAMLOCAL)) {
+ for (i = 0; i < pset->num_permitted_admin; i++) {
+ perm = &pset->permitted_admin[i];
+ if (open_match(perm, path, PORT_STREAMLOCAL)) {
permit_adm = 1;
break;
}
+ }
}
if (!permit || !permit_adm) {
@@ -3834,28 +4498,80 @@ channel_connect_to_path(const char *path, char *ctype, char *rname)
"but the request was denied.", path);
return NULL;
}
- return connect_to(path, PORT_STREAMLOCAL, ctype, rname);
+ return connect_to(ssh, path, PORT_STREAMLOCAL, ctype, rname);
}
void
-channel_send_window_changes(void)
+channel_send_window_changes(struct ssh *ssh)
{
- u_int i;
+ struct ssh_channels *sc = ssh->chanctxt;
struct winsize ws;
+ int r;
+ u_int i;
- for (i = 0; i < channels_alloc; i++) {
- if (channels[i] == NULL || !channels[i]->client_tty ||
- channels[i]->type != SSH_CHANNEL_OPEN)
+ for (i = 0; i < sc->channels_alloc; i++) {
+ if (sc->channels[i] == NULL || !sc->channels[i]->client_tty ||
+ sc->channels[i]->type != SSH_CHANNEL_OPEN)
continue;
- if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0)
+ if (ioctl(sc->channels[i]->rfd, TIOCGWINSZ, &ws) == -1)
continue;
- channel_request_start(i, "window-change", 0);
- packet_put_int((u_int)ws.ws_col);
- packet_put_int((u_int)ws.ws_row);
- packet_put_int((u_int)ws.ws_xpixel);
- packet_put_int((u_int)ws.ws_ypixel);
- packet_send();
+ channel_request_start(ssh, i, "window-change", 0);
+ if ((r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 ||
+ (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 ||
+ (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 ||
+ (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: channel %u: send window-change: %s",
+ __func__, i, ssh_err(r));
+ }
+}
+
+/* Return RDYNAMIC_OPEN channel: channel allows SOCKS, but is not connected */
+static Channel *
+rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname)
+{
+ Channel *c;
+ int r;
+
+ c = channel_new(ssh, ctype, SSH_CHANNEL_RDYNAMIC_OPEN, -1, -1, -1,
+ CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
+ c->host_port = 0;
+ c->path = NULL;
+
+ /*
+ * We need to open the channel before we have a FD,
+ * so that we can get SOCKS header from peer.
+ */
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) {
+ fatal("%s: channel %i: confirm: %s", __func__,
+ c->self, ssh_err(r));
+ }
+ return c;
+}
+
+/* Return CONNECTING socket to remote host:port or local socket path */
+static int
+rdynamic_connect_finish(struct ssh *ssh, Channel *c)
+{
+ struct channel_connect cctx;
+ int sock;
+
+ memset(&cctx, 0, sizeof(cctx));
+ sock = connect_to_helper(ssh, c->path, c->host_port, SOCK_STREAM, NULL,
+ NULL, &cctx, NULL, NULL);
+ if (sock == -1)
+ channel_connect_ctx_free(&cctx);
+ else {
+ /* similar to SSH_CHANNEL_CONNECTING but we've already sent the open */
+ c->type = SSH_CHANNEL_RDYNAMIC_FINISH;
+ c->connect_ctx = cctx;
+ channel_register_fds(ssh, c, sock, sock, -1, 0, 1, 0);
}
+ return sock;
}
/* -- X11 forwarding */
@@ -3866,8 +4582,9 @@ channel_send_window_changes(void)
* stored in display_numberp , or -1 if an error occurs.
*/
int
-x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
- int single_connection, u_int *display_numberp, int **chanids)
+x11_create_display_inet(struct ssh *ssh, int x11_display_offset,
+ int x11_use_localhost, int single_connection,
+ u_int *display_numberp, int **chanids)
{
Channel *nc = NULL;
int display_number, sock;
@@ -3884,20 +4601,22 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
display_number++) {
port = 6000 + display_number;
memset(&hints, 0, sizeof(hints));
- hints.ai_family = IPv4or6;
+ hints.ai_family = ssh->chanctxt->IPv4or6;
hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", port);
- if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {
+ if ((gaierr = getaddrinfo(NULL, strport,
+ &hints, &aitop)) != 0) {
error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr));
return -1;
}
for (ai = aitop; ai; ai = ai->ai_next) {
- if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+ if (ai->ai_family != AF_INET &&
+ ai->ai_family != AF_INET6)
continue;
sock = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
- if (sock < 0) {
+ if (sock == -1) {
if ((errno != EINVAL) && (errno != EAFNOSUPPORT)
#ifdef EPFNOSUPPORT
&& (errno != EPFNOSUPPORT)
@@ -3915,14 +4634,13 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
if (ai->ai_family == AF_INET6)
sock_set_v6only(sock);
if (x11_use_localhost)
- channel_set_reuseaddr(sock);
- if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
- debug2("bind port %d: %.100s", port, strerror(errno));
+ set_reuseaddr(sock);
+ if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
+ debug2("%s: bind port %d: %.100s", __func__,
+ port, strerror(errno));
close(sock);
-
- for (n = 0; n < num_socks; n++) {
+ for (n = 0; n < num_socks; n++)
close(socks[n]);
- }
num_socks = 0;
break;
}
@@ -3941,7 +4659,7 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
/* Start listening for connections on the socket. */
for (n = 0; n < num_socks; n++) {
sock = socks[n];
- if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
+ if (listen(sock, SSH_LISTEN_BACKLOG) == -1) {
error("listen: %.100s", strerror(errno));
close(sock);
return -1;
@@ -3952,7 +4670,7 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
*chanids = xcalloc(num_socks + 1, sizeof(**chanids));
for (n = 0; n < num_socks; n++) {
sock = socks[n];
- nc = channel_new("x11 listener",
+ nc = channel_new(ssh, "x11 listener",
SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
0, "X11 inet listener", 1);
@@ -3963,7 +4681,7 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
/* Return the display number for the DISPLAY environment variable. */
*display_numberp = display_number;
- return (0);
+ return 0;
}
static int
@@ -3973,7 +4691,7 @@ connect_local_xsocket_path(const char *pathname)
struct sockaddr_un addr;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0)
+ if (sock == -1)
error("socket: %.100s", strerror(errno));
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
@@ -3993,8 +4711,35 @@ connect_local_xsocket(u_int dnr)
return connect_local_xsocket_path(buf);
}
+#ifdef __APPLE__
+static int
+is_path_to_xsocket(const char *display, char *path, size_t pathlen)
+{
+ struct stat sbuf;
+
+ if (strlcpy(path, display, pathlen) >= pathlen) {
+ error("%s: display path too long", __func__);
+ return 0;
+ }
+ if (display[0] != '/')
+ return 0;
+ if (stat(path, &sbuf) == 0) {
+ return 1;
+ } else {
+ char *dot = strrchr(path, '.');
+ if (dot != NULL) {
+ *dot = '\0';
+ if (stat(path, &sbuf) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+#endif
+
int
-x11_connect_display(void)
+x11_connect_display(struct ssh *ssh)
{
u_int display_number;
const char *display;
@@ -4014,15 +4759,22 @@ x11_connect_display(void)
* connection to the real X server.
*/
- /* Check if the display is from launchd. */
#ifdef __APPLE__
- if (strncmp(display, "/tmp/launch", 11) == 0) {
- sock = connect_local_xsocket_path(display);
- if (sock < 0)
- return -1;
+ /* Check if display is a path to a socket (as set by launchd). */
+ {
+ char path[PATH_MAX];
- /* OK, we now have a connection to the display. */
- return sock;
+ if (is_path_to_xsocket(display, path, sizeof(path))) {
+ debug("x11_connect_display: $DISPLAY is launchd");
+
+ /* Create a socket. */
+ sock = connect_local_xsocket_path(path);
+ if (sock < 0)
+ return -1;
+
+ /* OK, we now have a connection to the display. */
+ return sock;
+ }
}
#endif
/*
@@ -4032,9 +4784,10 @@ x11_connect_display(void)
if (strncmp(display, "unix:", 5) == 0 ||
display[0] == ':') {
/* Connect to the unix domain socket. */
- if (sscanf(strrchr(display, ':') + 1, "%u", &display_number) != 1) {
- error("Could not parse display number from DISPLAY: %.100s",
- display);
+ if (sscanf(strrchr(display, ':') + 1, "%u",
+ &display_number) != 1) {
+ error("Could not parse display number from DISPLAY: "
+ "%.100s", display);
return -1;
}
/* Create a socket. */
@@ -4056,7 +4809,10 @@ x11_connect_display(void)
return -1;
}
*cp = 0;
- /* buf now contains the host name. But first we parse the display number. */
+ /*
+ * buf now contains the host name. But first we parse the
+ * display number.
+ */
if (sscanf(cp + 1, "%u", &display_number) != 1) {
error("Could not parse display number from DISPLAY: %.100s",
display);
@@ -4065,7 +4821,7 @@ x11_connect_display(void)
/* Look up the host address */
memset(&hints, 0, sizeof(hints));
- hints.ai_family = IPv4or6;
+ hints.ai_family = ssh->chanctxt->IPv4or6;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%u", 6000 + display_number);
if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
@@ -4076,12 +4832,12 @@ x11_connect_display(void)
for (ai = aitop; ai; ai = ai->ai_next) {
/* Create a socket. */
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (sock < 0) {
+ if (sock == -1) {
debug2("socket: %.100s", strerror(errno));
continue;
}
/* Connect it to the display. */
- if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
+ if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
debug2("connect %.100s port %u: %.100s", buf,
6000 + display_number, strerror(errno));
close(sock);
@@ -4092,8 +4848,8 @@ x11_connect_display(void)
}
freeaddrinfo(aitop);
if (!ai) {
- error("connect %.100s port %u: %.100s", buf, 6000 + display_number,
- strerror(errno));
+ error("connect %.100s port %u: %.100s", buf,
+ 6000 + display_number, strerror(errno));
return -1;
}
set_nodelay(sock);
@@ -4101,99 +4857,24 @@ x11_connect_display(void)
}
/*
- * This is called when SSH_SMSG_X11_OPEN is received. The packet contains
- * the remote channel number. We should do whatever we want, and respond
- * with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE.
- */
-
-/* ARGSUSED */
-int
-x11_input_open(int type, u_int32_t seq, void *ctxt)
-{
- Channel *c = NULL;
- int remote_id, sock = 0;
- char *remote_host;
-
- debug("Received X11 open request.");
-
- remote_id = packet_get_int();
-
- if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) {
- remote_host = packet_get_string(NULL);
- } else {
- remote_host = xstrdup("unknown (remote did not supply name)");
- }
- packet_check_eom();
-
- /* Obtain a connection to the real X display. */
- sock = x11_connect_display();
- if (sock != -1) {
- /* Allocate a channel for this connection. */
- c = channel_new("connected x11 socket",
- SSH_CHANNEL_X11_OPEN, sock, sock, -1, 0, 0, 0,
- remote_host, 1);
- c->remote_id = remote_id;
- c->force_drain = 1;
- }
- free(remote_host);
- if (c == NULL) {
- /* Send refusal to the remote host. */
- packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(remote_id);
- } else {
- /* Send a confirmation to the remote host. */
- packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(remote_id);
- packet_put_int(c->self);
- }
- packet_send();
- return 0;
-}
-
-/* dummy protocol handler that denies SSH-1 requests (agent/x11) */
-/* ARGSUSED */
-int
-deny_input_open(int type, u_int32_t seq, void *ctxt)
-{
- int rchan = packet_get_int();
-
- switch (type) {
- case SSH_SMSG_AGENT_OPEN:
- error("Warning: ssh server tried agent forwarding.");
- break;
- case SSH_SMSG_X11_OPEN:
- error("Warning: ssh server tried X11 forwarding.");
- break;
- default:
- error("deny_input_open: type %d", type);
- break;
- }
- error("Warning: this is probably a break-in attempt by a malicious server.");
- packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(rchan);
- packet_send();
- return 0;
-}
-
-/*
* Requests forwarding of X11 connections, generates fake authentication
* data, and enables authentication spoofing.
* This should be called in the client only.
*/
void
-x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
- const char *proto, const char *data, int want_reply)
+x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id,
+ const char *disp, const char *proto, const char *data, int want_reply)
{
+ struct ssh_channels *sc = ssh->chanctxt;
u_int data_len = (u_int) strlen(data) / 2;
u_int i, value;
- char *new_data;
- int screen_number;
const char *cp;
- u_int32_t rnd = 0;
+ char *new_data;
+ int r, screen_number;
- if (x11_saved_display == NULL)
- x11_saved_display = xstrdup(disp);
- else if (strcmp(disp, x11_saved_display) != 0) {
+ if (sc->x11_saved_display == NULL)
+ sc->x11_saved_display = xstrdup(disp);
+ else if (strcmp(disp, sc->x11_saved_display) != 0) {
error("x11_request_forwarding_with_spoofing: different "
"$DISPLAY already forwarded");
return;
@@ -4207,56 +4888,37 @@ x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
else
screen_number = 0;
- if (x11_saved_proto == NULL) {
+ if (sc->x11_saved_proto == NULL) {
/* Save protocol name. */
- x11_saved_proto = xstrdup(proto);
- /*
- * Extract real authentication data and generate fake data
- * of the same length.
- */
- x11_saved_data = xmalloc(data_len);
- x11_fake_data = xmalloc(data_len);
+ sc->x11_saved_proto = xstrdup(proto);
+
+ /* Extract real authentication data. */
+ sc->x11_saved_data = xmalloc(data_len);
for (i = 0; i < data_len; i++) {
if (sscanf(data + 2 * i, "%2x", &value) != 1)
fatal("x11_request_forwarding: bad "
"authentication data: %.100s", data);
- if (i % 4 == 0)
- rnd = arc4random();
- x11_saved_data[i] = value;
- x11_fake_data[i] = rnd & 0xff;
- rnd >>= 8;
+ sc->x11_saved_data[i] = value;
}
- x11_saved_data_len = data_len;
- x11_fake_data_len = data_len;
+ sc->x11_saved_data_len = data_len;
+
+ /* Generate fake data of the same length. */
+ sc->x11_fake_data = xmalloc(data_len);
+ arc4random_buf(sc->x11_fake_data, data_len);
+ sc->x11_fake_data_len = data_len;
}
/* Convert the fake data into hex. */
- new_data = tohex(x11_fake_data, data_len);
+ new_data = tohex(sc->x11_fake_data, data_len);
/* Send the request packet. */
- if (compat20) {
- channel_request_start(client_session_id, "x11-req", want_reply);
- packet_put_char(0); /* XXX bool single connection */
- } else {
- packet_start(SSH_CMSG_X11_REQUEST_FORWARDING);
- }
- packet_put_cstring(proto);
- packet_put_cstring(new_data);
- packet_put_int(screen_number);
- packet_send();
- packet_write_wait();
+ channel_request_start(ssh, client_session_id, "x11-req", want_reply);
+ if ((r = sshpkt_put_u8(ssh, 0)) != 0 || /* bool: single connection */
+ (r = sshpkt_put_cstring(ssh, proto)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, new_data)) != 0 ||
+ (r = sshpkt_put_u32(ssh, screen_number)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ fatal("%s: send x11-req: %s", __func__, ssh_err(r));
free(new_data);
}
-
-
-/* -- agent forwarding */
-
-/* Sends a message to the server to request authentication fd forwarding. */
-
-void
-auth_request_forwarding(void)
-{
- packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING);
- packet_send();
- packet_write_wait();
-}
diff --git a/channels.h b/channels.h
index 5a672f22..c8ae0d90 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.h,v 1.116 2015/01/19 20:07:45 markus Exp $ */
+/* $OpenBSD: channels.h,v 1.133 2020/01/25 22:49:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -46,8 +46,6 @@
#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
#define SSH_CHANNEL_AUTH_SOCKET 6 /* authentication socket */
#define SSH_CHANNEL_X11_OPEN 7 /* reading first X11 packet */
-#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */
-#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */
#define SSH_CHANNEL_LARVAL 10 /* larval session */
#define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */
#define SSH_CHANNEL_CONNECTING 12
@@ -58,22 +56,37 @@
#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_MAX_TYPE 20
+#define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-slave */
+#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
+/* TCP forwarding */
+#define FORWARD_DENY 0
+#define FORWARD_REMOTE (1)
+#define FORWARD_LOCAL (1<<1)
+#define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL)
+
+#define FORWARD_ADM 0x100
+#define FORWARD_USER 0x101
+
+struct ssh;
struct Channel;
typedef struct Channel Channel;
+struct fwd_perm_list;
-typedef void channel_open_fn(int, int, void *);
-typedef void channel_callback_fn(int, void *);
-typedef int channel_infilter_fn(struct Channel *, char *, int);
-typedef void channel_filter_cleanup_fn(int, void *);
-typedef u_char *channel_outfilter_fn(struct Channel *, u_char **, u_int *);
+typedef void channel_open_fn(struct ssh *, int, int, void *);
+typedef void channel_callback_fn(struct ssh *, int, void *);
+typedef int channel_infilter_fn(struct ssh *, struct Channel *, char *, int);
+typedef void channel_filter_cleanup_fn(struct ssh *, int, void *);
+typedef u_char *channel_outfilter_fn(struct ssh *, struct Channel *,
+ u_char **, size_t *);
/* Channel success/failure callbacks */
-typedef void channel_confirm_cb(int, struct Channel *, void *);
-typedef void channel_confirm_abandon_cb(struct Channel *, void *);
+typedef void channel_confirm_cb(struct ssh *, int, struct Channel *, void *);
+typedef void channel_confirm_abandon_cb(struct ssh *, struct Channel *, void *);
struct channel_confirm {
TAILQ_ENTRY(channel_confirm) entry;
channel_confirm_cb *cb;
@@ -90,12 +103,22 @@ struct channel_connect {
};
/* Callbacks for mux channels back into client-specific code */
-typedef int mux_callback_fn(struct Channel *);
+typedef int mux_callback_fn(struct ssh *, struct Channel *);
+
+/*
+ * NB. channel IDs on the wire and in c->remote_id are uint32, but local
+ * channel IDs (e.g. c->self) only ever use the int32 subset of this range,
+ * because we use local channel ID -1 for housekeeping. Remote channels have
+ * a dedicated "have_remote_id" flag to indicate their validity.
+ */
struct Channel {
int type; /* channel type/state */
+
int self; /* my own channel identifier */
- int remote_id; /* channel identifier for remote peer */
+ uint32_t remote_id; /* channel identifier for remote peer */
+ int have_remote_id; /* non-zero if remote_id is valid */
+
u_int istate; /* input from channel (state of receive half) */
u_int ostate; /* output to channel (state of transmit half) */
int flags; /* close sent/rcvd */
@@ -113,14 +136,15 @@ struct Channel {
time_t notbefore; /* Pause IO until deadline (time_t) */
int delayed; /* post-select handlers for newly created
* channels are delayed until the first call
- * to a matching pre-select handler.
+ * to a matching pre-select handler.
* this way post-select handlers are not
* accidentally called if a FD gets reused */
- Buffer input; /* data read from socket, to be sent over
+ struct sshbuf *input; /* data read from socket, to be sent over
* encrypted connection */
- Buffer output; /* data received over encrypted connection for
+ struct sshbuf *output; /* data received over encrypted connection for
* send on socket */
- Buffer extended;
+ struct sshbuf *extended;
+
char *path;
/* path for unix domain sockets, or host name for forwards */
int listening_port; /* port being listened for forwards */
@@ -156,12 +180,14 @@ struct Channel {
int datagram;
/* non-blocking connect */
+ /* XXX make this a pointer so the structure can be opaque */
struct channel_connect connect_ctx;
/* multiplexing protocol hook, called for each packet received */
mux_callback_fn *mux_rcb;
void *mux_ctx;
int mux_pause;
+ int mux_downstream_id;
};
#define CHAN_EXTENDED_IGNORE 0
@@ -194,121 +220,133 @@ struct Channel {
#define CHAN_EOF_RCVD 0x08
#define CHAN_LOCAL 0x10
-#define CHAN_RBUF 16*1024
+/* Read buffer size */
+#define CHAN_RBUF (16*1024)
+
+/* Hard limit on number of channels */
+#define CHANNELS_MAX_CHANNELS (16*1024)
/* check whether 'efd' is still in use */
#define CHANNEL_EFD_INPUT_ACTIVE(c) \
- (compat20 && c->extended_usage == CHAN_EXTENDED_READ && \
+ (c->extended_usage == CHAN_EXTENDED_READ && \
(c->efd != -1 || \
- buffer_len(&c->extended) > 0))
+ sshbuf_len(c->extended) > 0))
#define CHANNEL_EFD_OUTPUT_ACTIVE(c) \
- (compat20 && c->extended_usage == CHAN_EXTENDED_WRITE && \
+ (c->extended_usage == CHAN_EXTENDED_WRITE && \
c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \
- buffer_len(&c->extended) > 0))
+ sshbuf_len(c->extended) > 0))
+
+/* Add channel management structures to SSH transport instance */
+void channel_init_channels(struct ssh *ssh);
/* channel management */
-Channel *channel_by_id(int);
-Channel *channel_lookup(int);
-Channel *channel_new(char *, int, int, int, int, u_int, u_int, int, char *, int);
-void channel_set_fds(int, int, int, int, int, int, int, u_int);
-void channel_free(Channel *);
-void channel_free_all(void);
-void channel_stop_listening(void);
-
-void channel_send_open(int);
-void channel_request_start(int, char *, int);
-void channel_register_cleanup(int, channel_callback_fn *, int);
-void channel_register_open_confirm(int, channel_open_fn *, void *);
-void channel_register_filter(int, channel_infilter_fn *,
- channel_outfilter_fn *, channel_filter_cleanup_fn *, void *);
-void channel_register_status_confirm(int, channel_confirm_cb *,
- channel_confirm_abandon_cb *, void *);
-void channel_cancel_cleanup(int);
-int channel_close_fd(int *);
-void channel_send_window_changes(void);
+Channel *channel_by_id(struct ssh *, int);
+Channel *channel_by_remote_id(struct ssh *, u_int);
+Channel *channel_lookup(struct ssh *, int);
+Channel *channel_new(struct ssh *, char *, int, int, int, int,
+ u_int, u_int, int, char *, int);
+void channel_set_fds(struct ssh *, int, int, int, int, int,
+ int, int, u_int);
+void channel_free(struct ssh *, Channel *);
+void channel_free_all(struct ssh *);
+void channel_stop_listening(struct ssh *);
+
+void channel_send_open(struct ssh *, int);
+void channel_request_start(struct ssh *, int, char *, int);
+void channel_register_cleanup(struct ssh *, int,
+ channel_callback_fn *, int);
+void channel_register_open_confirm(struct ssh *, int,
+ channel_open_fn *, void *);
+void channel_register_filter(struct ssh *, int, channel_infilter_fn *,
+ channel_outfilter_fn *, channel_filter_cleanup_fn *, void *);
+void channel_register_status_confirm(struct ssh *, int,
+ channel_confirm_cb *, channel_confirm_abandon_cb *, void *);
+void channel_cancel_cleanup(struct ssh *, int);
+int channel_close_fd(struct ssh *, int *);
+void channel_send_window_changes(struct ssh *);
+
+/* mux proxy support */
+
+int channel_proxy_downstream(struct ssh *, Channel *mc);
+int channel_proxy_upstream(Channel *, int, u_int32_t, struct ssh *);
/* protocol handler */
-int channel_input_close(int, u_int32_t, void *);
-int channel_input_close_confirmation(int, u_int32_t, void *);
-int channel_input_data(int, u_int32_t, void *);
-int channel_input_extended_data(int, u_int32_t, void *);
-int channel_input_ieof(int, u_int32_t, void *);
-int channel_input_oclose(int, u_int32_t, void *);
-int channel_input_open_confirmation(int, u_int32_t, void *);
-int channel_input_open_failure(int, u_int32_t, void *);
-int channel_input_port_open(int, u_int32_t, void *);
-int channel_input_window_adjust(int, u_int32_t, void *);
-int channel_input_status_confirm(int, u_int32_t, void *);
+int channel_input_data(int, u_int32_t, struct ssh *);
+int channel_input_extended_data(int, u_int32_t, struct ssh *);
+int channel_input_ieof(int, u_int32_t, struct ssh *);
+int channel_input_oclose(int, u_int32_t, struct ssh *);
+int channel_input_open_confirmation(int, u_int32_t, struct ssh *);
+int channel_input_open_failure(int, u_int32_t, struct ssh *);
+int channel_input_port_open(int, u_int32_t, struct ssh *);
+int channel_input_window_adjust(int, u_int32_t, struct ssh *);
+int channel_input_status_confirm(int, u_int32_t, struct ssh *);
/* file descriptor handling (read/write) */
-void channel_prepare_select(fd_set **, fd_set **, int *, u_int*,
- time_t*, int);
-void channel_after_select(fd_set *, fd_set *);
-void channel_output_poll(void);
+void channel_prepare_select(struct ssh *, fd_set **, fd_set **, int *,
+ u_int*, time_t*);
+void channel_after_select(struct ssh *, fd_set *, fd_set *);
+void channel_output_poll(struct ssh *);
-int channel_not_very_much_buffered_data(void);
-void channel_close_all(void);
-int channel_still_open(void);
-char *channel_open_message(void);
-int channel_find_open(void);
+int channel_not_very_much_buffered_data(struct ssh *);
+void channel_close_all(struct ssh *);
+int channel_still_open(struct ssh *);
+const char *channel_format_extended_usage(const Channel *);
+char *channel_open_message(struct ssh *);
+int channel_find_open(struct ssh *);
/* tcp forwarding */
struct Forward;
struct ForwardOptions;
-void channel_set_af(int af);
-void channel_permit_all_opens(void);
-void channel_add_permitted_opens(char *, int);
-int channel_add_adm_permitted_opens(char *, int);
-void channel_disable_adm_local_opens(void);
-void channel_update_permitted_opens(int, int);
-void channel_clear_permitted_opens(void);
-void channel_clear_adm_permitted_opens(void);
-void channel_print_adm_permitted_opens(void);
-int channel_input_port_forward_request(int, struct ForwardOptions *);
-Channel *channel_connect_to_port(const char *, u_short, char *, char *);
-Channel *channel_connect_to_path(const char *, char *, char *);
-Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
-Channel *channel_connect_by_listen_address(const char *, u_short,
- char *, char *);
-Channel *channel_connect_by_listen_path(const char *, char *, char *);
-int channel_request_remote_forwarding(struct Forward *);
-int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *);
-int channel_request_rforward_cancel(struct Forward *);
-int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *);
-int channel_cancel_rport_listener(struct Forward *);
-int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *);
+void channel_set_af(struct ssh *, int af);
+void channel_permit_all(struct ssh *, int);
+void channel_add_permission(struct ssh *, int, int, char *, int);
+void channel_clear_permission(struct ssh *, int, int);
+void channel_disable_admin(struct ssh *, int);
+void channel_update_permission(struct ssh *, int, int);
+Channel *channel_connect_to_port(struct ssh *, const char *, u_short,
+ char *, char *, int *, const char **);
+Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *);
+Channel *channel_connect_stdio_fwd(struct ssh *, const char*,
+ u_short, int, int);
+Channel *channel_connect_by_listen_address(struct ssh *, const char *,
+ u_short, char *, char *);
+Channel *channel_connect_by_listen_path(struct ssh *, const char *,
+ char *, char *);
+int channel_request_remote_forwarding(struct ssh *, struct Forward *);
+int channel_setup_local_fwd_listener(struct ssh *, struct Forward *,
+ struct ForwardOptions *);
+int channel_request_rforward_cancel(struct ssh *, struct Forward *);
+int channel_setup_remote_fwd_listener(struct ssh *, struct Forward *,
+ int *, struct ForwardOptions *);
+int channel_cancel_rport_listener(struct ssh *, struct Forward *);
+int channel_cancel_lport_listener(struct ssh *, struct Forward *,
+ int, struct ForwardOptions *);
int permitopen_port(const char *);
/* x11 forwarding */
-int x11_connect_display(void);
-int x11_create_display_inet(int, int, int, u_int *, int **);
-int x11_input_open(int, u_int32_t, void *);
-void x11_request_forwarding_with_spoofing(int, const char *, const char *,
- const char *, int);
-int deny_input_open(int, u_int32_t, void *);
-
-/* agent forwarding */
-
-void auth_request_forwarding(void);
+void channel_set_x11_refuse_time(struct ssh *, u_int);
+int x11_connect_display(struct ssh *);
+int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **);
+void x11_request_forwarding_with_spoofing(struct ssh *, int,
+ const char *, const char *, const char *, int);
/* channel close */
-int chan_is_dead(Channel *, int);
-void chan_mark_dead(Channel *);
+int chan_is_dead(struct ssh *, Channel *, int);
+void chan_mark_dead(struct ssh *, Channel *);
/* channel events */
-void chan_rcvd_oclose(Channel *);
-void chan_rcvd_eow(Channel *); /* SSH2-only */
-void chan_read_failed(Channel *);
-void chan_ibuf_empty(Channel *);
-
-void chan_rcvd_ieof(Channel *);
-void chan_write_failed(Channel *);
-void chan_obuf_empty(Channel *);
+void chan_rcvd_oclose(struct ssh *, Channel *);
+void chan_rcvd_eow(struct ssh *, Channel *);
+void chan_read_failed(struct ssh *, Channel *);
+void chan_ibuf_empty(struct ssh *, Channel *);
+void chan_rcvd_ieof(struct ssh *, Channel *);
+void chan_write_failed(struct ssh *, Channel *);
+void chan_obuf_empty(struct ssh *, Channel *);
#endif
diff --git a/cipher-3des1.c b/cipher-3des1.c
deleted file mode 100644
index 6a0f1f37..00000000
--- a/cipher-3des1.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/* $OpenBSD: cipher-3des1.c,v 1.12 2015/01/14 10:24:42 markus Exp $ */
-/*
- * Copyright (c) 2003 Markus Friedl. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * 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 <string.h>
-#include <openssl/evp.h>
-
-#include "ssherr.h"
-
-/*
- * This is used by SSH1:
- *
- * What kind of triple DES are these 2 routines?
- *
- * Why is there a redundant initialization vector?
- *
- * If only iv3 was used, then, this would till effect have been
- * outer-cbc. However, there is also a private iv1 == iv2 which
- * perhaps makes differential analysis easier. On the other hand, the
- * private iv1 probably makes the CRC-32 attack ineffective. This is a
- * result of that there is no longer any known iv1 to use when
- * choosing the X block.
- */
-struct ssh1_3des_ctx
-{
- EVP_CIPHER_CTX k1, k2, k3;
-};
-
-const EVP_CIPHER * evp_ssh1_3des(void);
-int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
-
-static int
-ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
- int enc)
-{
- struct ssh1_3des_ctx *c;
- u_char *k1, *k2, *k3;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
- if ((c = calloc(1, sizeof(*c))) == NULL)
- return 0;
- EVP_CIPHER_CTX_set_app_data(ctx, c);
- }
- if (key == NULL)
- return 1;
- if (enc == -1)
- enc = ctx->encrypt;
- k1 = k2 = k3 = (u_char *) key;
- k2 += 8;
- if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
- if (enc)
- k3 += 16;
- else
- k1 += 16;
- }
- EVP_CIPHER_CTX_init(&c->k1);
- EVP_CIPHER_CTX_init(&c->k2);
- EVP_CIPHER_CTX_init(&c->k3);
- if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
- EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
- EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
- explicit_bzero(c, sizeof(*c));
- free(c);
- EVP_CIPHER_CTX_set_app_data(ctx, NULL);
- return 0;
- }
- return 1;
-}
-
-static int
-ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len)
-{
- struct ssh1_3des_ctx *c;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
- return 0;
- if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
- EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
- EVP_Cipher(&c->k3, dest, dest, len) == 0)
- return 0;
- return 1;
-}
-
-static int
-ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
-{
- struct ssh1_3des_ctx *c;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
- EVP_CIPHER_CTX_cleanup(&c->k1);
- EVP_CIPHER_CTX_cleanup(&c->k2);
- EVP_CIPHER_CTX_cleanup(&c->k3);
- explicit_bzero(c, sizeof(*c));
- free(c);
- EVP_CIPHER_CTX_set_app_data(ctx, NULL);
- }
- return 1;
-}
-
-int
-ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
-{
- struct ssh1_3des_ctx *c;
-
- if (len != 24)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
- return SSH_ERR_INTERNAL_ERROR;
- if (doset) {
- memcpy(c->k1.iv, iv, 8);
- memcpy(c->k2.iv, iv + 8, 8);
- memcpy(c->k3.iv, iv + 16, 8);
- } else {
- memcpy(iv, c->k1.iv, 8);
- memcpy(iv + 8, c->k2.iv, 8);
- memcpy(iv + 16, c->k3.iv, 8);
- }
- return 0;
-}
-
-const EVP_CIPHER *
-evp_ssh1_3des(void)
-{
- static EVP_CIPHER ssh1_3des;
-
- memset(&ssh1_3des, 0, sizeof(ssh1_3des));
- ssh1_3des.nid = NID_undef;
- ssh1_3des.block_size = 8;
- ssh1_3des.iv_len = 0;
- ssh1_3des.key_len = 16;
- ssh1_3des.init = ssh1_3des_init;
- ssh1_3des.cleanup = ssh1_3des_cleanup;
- ssh1_3des.do_cipher = ssh1_3des_cbc;
- ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
- return &ssh1_3des;
-}
diff --git a/cipher-bf1.c b/cipher-bf1.c
deleted file mode 100644
index ee72ac08..00000000
--- a/cipher-bf1.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/* $OpenBSD: cipher-bf1.c,v 1.7 2015/01/14 10:24:42 markus Exp $ */
-/*
- * Copyright (c) 2003 Markus Friedl. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#ifdef WITH_OPENSSL
-
-#include <sys/types.h>
-
-#include <stdarg.h>
-#include <string.h>
-
-#include <openssl/evp.h>
-
-#include "openbsd-compat/openssl-compat.h"
-
-/*
- * SSH1 uses a variation on Blowfish, all bytes must be swapped before
- * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
- */
-
-const EVP_CIPHER * evp_ssh1_bf(void);
-
-static void
-swap_bytes(const u_char *src, u_char *dst, int n)
-{
- u_char c[4];
-
- /* Process 4 bytes every lap. */
- for (n = n / 4; n > 0; n--) {
- c[3] = *src++;
- c[2] = *src++;
- c[1] = *src++;
- c[0] = *src++;
-
- *dst++ = c[0];
- *dst++ = c[1];
- *dst++ = c[2];
- *dst++ = c[3];
- }
-}
-
-#ifdef SSH_OLD_EVP
-static void bf_ssh1_init (EVP_CIPHER_CTX * ctx, const unsigned char *key,
- const unsigned char *iv, int enc)
-{
- if (iv != NULL)
- memcpy (&(ctx->oiv[0]), iv, 8);
- memcpy (&(ctx->iv[0]), &(ctx->oiv[0]), 8);
- if (key != NULL)
- BF_set_key (&(ctx->c.bf_ks), EVP_CIPHER_CTX_key_length (ctx),
- key);
-}
-#endif
-
-static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *,
- const u_char *, LIBCRYPTO_EVP_INL_TYPE) = NULL;
-
-static int
-bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in,
- LIBCRYPTO_EVP_INL_TYPE len)
-{
- int ret;
-
- swap_bytes(in, out, len);
- ret = (*orig_bf)(ctx, out, out, len);
- swap_bytes(out, out, len);
- return (ret);
-}
-
-const EVP_CIPHER *
-evp_ssh1_bf(void)
-{
- static EVP_CIPHER ssh1_bf;
-
- memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
- orig_bf = ssh1_bf.do_cipher;
- ssh1_bf.nid = NID_undef;
-#ifdef SSH_OLD_EVP
- ssh1_bf.init = bf_ssh1_init;
-#endif
- ssh1_bf.do_cipher = bf_ssh1_cipher;
- ssh1_bf.key_len = 32;
- return (&ssh1_bf);
-}
-#endif /* WITH_OPENSSL */
diff --git a/cipher-chachapoly-libcrypto.c b/cipher-chachapoly-libcrypto.c
new file mode 100644
index 00000000..719f9c84
--- /dev/null
+++ b/cipher-chachapoly-libcrypto.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+
+/* $OpenBSD: cipher-chachapoly-libcrypto.c,v 1.1 2020/04/03 04:32:21 djm Exp $ */
+
+#include "includes.h"
+#ifdef WITH_OPENSSL
+#include "openbsd-compat/openssl-compat.h"
+#endif
+
+#if defined(HAVE_EVP_CHACHA20) && !defined(HAVE_BROKEN_CHACHA20)
+
+#include <sys/types.h>
+#include <stdarg.h> /* needed for log.h */
+#include <string.h>
+#include <stdio.h> /* needed for misc.h */
+
+#include <openssl/evp.h>
+
+#include "log.h"
+#include "sshbuf.h"
+#include "ssherr.h"
+#include "cipher-chachapoly.h"
+
+struct chachapoly_ctx {
+ EVP_CIPHER_CTX *main_evp, *header_evp;
+};
+
+struct chachapoly_ctx *
+chachapoly_new(const u_char *key, u_int keylen)
+{
+ struct chachapoly_ctx *ctx;
+
+ if (keylen != (32 + 32)) /* 2 x 256 bit keys */
+ return NULL;
+ if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
+ return NULL;
+ if ((ctx->main_evp = EVP_CIPHER_CTX_new()) == NULL ||
+ (ctx->header_evp = EVP_CIPHER_CTX_new()) == NULL)
+ goto fail;
+ if (!EVP_CipherInit(ctx->main_evp, EVP_chacha20(), key, NULL, 1))
+ goto fail;
+ if (!EVP_CipherInit(ctx->header_evp, EVP_chacha20(), key + 32, NULL, 1))
+ goto fail;
+ if (EVP_CIPHER_CTX_iv_length(ctx->header_evp) != 16)
+ goto fail;
+ return ctx;
+ fail:
+ chachapoly_free(ctx);
+ return NULL;
+}
+
+void
+chachapoly_free(struct chachapoly_ctx *cpctx)
+{
+ if (cpctx == NULL)
+ return;
+ EVP_CIPHER_CTX_free(cpctx->main_evp);
+ EVP_CIPHER_CTX_free(cpctx->header_evp);
+ freezero(cpctx, sizeof(*cpctx));
+}
+
+/*
+ * chachapoly_crypt() operates as following:
+ * En/decrypt with header key 'aadlen' bytes from 'src', storing result
+ * to 'dest'. The ciphertext here is treated as additional authenticated
+ * data for MAC calculation.
+ * En/decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. Use
+ * POLY1305_TAGLEN bytes at offset 'len'+'aadlen' as the authentication
+ * tag. This tag is written on encryption and verified on decryption.
+ */
+int
+chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
+ const u_char *src, u_int len, u_int aadlen, u_int authlen, int do_encrypt)
+{
+ u_char seqbuf[16]; /* layout: u64 counter || u64 seqno */
+ int r = SSH_ERR_INTERNAL_ERROR;
+ u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
+
+ /*
+ * Run ChaCha20 once to generate the Poly1305 key. The IV is the
+ * packet sequence number.
+ */
+ memset(seqbuf, 0, sizeof(seqbuf));
+ POKE_U64(seqbuf + 8, seqnr);
+ memset(poly_key, 0, sizeof(poly_key));
+ if (!EVP_CipherInit(ctx->main_evp, NULL, NULL, seqbuf, 1) ||
+ EVP_Cipher(ctx->main_evp, poly_key,
+ poly_key, sizeof(poly_key)) < 0) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+
+ /* If decrypting, check tag before anything else */
+ if (!do_encrypt) {
+ const u_char *tag = src + aadlen + len;
+
+ poly1305_auth(expected_tag, src, aadlen + len, poly_key);
+ if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) {
+ r = SSH_ERR_MAC_INVALID;
+ goto out;
+ }
+ }
+
+ /* Crypt additional data */
+ if (aadlen) {
+ if (!EVP_CipherInit(ctx->header_evp, NULL, NULL, seqbuf, 1) ||
+ EVP_Cipher(ctx->header_evp, dest, src, aadlen) < 0) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ }
+
+ /* Set Chacha's block counter to 1 */
+ seqbuf[0] = 1;
+ if (!EVP_CipherInit(ctx->main_evp, NULL, NULL, seqbuf, 1) ||
+ EVP_Cipher(ctx->main_evp, dest + aadlen, src + aadlen, len) < 0) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+
+ /* If encrypting, calculate and append tag */
+ if (do_encrypt) {
+ poly1305_auth(dest + aadlen + len, dest, aadlen + len,
+ poly_key);
+ }
+ r = 0;
+ out:
+ explicit_bzero(expected_tag, sizeof(expected_tag));
+ explicit_bzero(seqbuf, sizeof(seqbuf));
+ explicit_bzero(poly_key, sizeof(poly_key));
+ return r;
+}
+
+/* Decrypt and extract the encrypted packet length */
+int
+chachapoly_get_length(struct chachapoly_ctx *ctx,
+ u_int *plenp, u_int seqnr, const u_char *cp, u_int len)
+{
+ u_char buf[4], seqbuf[16];
+
+ if (len < 4)
+ return SSH_ERR_MESSAGE_INCOMPLETE;
+ memset(seqbuf, 0, sizeof(seqbuf));
+ POKE_U64(seqbuf + 8, seqnr);
+ if (!EVP_CipherInit(ctx->header_evp, NULL, NULL, seqbuf, 0))
+ return SSH_ERR_LIBCRYPTO_ERROR;
+ if (EVP_Cipher(ctx->header_evp, buf, (u_char *)cp, sizeof(buf)) < 0)
+ return SSH_ERR_LIBCRYPTO_ERROR;
+ *plenp = PEEK_U32(buf);
+ return 0;
+}
+#endif /* defined(HAVE_EVP_CHACHA20) && !defined(HAVE_BROKEN_CHACHA20) */
diff --git a/cipher-chachapoly.c b/cipher-chachapoly.c
index 7f31ff4c..716f8d42 100644
--- a/cipher-chachapoly.c
+++ b/cipher-chachapoly.c
@@ -14,9 +14,14 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $OpenBSD: cipher-chachapoly.c,v 1.7 2015/01/14 10:24:42 markus Exp $ */
+/* $OpenBSD: cipher-chachapoly.c,v 1.9 2020/04/03 04:27:03 djm Exp $ */
#include "includes.h"
+#ifdef WITH_OPENSSL
+#include "openbsd-compat/openssl-compat.h"
+#endif
+
+#if !defined(HAVE_EVP_CHACHA20) || defined(HAVE_BROKEN_CHACHA20)
#include <sys/types.h>
#include <stdarg.h> /* needed for log.h */
@@ -28,14 +33,28 @@
#include "ssherr.h"
#include "cipher-chachapoly.h"
-int chachapoly_init(struct chachapoly_ctx *ctx,
- const u_char *key, u_int keylen)
+struct chachapoly_ctx {
+ struct chacha_ctx main_ctx, header_ctx;
+};
+
+struct chachapoly_ctx *
+chachapoly_new(const u_char *key, u_int keylen)
{
+ struct chachapoly_ctx *ctx;
+
if (keylen != (32 + 32)) /* 2 x 256 bit keys */
- return SSH_ERR_INVALID_ARGUMENT;
+ return NULL;
+ if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
+ return NULL;
chacha_keysetup(&ctx->main_ctx, key, 256);
chacha_keysetup(&ctx->header_ctx, key + 32, 256);
- return 0;
+ return ctx;
+}
+
+void
+chachapoly_free(struct chachapoly_ctx *cpctx)
+{
+ freezero(cpctx, sizeof(*cpctx));
}
/*
@@ -116,3 +135,5 @@ chachapoly_get_length(struct chachapoly_ctx *ctx,
*plenp = PEEK_U32(buf);
return 0;
}
+
+#endif /* !defined(HAVE_EVP_CHACHA20) || defined(HAVE_BROKEN_CHACHA20) */
diff --git a/cipher-chachapoly.h b/cipher-chachapoly.h
index b7072be7..026d2de9 100644
--- a/cipher-chachapoly.h
+++ b/cipher-chachapoly.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cipher-chachapoly.h,v 1.4 2014/06/24 01:13:21 djm Exp $ */
+/* $OpenBSD: cipher-chachapoly.h,v 1.5 2020/04/03 04:27:03 djm Exp $ */
/*
* Copyright (c) Damien Miller 2013 <djm@mindrot.org>
@@ -24,13 +24,12 @@
#define CHACHA_KEYLEN 32 /* Only 256 bit keys used here */
-struct chachapoly_ctx {
- struct chacha_ctx main_ctx, header_ctx;
-};
+struct chachapoly_ctx;
+
+struct chachapoly_ctx *chachapoly_new(const u_char *key, u_int keylen)
+ __attribute__((__bounded__(__buffer__, 1, 2)));
+void chachapoly_free(struct chachapoly_ctx *cpctx);
-int chachapoly_init(struct chachapoly_ctx *cpctx,
- const u_char *key, u_int keylen)
- __attribute__((__bounded__(__buffer__, 2, 3)));
int chachapoly_crypt(struct chachapoly_ctx *cpctx, u_int seqnr,
u_char *dest, const u_char *src, u_int len, u_int aadlen, u_int authlen,
int do_encrypt);
diff --git a/cipher.c b/cipher.c
index 6bd3f0cd..8195199b 100644
--- a/cipher.c
+++ b/cipher.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cipher.c,v 1.100 2015/01/14 10:29:45 djm Exp $ */
+/* $OpenBSD: cipher.c,v 1.117 2020/04/03 04:27:03 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -51,25 +51,31 @@
#include "openbsd-compat/openssl-compat.h"
-#ifdef WITH_SSH1
-extern const EVP_CIPHER *evp_ssh1_bf(void);
-extern const EVP_CIPHER *evp_ssh1_3des(void);
-extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
+#ifndef WITH_OPENSSL
+#define EVP_CIPHER_CTX void
#endif
+struct sshcipher_ctx {
+ int plaintext;
+ int encrypt;
+ EVP_CIPHER_CTX *evp;
+ struct chachapoly_ctx *cp_ctx;
+ struct aesctr_ctx ac_ctx; /* XXX union with evp? */
+ const struct sshcipher *cipher;
+};
+
struct sshcipher {
char *name;
- int number; /* for ssh1 only */
u_int block_size;
u_int key_len;
u_int iv_len; /* defaults to block_size */
u_int auth_len;
- u_int discard_len;
u_int flags;
#define CFLAG_CBC (1<<0)
#define CFLAG_CHACHAPOLY (1<<1)
#define CFLAG_AESCTR (1<<2)
#define CFLAG_NONE (1<<3)
+#define CFLAG_INTERNAL CFLAG_NONE /* Don't use "none" for packets */
#ifdef WITH_OPENSSL
const EVP_CIPHER *(*evptype)(void);
#else
@@ -78,49 +84,34 @@ struct sshcipher {
};
static const struct sshcipher ciphers[] = {
-#ifdef WITH_SSH1
- { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
- { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
- { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf },
-#endif /* WITH_SSH1 */
#ifdef WITH_OPENSSL
- { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
-#if !defined(ANDROID)
- { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc },
- { "blowfish-cbc",
- SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc },
- { "cast128-cbc",
- SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_cast5_cbc },
+#ifndef OPENSSL_NO_DES
+ { "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc },
#endif
- { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 0, EVP_rc4 },
- { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 0, 0, 1536, 0, EVP_rc4 },
- { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 0, 0, 1536, 0, EVP_rc4 },
- { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc },
- { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc },
- { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
+ { "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",
- SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
- { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr },
-#if !defined(ANDROID)
- { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr },
-#endif
- { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr },
+ 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 },
# ifdef OPENSSL_HAVE_EVPGCM
{ "aes128-gcm@openssh.com",
- SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm },
+ 16, 16, 12, 16, 0, EVP_aes_128_gcm },
{ "aes256-gcm@openssh.com",
- SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },
+ 16, 32, 12, 16, 0, EVP_aes_256_gcm },
# endif /* OPENSSL_HAVE_EVPGCM */
-#else /* WITH_OPENSSL */
- { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL },
- { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL },
- { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, CFLAG_AESCTR, NULL },
- { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, CFLAG_NONE, NULL },
-#endif /* WITH_OPENSSL */
+#else
+ { "aes128-ctr", 16, 16, 0, 0, CFLAG_AESCTR, NULL },
+ { "aes192-ctr", 16, 24, 0, 0, CFLAG_AESCTR, NULL },
+ { "aes256-ctr", 16, 32, 0, 0, CFLAG_AESCTR, NULL },
+#endif
{ "chacha20-poly1305@openssh.com",
- SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL },
+ 8, 64, 0, 16, CFLAG_CHACHAPOLY, NULL },
+ { "none", 8, 0, 0, 0, CFLAG_NONE, NULL },
- { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }
+ { NULL, 0, 0, 0, 0, 0, NULL }
};
/*--*/
@@ -134,7 +125,7 @@ cipher_alg_list(char sep, int auth_only)
const struct sshcipher *c;
for (c = ciphers; c->name != NULL; c++) {
- if (c->number != SSH_CIPHER_SSH2)
+ if ((c->flags & CFLAG_INTERNAL) != 0)
continue;
if (auth_only && c->auth_len == 0)
continue;
@@ -152,6 +143,17 @@ cipher_alg_list(char sep, int auth_only)
return ret;
}
+const char *
+compression_alg_list(int compression)
+{
+#ifdef WITH_ZLIB
+ return compression ? "zlib@openssh.com,zlib,none" :
+ "none,zlib@openssh.com,zlib";
+#else
+ return "none";
+#endif
+}
+
u_int
cipher_blocksize(const struct sshcipher *c)
{
@@ -190,27 +192,15 @@ cipher_ivlen(const struct sshcipher *c)
}
u_int
-cipher_get_number(const struct sshcipher *c)
-{
- return (c->number);
-}
-
-u_int
cipher_is_cbc(const struct sshcipher *c)
{
return (c->flags & CFLAG_CBC) != 0;
}
u_int
-cipher_mask_ssh1(int client)
+cipher_ctx_is_plaintext(struct sshcipher_ctx *cc)
{
- u_int mask = 0;
- mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
- mask |= 1 << SSH_CIPHER_BLOWFISH;
- if (client) {
- mask |= 1 << SSH_CIPHER_DES;
- }
- return mask;
+ return cc->plaintext;
}
const struct sshcipher *
@@ -223,16 +213,6 @@ cipher_by_name(const char *name)
return NULL;
}
-const struct sshcipher *
-cipher_by_number(int id)
-{
- const struct sshcipher *c;
- for (c = ciphers; c->name != NULL; c++)
- if (c->number == id)
- return c;
- return NULL;
-}
-
#define CIPHER_SEP ","
int
ciphers_valid(const char *names)
@@ -248,7 +228,7 @@ ciphers_valid(const char *names)
for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
(p = strsep(&cp, CIPHER_SEP))) {
c = cipher_by_name(p);
- if (c == NULL || c->number != SSH_CIPHER_SSH2) {
+ if (c == NULL || (c->flags & CFLAG_INTERNAL) != 0) {
free(cipher_list);
return 0;
}
@@ -257,130 +237,108 @@ ciphers_valid(const char *names)
return 1;
}
-/*
- * Parses the name of the cipher. Returns the number of the corresponding
- * cipher, or -1 on error.
- */
-
-int
-cipher_number(const char *name)
-{
- const struct sshcipher *c;
- if (name == NULL)
- return -1;
- for (c = ciphers; c->name != NULL; c++)
- if (strcasecmp(c->name, name) == 0)
- return c->number;
- return -1;
-}
-
-char *
-cipher_name(int id)
-{
- const struct sshcipher *c = cipher_by_number(id);
- return (c==NULL) ? "<unknown>" : c->name;
-}
-
const char *
cipher_warning_message(const struct sshcipher_ctx *cc)
{
if (cc == NULL || cc->cipher == NULL)
return NULL;
- if (cc->cipher->number == SSH_CIPHER_DES)
- return "use of DES is strongly discouraged due to "
- "cryptographic weaknesses";
+ /* XXX repurpose for CBC warning */
return NULL;
}
int
-cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
+cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
int do_encrypt)
{
-#ifdef WITH_OPENSSL
+ struct sshcipher_ctx *cc = NULL;
int ret = SSH_ERR_INTERNAL_ERROR;
+#ifdef WITH_OPENSSL
const EVP_CIPHER *type;
int klen;
- u_char *junk, *discard;
-
- if (cipher->number == SSH_CIPHER_DES) {
- if (keylen > 8)
- keylen = 8;
- }
#endif
- cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
+
+ *ccp = NULL;
+ if ((cc = calloc(sizeof(*cc), 1)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+
+ cc->plaintext = (cipher->flags & CFLAG_NONE) != 0;
cc->encrypt = do_encrypt;
if (keylen < cipher->key_len ||
- (iv != NULL && ivlen < cipher_ivlen(cipher)))
- return SSH_ERR_INVALID_ARGUMENT;
+ (iv != NULL && ivlen < cipher_ivlen(cipher))) {
+ ret = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
cc->cipher = cipher;
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
- return chachapoly_init(&cc->cp_ctx, key, keylen);
+ cc->cp_ctx = chachapoly_new(key, keylen);
+ ret = cc->cp_ctx != NULL ? 0 : SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if ((cc->cipher->flags & CFLAG_NONE) != 0) {
+ ret = 0;
+ goto out;
}
#ifndef WITH_OPENSSL
if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
aesctr_ivsetup(&cc->ac_ctx, iv);
- return 0;
+ ret = 0;
+ goto out;
}
- if ((cc->cipher->flags & CFLAG_NONE) != 0)
- return 0;
- return SSH_ERR_INVALID_ARGUMENT;
-#else
+ ret = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+#else /* WITH_OPENSSL */
type = (*cipher->evptype)();
- EVP_CIPHER_CTX_init(&cc->evp);
- if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
+ if ((cc->evp = EVP_CIPHER_CTX_new()) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv,
(do_encrypt == CIPHER_ENCRYPT)) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
- goto bad;
+ goto out;
}
if (cipher_authlen(cipher) &&
- !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
+ !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
-1, (u_char *)iv)) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
- goto bad;
+ goto out;
}
- klen = EVP_CIPHER_CTX_key_length(&cc->evp);
+ klen = EVP_CIPHER_CTX_key_length(cc->evp);
if (klen > 0 && keylen != (u_int)klen) {
- if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) {
+ if (EVP_CIPHER_CTX_set_key_length(cc->evp, keylen) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
- goto bad;
+ goto out;
}
}
- if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
+ if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
- goto bad;
+ goto out;
}
-
- if (cipher->discard_len > 0) {
- if ((junk = malloc(cipher->discard_len)) == NULL ||
- (discard = malloc(cipher->discard_len)) == NULL) {
- if (junk != NULL)
- free(junk);
- ret = SSH_ERR_ALLOC_FAIL;
- goto bad;
- }
- ret = EVP_Cipher(&cc->evp, discard, junk, cipher->discard_len);
- explicit_bzero(discard, cipher->discard_len);
- free(junk);
- free(discard);
- if (ret != 1) {
- ret = SSH_ERR_LIBCRYPTO_ERROR;
- bad:
- EVP_CIPHER_CTX_cleanup(&cc->evp);
- return ret;
+ ret = 0;
+#endif /* WITH_OPENSSL */
+ out:
+ if (ret == 0) {
+ /* success */
+ *ccp = cc;
+ } else {
+ if (cc != NULL) {
+#ifdef WITH_OPENSSL
+ EVP_CIPHER_CTX_free(cc->evp);
+#endif /* WITH_OPENSSL */
+ freezero(cc, sizeof(*cc));
}
}
-#endif
- return 0;
+ return ret;
}
/*
* cipher_crypt() operates as following:
* Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'.
- * Theses bytes are treated as additional authenticated data for
+ * These bytes are treated as additional authenticated data for
* authenticated encryption modes.
* En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'.
* Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
@@ -392,9 +350,13 @@ cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
const u_char *src, u_int len, u_int aadlen, u_int authlen)
{
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
- return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src,
+ return chachapoly_crypt(cc->cp_ctx, seqnr, dest, src,
len, aadlen, authlen, cc->encrypt);
}
+ if ((cc->cipher->flags & CFLAG_NONE) != 0) {
+ memcpy(dest, src, aadlen + len);
+ return 0;
+ }
#ifndef WITH_OPENSSL
if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
if (aadlen)
@@ -403,10 +365,6 @@ cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
dest + aadlen, len);
return 0;
}
- if ((cc->cipher->flags & CFLAG_NONE) != 0) {
- memcpy(dest, src, aadlen + len);
- return 0;
- }
return SSH_ERR_INVALID_ARGUMENT;
#else
if (authlen) {
@@ -415,33 +373,33 @@ cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
if (authlen != cipher_authlen(cc->cipher))
return SSH_ERR_INVALID_ARGUMENT;
/* increment IV */
- if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
+ if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
1, lastiv))
return SSH_ERR_LIBCRYPTO_ERROR;
/* set tag on decyption */
if (!cc->encrypt &&
- !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG,
+ !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_TAG,
authlen, (u_char *)src + aadlen + len))
return SSH_ERR_LIBCRYPTO_ERROR;
}
if (aadlen) {
if (authlen &&
- EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0)
+ EVP_Cipher(cc->evp, NULL, (u_char *)src, aadlen) < 0)
return SSH_ERR_LIBCRYPTO_ERROR;
memcpy(dest, src, aadlen);
}
if (len % cc->cipher->block_size)
return SSH_ERR_INVALID_ARGUMENT;
- if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen,
+ if (EVP_Cipher(cc->evp, dest + aadlen, (u_char *)src + aadlen,
len) < 0)
return SSH_ERR_LIBCRYPTO_ERROR;
if (authlen) {
/* compute tag (on encrypt) or verify tag (on decrypt) */
- if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0)
+ if (EVP_Cipher(cc->evp, NULL, NULL, 0) < 0)
return cc->encrypt ?
SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID;
if (cc->encrypt &&
- !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG,
+ !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_GET_TAG,
authlen, dest + aadlen + len))
return SSH_ERR_LIBCRYPTO_ERROR;
}
@@ -455,50 +413,29 @@ cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr,
const u_char *cp, u_int len)
{
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
- return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr,
+ return chachapoly_get_length(cc->cp_ctx, plenp, seqnr,
cp, len);
if (len < 4)
return SSH_ERR_MESSAGE_INCOMPLETE;
- *plenp = get_u32(cp);
+ *plenp = PEEK_U32(cp);
return 0;
}
-int
-cipher_cleanup(struct sshcipher_ctx *cc)
+void
+cipher_free(struct sshcipher_ctx *cc)
{
- if (cc == NULL || cc->cipher == NULL)
- return 0;
- if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
- explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx));
- else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
+ if (cc == NULL)
+ return;
+ if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
+ chachapoly_free(cc->cp_ctx);
+ cc->cp_ctx = NULL;
+ } else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx));
#ifdef WITH_OPENSSL
- else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
- return SSH_ERR_LIBCRYPTO_ERROR;
+ EVP_CIPHER_CTX_free(cc->evp);
+ cc->evp = NULL;
#endif
- return 0;
-}
-
-/*
- * Selects the cipher, and keys if by computing the MD5 checksum of the
- * passphrase and using the resulting 16 bytes as the key.
- */
-int
-cipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
- const char *passphrase, int do_encrypt)
-{
- u_char digest[16];
- int r = SSH_ERR_INTERNAL_ERROR;
-
- if ((r = ssh_digest_memory(SSH_DIGEST_MD5,
- passphrase, strlen(passphrase),
- digest, sizeof(digest))) != 0)
- goto out;
-
- r = cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
- out:
- explicit_bzero(digest, sizeof(digest));
- return r;
+ freezero(cc, sizeof(*cc));
}
/*
@@ -510,27 +447,24 @@ int
cipher_get_keyiv_len(const struct sshcipher_ctx *cc)
{
const struct sshcipher *c = cc->cipher;
- int ivlen = 0;
-
- if (c->number == SSH_CIPHER_3DES)
- ivlen = 24;
- else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
- ivlen = 0;
- else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
- ivlen = sizeof(cc->ac_ctx.ctr);
+
+ if ((c->flags & CFLAG_CHACHAPOLY) != 0)
+ return 0;
+ else if ((c->flags & CFLAG_AESCTR) != 0)
+ return sizeof(cc->ac_ctx.ctr);
#ifdef WITH_OPENSSL
- else
- ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
-#endif /* WITH_OPENSSL */
- return (ivlen);
+ return EVP_CIPHER_CTX_iv_length(cc->evp);
+#else
+ return 0;
+#endif
}
int
-cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
+cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, size_t len)
{
- const struct sshcipher *c = cc->cipher;
#ifdef WITH_OPENSSL
- int evplen;
+ const struct sshcipher *c = cc->cipher;
+ int evplen;
#endif
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
@@ -547,47 +481,35 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
if ((cc->cipher->flags & CFLAG_NONE) != 0)
return 0;
- switch (c->number) {
#ifdef WITH_OPENSSL
- case SSH_CIPHER_SSH2:
- case SSH_CIPHER_DES:
- case SSH_CIPHER_BLOWFISH:
- evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
- if (evplen == 0)
- return 0;
- else if (evplen < 0)
- return SSH_ERR_LIBCRYPTO_ERROR;
- if ((u_int)evplen != len)
- return SSH_ERR_INVALID_ARGUMENT;
+ evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
+ if (evplen == 0)
+ return 0;
+ else if (evplen < 0)
+ return SSH_ERR_LIBCRYPTO_ERROR;
+ if ((size_t)evplen != len)
+ return SSH_ERR_INVALID_ARGUMENT;
#ifndef OPENSSL_HAVE_EVPCTR
- if (c->evptype == evp_aes_128_ctr)
- ssh_aes_ctr_iv(&cc->evp, 0, iv, len);
- else
-#endif
- if (cipher_authlen(c)) {
- if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
- len, iv))
- return SSH_ERR_LIBCRYPTO_ERROR;
- } else
- memcpy(iv, cc->evp.iv, len);
- break;
+ if (c->evptype == evp_aes_128_ctr)
+ ssh_aes_ctr_iv(cc->evp, 0, iv, len);
+ else
#endif
-#ifdef WITH_SSH1
- case SSH_CIPHER_3DES:
- return ssh1_3des_iv(&cc->evp, 0, iv, 24);
+ if (cipher_authlen(c)) {
+ if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
+ len, iv))
+ return SSH_ERR_LIBCRYPTO_ERROR;
+ } else if (!EVP_CIPHER_CTX_get_iv(cc->evp, iv, len))
+ return SSH_ERR_LIBCRYPTO_ERROR;
#endif
- default:
- return SSH_ERR_INVALID_ARGUMENT;
- }
return 0;
}
int
-cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
+cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv, size_t len)
{
- const struct sshcipher *c = cc->cipher;
#ifdef WITH_OPENSSL
- int evplen = 0;
+ const struct sshcipher *c = cc->cipher;
+ int evplen = 0;
#endif
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
@@ -595,67 +517,25 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
if ((cc->cipher->flags & CFLAG_NONE) != 0)
return 0;
- switch (c->number) {
#ifdef WITH_OPENSSL
- case SSH_CIPHER_SSH2:
- case SSH_CIPHER_DES:
- case SSH_CIPHER_BLOWFISH:
- evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
- if (evplen <= 0)
- return SSH_ERR_LIBCRYPTO_ERROR;
- if (cipher_authlen(c)) {
- /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
- if (!EVP_CIPHER_CTX_ctrl(&cc->evp,
- EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
- return SSH_ERR_LIBCRYPTO_ERROR;
- } else
- memcpy(cc->evp.iv, iv, evplen);
- break;
-#endif
-#ifdef WITH_SSH1
- case SSH_CIPHER_3DES:
- return ssh1_3des_iv(&cc->evp, 1, (u_char *)iv, 24);
-#endif
- default:
+ evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
+ if (evplen <= 0)
+ return SSH_ERR_LIBCRYPTO_ERROR;
+ if ((size_t)evplen != len)
return SSH_ERR_INVALID_ARGUMENT;
- }
- return 0;
-}
-
-#ifdef WITH_OPENSSL
-#define EVP_X_STATE(evp) (evp).cipher_data
-#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
-#endif
-
-int
-cipher_get_keycontext(const struct sshcipher_ctx *cc, u_char *dat)
-{
-#ifdef WITH_OPENSSL
- const struct sshcipher *c = cc->cipher;
- int plen = 0;
-
- if (c->evptype == EVP_rc4) {
- plen = EVP_X_STATE_LEN(cc->evp);
- if (dat == NULL)
- return (plen);
- memcpy(dat, EVP_X_STATE(cc->evp), plen);
- }
- return (plen);
-#else
- return 0;
+#ifndef OPENSSL_HAVE_EVPCTR
+ /* XXX iv arg is const, but ssh_aes_ctr_iv isn't */
+ if (c->evptype == evp_aes_128_ctr)
+ ssh_aes_ctr_iv(cc->evp, 1, (u_char *)iv, evplen);
+ else
#endif
-}
-
-void
-cipher_set_keycontext(struct sshcipher_ctx *cc, const u_char *dat)
-{
-#ifdef WITH_OPENSSL
- const struct sshcipher *c = cc->cipher;
- int plen;
-
- if (c->evptype == EVP_rc4) {
- plen = EVP_X_STATE_LEN(cc->evp);
- memcpy(EVP_X_STATE(cc->evp), dat, plen);
- }
+ if (cipher_authlen(c)) {
+ /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
+ if (!EVP_CIPHER_CTX_ctrl(cc->evp,
+ EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
+ return SSH_ERR_LIBCRYPTO_ERROR;
+ } else if (!EVP_CIPHER_CTX_set_iv(cc->evp, iv, evplen))
+ return SSH_ERR_LIBCRYPTO_ERROR;
#endif
+ return 0;
}
diff --git a/cipher.h b/cipher.h
index 62a88b42..1a591cd7 100644
--- a/cipher.h
+++ b/cipher.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cipher.h,v 1.47 2015/01/14 10:24:42 markus Exp $ */
+/* $OpenBSD: cipher.h,v 1.55 2020/01/23 10:24:29 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -38,60 +38,30 @@
#define CIPHER_H
#include <sys/types.h>
+#ifdef WITH_OPENSSL
#include <openssl/evp.h>
+#endif
#include "cipher-chachapoly.h"
#include "cipher-aesctr.h"
-/*
- * Cipher types for SSH-1. New types can be added, but old types should not
- * be removed for compatibility. The maximum allowed value is 31.
- */
-#define SSH_CIPHER_SSH2 -3
-#define SSH_CIPHER_INVALID -2 /* No valid cipher selected. */
-#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */
-#define SSH_CIPHER_NONE 0 /* no encryption */
-#define SSH_CIPHER_IDEA 1 /* IDEA CFB */
-#define SSH_CIPHER_DES 2 /* DES CBC */
-#define SSH_CIPHER_3DES 3 /* 3DES CBC */
-#define SSH_CIPHER_BROKEN_TSS 4 /* TRI's Simple Stream encryption CBC */
-#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */
-#define SSH_CIPHER_BLOWFISH 6
-#define SSH_CIPHER_RESERVED 7
-#define SSH_CIPHER_MAX 31
-
#define CIPHER_ENCRYPT 1
#define CIPHER_DECRYPT 0
struct sshcipher;
-struct sshcipher_ctx {
- int plaintext;
- int encrypt;
- EVP_CIPHER_CTX evp;
- struct chachapoly_ctx cp_ctx; /* XXX union with evp? */
- struct aesctr_ctx ac_ctx; /* XXX union with evp? */
- const struct sshcipher *cipher;
-};
+struct sshcipher_ctx;
-typedef struct sshcipher Cipher;
-typedef struct sshcipher_ctx CipherContext;
-
-u_int cipher_mask_ssh1(int);
const struct sshcipher *cipher_by_name(const char *);
-const struct sshcipher *cipher_by_number(int);
-int cipher_number(const char *);
-char *cipher_name(int);
const char *cipher_warning_message(const struct sshcipher_ctx *);
int ciphers_valid(const char *);
char *cipher_alg_list(char, int);
-int cipher_init(struct sshcipher_ctx *, const struct sshcipher *,
+const char *compression_alg_list(int);
+int cipher_init(struct sshcipher_ctx **, const struct sshcipher *,
const u_char *, u_int, const u_char *, u_int, int);
int cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *,
u_int, u_int, u_int);
int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int,
const u_char *, u_int);
-int cipher_cleanup(struct sshcipher_ctx *);
-int cipher_set_key_string(struct sshcipher_ctx *, const struct sshcipher *,
- const char *, int);
+void cipher_free(struct sshcipher_ctx *);
u_int cipher_blocksize(const struct sshcipher *);
u_int cipher_keylen(const struct sshcipher *);
u_int cipher_seclen(const struct sshcipher *);
@@ -99,10 +69,10 @@ u_int cipher_authlen(const struct sshcipher *);
u_int cipher_ivlen(const struct sshcipher *);
u_int cipher_is_cbc(const struct sshcipher *);
-u_int cipher_get_number(const struct sshcipher *);
-int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int);
-int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *);
+u_int cipher_ctx_is_plaintext(struct sshcipher_ctx *);
+
+int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, size_t);
+int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *, size_t);
int cipher_get_keyiv_len(const struct sshcipher_ctx *);
-int cipher_get_keycontext(const struct sshcipher_ctx *, u_char *);
-void cipher_set_keycontext(struct sshcipher_ctx *, const u_char *);
+
#endif /* CIPHER_H */
diff --git a/clientloop.c b/clientloop.c
index a9c8a90f..da396c72 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.272 2015/02/25 19:54:02 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.344 2020/04/24 02:19:40 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -61,7 +61,6 @@
#include "includes.h"
-#include <sys/param.h> /* MIN MAX */
#include <sys/types.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_STAT_H
@@ -78,10 +77,10 @@
#include <paths.h>
#endif
#include <signal.h>
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
#include <termios.h>
#include <pwd.h>
#include <unistd.h>
@@ -90,16 +89,16 @@
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
-#include "ssh1.h"
#include "ssh2.h"
#include "packet.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "compat.h"
#include "channels.h"
#include "dispatch.h"
-#include "key.h"
+#include "sshkey.h"
#include "cipher.h"
#include "kex.h"
+#include "myproposal.h"
#include "log.h"
#include "misc.h"
#include "readconf.h"
@@ -110,7 +109,6 @@
#include "sshpty.h"
#include "match.h"
#include "msg.h"
-#include "roaming.h"
#include "ssherr.h"
#include "hostfile.h"
@@ -123,17 +121,26 @@ extern int stdin_null_flag;
/* Flag indicating that no shell has been requested */
extern int no_shell_flag;
+/* Flag indicating that ssh should daemonise after authentication is complete */
+extern int fork_after_authentication_flag;
+
/* Control socket */
extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
/*
* Name of the host we are connecting to. This is the name given on the
- * command line, or the HostName specified for the user-supplied name in a
+ * command line, or the Hostname specified for the user-supplied name in a
* configuration file.
*/
extern char *host;
/*
+ * If this field is not NULL, the ForwardAgent socket is this path and different
+ * instead of SSH_AUTH_SOCK.
+ */
+extern char *forward_agent_sock_path;
+
+/*
* Flag to indicate that we have received a window change signal which has
* not yet been processed. This will cause a message indicating the new
* window size to be sent to the server a little later. This is volatile
@@ -142,34 +149,23 @@ extern char *host;
static volatile sig_atomic_t received_window_change_signal = 0;
static volatile sig_atomic_t received_signal = 0;
-/* Flag indicating whether the user's terminal is in non-blocking mode. */
-static int in_non_blocking_mode = 0;
-
/* Time when backgrounded control master using ControlPersist should exit */
static time_t control_persist_exit_time = 0;
/* Common data for the client loop code. */
volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
-static int escape_char1; /* Escape character. (proto1 only) */
-static int escape_pending1; /* Last character was an escape (proto1 only) */
static int last_was_cr; /* Last character was a newline. */
static int exit_status; /* Used to store the command exit status. */
-static int stdin_eof; /* EOF has been encountered on stderr. */
-static Buffer stdin_buffer; /* Buffer for stdin data. */
-static Buffer stdout_buffer; /* Buffer for stdout data. */
-static Buffer stderr_buffer; /* Buffer for stderr data. */
-static u_int buffer_high; /* Soft max buffer size. */
+static struct sshbuf *stderr_buffer; /* Used for final exit message. */
static int connection_in; /* Connection to server (input). */
static int connection_out; /* Connection to server (output). */
static int need_rekeying; /* Set to non-zero if rekeying is requested. */
static int session_closed; /* In SSH2: login session closed. */
-static int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
+static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
-static void client_init_dispatch(void);
+static void client_init_dispatch(struct ssh *ssh);
int session_ident = -1;
-int session_resumed = 0;
-
/* Track escape per proto2 channel */
struct escape_filter_ctx {
int escape_pending;
@@ -184,6 +180,7 @@ struct channel_reply_ctx {
};
/* Global request success/failure callbacks */
+/* XXX move to struct ssh? */
struct global_confirm {
TAILQ_ENTRY(global_confirm) entry;
global_confirm_cb *cb;
@@ -194,27 +191,7 @@ TAILQ_HEAD(global_confirms, global_confirm);
static struct global_confirms global_confirms =
TAILQ_HEAD_INITIALIZER(global_confirms);
-void ssh_process_session2_setup(int, int, int, Buffer *);
-
-/* Restores stdin to blocking mode. */
-
-static void
-leave_non_blocking(void)
-{
- if (in_non_blocking_mode) {
- unset_nonblock(fileno(stdin));
- in_non_blocking_mode = 0;
- }
-}
-
-/* Puts stdin terminal in non-blocking mode. */
-
-static void
-enter_non_blocking(void)
-{
- in_non_blocking_mode = 1;
- set_nonblock(fileno(stdin));
-}
+void ssh_process_session2_setup(int, int, int, struct sshbuf *);
/*
* Signal handler for the window change signal (SIGWINCH). This just sets a
@@ -225,7 +202,6 @@ static void
window_change_handler(int sig)
{
received_window_change_signal = 1;
- signal(SIGWINCH, window_change_handler);
}
/*
@@ -241,32 +217,19 @@ signal_handler(int sig)
}
/*
- * Returns current time in seconds from Jan 1, 1970 with the maximum
- * available resolution.
- */
-
-static double
-get_current_time(void)
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
-}
-
-/*
* Sets control_persist_exit_time to the absolute time when the
* backgrounded control master should exit due to expiry of the
* ControlPersist timeout. Sets it to 0 if we are not a backgrounded
* control master process, or if there is no ControlPersist timeout.
*/
static void
-set_control_persist_exit_time(void)
+set_control_persist_exit_time(struct ssh *ssh)
{
if (muxserver_sock == -1 || !options.control_persist
|| options.control_persist_timeout == 0) {
/* not using a ControlPersist timeout */
control_persist_exit_time = 0;
- } else if (channel_still_open()) {
+ } else if (channel_still_open(ssh)) {
/* some client connections are still open */
if (control_persist_exit_time > 0)
debug2("%s: cancel scheduled exit", __func__);
@@ -287,6 +250,9 @@ client_x11_display_valid(const char *display)
{
size_t i, dlen;
+ if (display == NULL)
+ return 0;
+
dlen = strlen(display);
for (i = 0; i < dlen; i++) {
if (!isalnum((u_char)display[i]) &&
@@ -298,36 +264,37 @@ client_x11_display_valid(const char *display)
return 1;
}
-#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
-void
-client_x11_get_proto(const char *display, const char *xauth_path,
- u_int trusted, u_int timeout, char **_proto, char **_data)
+#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
+#define X11_TIMEOUT_SLACK 60
+int
+client_x11_get_proto(struct ssh *ssh, const char *display,
+ const char *xauth_path, u_int trusted, u_int timeout,
+ char **_proto, char **_data)
{
- char cmd[1024];
- char line[512];
- char xdisplay[512];
+ char *cmd, line[512], xdisplay[512];
+ char xauthfile[PATH_MAX], xauthdir[PATH_MAX];
static char proto[512], data[512];
FILE *f;
- int got_data = 0, generated = 0, do_unlink = 0, i;
- char *xauthdir, *xauthfile;
+ int got_data = 0, generated = 0, do_unlink = 0, r;
struct stat st;
- u_int now;
+ u_int now, x11_timeout_real;
- xauthdir = xauthfile = NULL;
*_proto = proto;
*_data = data;
- proto[0] = data[0] = '\0';
+ proto[0] = data[0] = xauthfile[0] = xauthdir[0] = '\0';
- if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) {
+ if (!client_x11_display_valid(display)) {
+ if (display != NULL)
+ logit("DISPLAY \"%s\" invalid; disabling X11 forwarding",
+ display);
+ return -1;
+ }
+ if (xauth_path != NULL && stat(xauth_path, &st) == -1) {
debug("No xauth program.");
- } else if (!client_x11_display_valid(display)) {
- logit("DISPLAY '%s' invalid, falling back to fake xauth data",
- display);
- } else {
- if (display == NULL) {
- debug("x11_get_proto: DISPLAY not set");
- return;
- }
+ xauth_path = NULL;
+ }
+
+ if (xauth_path != NULL) {
/*
* Handle FamilyLocal case where $DISPLAY does
* not match an authorization entry. For this we
@@ -336,33 +303,72 @@ client_x11_get_proto(const char *display, const char *xauth_path,
* is not perfect.
*/
if (strncmp(display, "localhost:", 10) == 0) {
- snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
- display + 10);
+ if ((r = snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
+ display + 10)) < 0 ||
+ (size_t)r >= sizeof(xdisplay)) {
+ error("%s: display name too long", __func__);
+ return -1;
+ }
display = xdisplay;
}
if (trusted == 0) {
- xauthdir = xmalloc(PATH_MAX);
- xauthfile = xmalloc(PATH_MAX);
- mktemp_proto(xauthdir, PATH_MAX);
- if (mkdtemp(xauthdir) != NULL) {
- do_unlink = 1;
- snprintf(xauthfile, PATH_MAX, "%s/xauthfile",
- xauthdir);
- snprintf(cmd, sizeof(cmd),
- "%s -f %s generate %s " SSH_X11_PROTO
- " untrusted timeout %u 2>" _PATH_DEVNULL,
- xauth_path, xauthfile, display, timeout);
- debug2("x11_get_proto: %s", cmd);
- if (system(cmd) == 0)
- generated = 1;
- if (x11_refuse_time == 0) {
- now = monotime() + 1;
- if (UINT_MAX - timeout < now)
- x11_refuse_time = UINT_MAX;
- else
- x11_refuse_time = now + timeout;
+ /*
+ * Generate an untrusted X11 auth cookie.
+ *
+ * The authentication cookie should briefly outlive
+ * ssh's willingness to forward X11 connections to
+ * avoid nasty fail-open behaviour in the X server.
+ */
+ mktemp_proto(xauthdir, sizeof(xauthdir));
+ if (mkdtemp(xauthdir) == NULL) {
+ error("%s: mkdtemp: %s",
+ __func__, strerror(errno));
+ return -1;
+ }
+ do_unlink = 1;
+ if ((r = snprintf(xauthfile, sizeof(xauthfile),
+ "%s/xauthfile", xauthdir)) < 0 ||
+ (size_t)r >= sizeof(xauthfile)) {
+ error("%s: xauthfile path too long", __func__);
+ rmdir(xauthdir);
+ return -1;
+ }
+
+ if (timeout == 0) {
+ /* auth doesn't time out */
+ xasprintf(&cmd, "%s -f %s generate %s %s "
+ "untrusted 2>%s",
+ xauth_path, xauthfile, display,
+ SSH_X11_PROTO, _PATH_DEVNULL);
+ } else {
+ /* Add some slack to requested expiry */
+ if (timeout < UINT_MAX - X11_TIMEOUT_SLACK)
+ x11_timeout_real = timeout +
+ X11_TIMEOUT_SLACK;
+ else {
+ /* Don't overflow on long timeouts */
+ x11_timeout_real = UINT_MAX;
}
+ xasprintf(&cmd, "%s -f %s generate %s %s "
+ "untrusted timeout %u 2>%s",
+ xauth_path, xauthfile, display,
+ SSH_X11_PROTO, x11_timeout_real,
+ _PATH_DEVNULL);
+ }
+ debug2("%s: xauth command: %s", __func__, cmd);
+
+ if (timeout != 0 && x11_refuse_time == 0) {
+ now = monotime() + 1;
+ if (UINT_MAX - timeout < now)
+ x11_refuse_time = UINT_MAX;
+ else
+ x11_refuse_time = now + timeout;
+ channel_set_x11_refuse_time(ssh,
+ x11_refuse_time);
}
+ if (system(cmd) == 0)
+ generated = 1;
+ free(cmd);
}
/*
@@ -371,7 +377,7 @@ client_x11_get_proto(const char *display, const char *xauth_path,
* above.
*/
if (trusted || generated) {
- snprintf(cmd, sizeof(cmd),
+ xasprintf(&cmd,
"%s %s%s list %s 2>" _PATH_DEVNULL,
xauth_path,
generated ? "-f " : "" ,
@@ -384,17 +390,21 @@ client_x11_get_proto(const char *display, const char *xauth_path,
got_data = 1;
if (f)
pclose(f);
- } else
- error("Warning: untrusted X11 forwarding setup failed: "
- "xauth key data not generated");
+ free(cmd);
+ }
}
if (do_unlink) {
unlink(xauthfile);
rmdir(xauthdir);
}
- free(xauthdir);
- free(xauthfile);
+
+ /* Don't fall back to fake X11 data for untrusted forwarding */
+ if (!trusted && !got_data) {
+ error("Warning: untrusted X11 forwarding setup failed: "
+ "xauth key data not generated");
+ return -1;
+ }
/*
* If we didn't get authentication data, just make up some
@@ -405,104 +415,20 @@ client_x11_get_proto(const char *display, const char *xauth_path,
* for the local connection.
*/
if (!got_data) {
- u_int32_t rnd = 0;
+ u_int8_t rnd[16];
+ u_int i;
logit("Warning: No xauth data; "
"using fake authentication data for X11 forwarding.");
strlcpy(proto, SSH_X11_PROTO, sizeof proto);
- for (i = 0; i < 16; i++) {
- if (i % 4 == 0)
- rnd = arc4random();
+ arc4random_buf(rnd, sizeof(rnd));
+ for (i = 0; i < sizeof(rnd); i++) {
snprintf(data + 2 * i, sizeof data - 2 * i, "%02x",
- rnd & 0xff);
- rnd >>= 8;
- }
- }
-}
-
-/*
- * This is called when the interactive is entered. This checks if there is
- * an EOF coming on stdin. We must check this explicitly, as select() does
- * not appear to wake up when redirecting from /dev/null.
- */
-
-static void
-client_check_initial_eof_on_stdin(void)
-{
- int len;
- char buf[1];
-
- /*
- * If standard input is to be "redirected from /dev/null", we simply
- * mark that we have seen an EOF and send an EOF message to the
- * server. Otherwise, we try to read a single character; it appears
- * that for some files, such /dev/null, select() never wakes up for
- * read for this descriptor, which means that we never get EOF. This
- * way we will get the EOF if stdin comes from /dev/null or similar.
- */
- if (stdin_null_flag) {
- /* Fake EOF on stdin. */
- debug("Sending eof.");
- stdin_eof = 1;
- packet_start(SSH_CMSG_EOF);
- packet_send();
- } else {
- enter_non_blocking();
-
- /* Check for immediate EOF on stdin. */
- len = read(fileno(stdin), buf, 1);
- if (len == 0) {
- /*
- * EOF. Record that we have seen it and send
- * EOF to server.
- */
- debug("Sending eof.");
- stdin_eof = 1;
- packet_start(SSH_CMSG_EOF);
- packet_send();
- } else if (len > 0) {
- /*
- * Got data. We must store the data in the buffer,
- * and also process it as an escape character if
- * appropriate.
- */
- if ((u_char) buf[0] == escape_char1)
- escape_pending1 = 1;
- else
- buffer_append(&stdin_buffer, buf, 1);
+ rnd[i]);
}
- leave_non_blocking();
}
-}
-
-/*
- * Make packets from buffered stdin data, and buffer them for sending to the
- * connection.
- */
-
-static void
-client_make_packets_from_stdin_data(void)
-{
- u_int len;
-
- /* Send buffered stdin data to the server. */
- while (buffer_len(&stdin_buffer) > 0 &&
- packet_not_very_much_data_to_write()) {
- len = buffer_len(&stdin_buffer);
- /* Keep the packets at reasonable size. */
- if (len > packet_get_maxsize())
- len = packet_get_maxsize();
- packet_start(SSH_CMSG_STDIN_DATA);
- packet_put_string(buffer_ptr(&stdin_buffer), len);
- packet_send();
- buffer_consume(&stdin_buffer, len);
- /* If we have a pending EOF, send it now. */
- if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
- packet_start(SSH_CMSG_EOF);
- packet_send();
- }
- }
+ return 0;
}
/*
@@ -513,61 +439,47 @@ client_make_packets_from_stdin_data(void)
*/
static void
-client_check_window_change(void)
+client_check_window_change(struct ssh *ssh)
{
- struct winsize ws;
-
- if (! received_window_change_signal)
+ if (!received_window_change_signal)
return;
- /** XXX race */
received_window_change_signal = 0;
-
- debug2("client_check_window_change: changed");
-
- if (compat20) {
- channel_send_window_changes();
- } else {
- if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
- return;
- packet_start(SSH_CMSG_WINDOW_SIZE);
- packet_put_int((u_int)ws.ws_row);
- packet_put_int((u_int)ws.ws_col);
- packet_put_int((u_int)ws.ws_xpixel);
- packet_put_int((u_int)ws.ws_ypixel);
- packet_send();
- }
+ debug2("%s: changed", __func__);
+ channel_send_window_changes(ssh);
}
static int
-client_global_request_reply(int type, u_int32_t seq, void *ctxt)
+client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh)
{
struct global_confirm *gc;
if ((gc = TAILQ_FIRST(&global_confirms)) == NULL)
return 0;
if (gc->cb != NULL)
- gc->cb(type, seq, gc->ctx);
+ gc->cb(ssh, type, seq, gc->ctx);
if (--gc->ref_count <= 0) {
TAILQ_REMOVE(&global_confirms, gc, entry);
- explicit_bzero(gc, sizeof(*gc));
- free(gc);
+ freezero(gc, sizeof(*gc));
}
- packet_set_alive_timeouts(0);
+ ssh_packet_set_alive_timeouts(ssh, 0);
return 0;
}
static void
-server_alive_check(void)
+server_alive_check(struct ssh *ssh)
{
- if (packet_inc_alive_timeouts() > options.server_alive_count_max) {
+ int r;
+
+ if (ssh_packet_inc_alive_timeouts(ssh) > options.server_alive_count_max) {
logit("Timeout, server %s not responding.", host);
cleanup_exit(255);
}
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring("keepalive@openssh.com");
- packet_put_char(1); /* boolean: want reply */
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "keepalive@openssh.com")) != 0 ||
+ (r = sshpkt_put_u8(ssh, 1)) != 0 || /* boolean: want reply */
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: send packet: %s", __func__, ssh_err(r));
/* Insert an empty placeholder to maintain ordering */
client_register_global_confirm(NULL, NULL);
}
@@ -577,51 +489,32 @@ server_alive_check(void)
* one of the file descriptors).
*/
static void
-client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
+client_wait_until_can_do_something(struct ssh *ssh,
+ fd_set **readsetp, fd_set **writesetp,
int *maxfdp, u_int *nallocp, int rekeying)
{
struct timeval tv, *tvp;
int timeout_secs;
time_t minwait_secs = 0, server_alive_time = 0, now = monotime();
- int ret;
+ int r, ret;
/* Add any selections by the channel mechanism. */
- channel_prepare_select(readsetp, writesetp, maxfdp, nallocp,
- &minwait_secs, rekeying);
-
- if (!compat20) {
- /* Read from the connection, unless our buffers are full. */
- if (buffer_len(&stdout_buffer) < buffer_high &&
- buffer_len(&stderr_buffer) < buffer_high &&
- channel_not_very_much_buffered_data())
- FD_SET(connection_in, *readsetp);
- /*
- * Read from stdin, unless we have seen EOF or have very much
- * buffered data to send to the server.
- */
- if (!stdin_eof && packet_not_very_much_data_to_write())
- FD_SET(fileno(stdin), *readsetp);
-
- /* Select stdout/stderr if have data in buffer. */
- if (buffer_len(&stdout_buffer) > 0)
- FD_SET(fileno(stdout), *writesetp);
- if (buffer_len(&stderr_buffer) > 0)
- FD_SET(fileno(stderr), *writesetp);
- } else {
- /* channel_prepare_select could have closed the last channel */
- if (session_closed && !channel_still_open() &&
- !packet_have_data_to_write()) {
- /* clear mask since we did not call select() */
- memset(*readsetp, 0, *nallocp);
- memset(*writesetp, 0, *nallocp);
- return;
- } else {
- FD_SET(connection_in, *readsetp);
- }
+ channel_prepare_select(ssh, readsetp, writesetp, maxfdp,
+ nallocp, &minwait_secs);
+
+ /* channel_prepare_select could have closed the last channel */
+ if (session_closed && !channel_still_open(ssh) &&
+ !ssh_packet_have_data_to_write(ssh)) {
+ /* clear mask since we did not call select() */
+ memset(*readsetp, 0, *nallocp);
+ memset(*writesetp, 0, *nallocp);
+ return;
}
+ FD_SET(connection_in, *readsetp);
+
/* Select server connection if have data to write to the server. */
- if (packet_have_data_to_write())
+ if (ssh_packet_have_data_to_write(ssh))
FD_SET(connection_out, *writesetp);
/*
@@ -631,21 +524,22 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
*/
timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
- if (options.server_alive_interval > 0 && compat20) {
+ if (options.server_alive_interval > 0) {
timeout_secs = options.server_alive_interval;
server_alive_time = now + options.server_alive_interval;
}
- if (options.rekey_interval > 0 && compat20 && !rekeying)
- timeout_secs = MIN(timeout_secs, packet_get_rekey_timeout());
- set_control_persist_exit_time();
+ if (options.rekey_interval > 0 && !rekeying)
+ timeout_secs = MINIMUM(timeout_secs,
+ ssh_packet_get_rekey_timeout(ssh));
+ set_control_persist_exit_time(ssh);
if (control_persist_exit_time > 0) {
- timeout_secs = MIN(timeout_secs,
+ timeout_secs = MINIMUM(timeout_secs,
control_persist_exit_time - now);
if (timeout_secs < 0)
timeout_secs = 0;
}
if (minwait_secs != 0)
- timeout_secs = MIN(timeout_secs, (int)minwait_secs);
+ timeout_secs = MINIMUM(timeout_secs, (int)minwait_secs);
if (timeout_secs == INT_MAX)
tvp = NULL;
else {
@@ -655,9 +549,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
}
ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
- if (ret < 0) {
- char buf[100];
-
+ if (ret == -1) {
/*
* We have to clear the select masks, because we return.
* We have to return, because the mainloop checks for the flags
@@ -669,8 +561,9 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
if (errno == EINTR)
return;
/* Note: we might still have data in the buffers. */
- snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
- buffer_append(&stderr_buffer, buf, strlen(buf));
+ if ((r = sshbuf_putf(stderr_buffer,
+ "select: %s\r\n", strerror(errno))) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
quit_pending = 1;
} else if (ret == 0) {
/*
@@ -678,31 +571,27 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
* Keepalive we check here, rekeying is checked in clientloop.
*/
if (server_alive_time != 0 && server_alive_time <= monotime())
- server_alive_check();
+ server_alive_check(ssh);
}
}
static void
-client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
+client_suspend_self(struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr)
{
/* Flush stdout and stderr buffers. */
- if (buffer_len(bout) > 0)
- atomicio(vwrite, fileno(stdout), buffer_ptr(bout),
- buffer_len(bout));
- if (buffer_len(berr) > 0)
- atomicio(vwrite, fileno(stderr), buffer_ptr(berr),
- buffer_len(berr));
+ if (sshbuf_len(bout) > 0)
+ atomicio(vwrite, fileno(stdout), sshbuf_mutable_ptr(bout),
+ sshbuf_len(bout));
+ if (sshbuf_len(berr) > 0)
+ atomicio(vwrite, fileno(stderr), sshbuf_mutable_ptr(berr),
+ sshbuf_len(berr));
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
- /*
- * Free (and clear) the buffer to reduce the amount of data that gets
- * written to swap.
- */
- buffer_free(bin);
- buffer_free(bout);
- buffer_free(berr);
+ sshbuf_reset(bin);
+ sshbuf_reset(bout);
+ sshbuf_reset(berr);
/* Send the suspend signal to the program itself. */
kill(getpid(), SIGTSTP);
@@ -710,19 +599,14 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
/* Reset window sizes in case they have changed */
received_window_change_signal = 1;
- /* OK, we have been continued by the user. Reinitialize buffers. */
- buffer_init(bin);
- buffer_init(bout);
- buffer_init(berr);
-
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
}
static void
-client_process_net_input(fd_set *readset)
+client_process_net_input(struct ssh *ssh, fd_set *readset)
{
- int len, cont = 0;
char buf[SSH_IOBUFSZ];
+ int r, len;
/*
* Read input from the server, and add any such data to the buffer of
@@ -730,16 +614,17 @@ client_process_net_input(fd_set *readset)
*/
if (FD_ISSET(connection_in, readset)) {
/* Read as much as possible. */
- len = roaming_read(connection_in, buf, sizeof(buf), &cont);
- if (len == 0 && cont == 0) {
+ len = read(connection_in, buf, sizeof(buf));
+ if (len == 0) {
/*
* Received EOF. The remote host has closed the
* connection.
*/
- snprintf(buf, sizeof buf,
+ if ((r = sshbuf_putf(stderr_buffer,
"Connection to %.300s closed by remote host.\r\n",
- host);
- buffer_append(&stderr_buffer, buf, strlen(buf));
+ host)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
quit_pending = 1;
return;
}
@@ -747,32 +632,33 @@ client_process_net_input(fd_set *readset)
* There is a kernel bug on Solaris that causes select to
* sometimes wake up even though there is no data available.
*/
- if (len < 0 &&
+ if (len == -1 &&
(errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
len = 0;
- if (len < 0) {
+ if (len == -1) {
/*
* An error has encountered. Perhaps there is a
* network problem.
*/
- snprintf(buf, sizeof buf,
+ if ((r = sshbuf_putf(stderr_buffer,
"Read from remote host %.300s: %.100s\r\n",
- host, strerror(errno));
- buffer_append(&stderr_buffer, buf, strlen(buf));
+ host, strerror(errno))) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
quit_pending = 1;
return;
}
- packet_process_incoming(buf, len);
+ ssh_packet_process_incoming(ssh, buf, len);
}
}
static void
-client_status_confirm(int type, Channel *c, void *ctx)
+client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx)
{
struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx;
char errmsg[256];
- int tochan;
+ int r, tochan;
/*
* If a TTY was explicitly requested, then a failure to allocate
@@ -783,7 +669,7 @@ client_status_confirm(int type, Channel *c, void *ctx)
options.request_tty == REQUEST_TTY_YES))
cr->action = CONFIRM_CLOSE;
- /* XXX supress on mux _client_ quietmode */
+ /* XXX suppress on mux _client_ quietmode */
tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
@@ -807,8 +693,10 @@ client_status_confirm(int type, Channel *c, void *ctx)
* their stderr.
*/
if (tochan) {
- buffer_append(&c->extended, errmsg,
- strlen(errmsg));
+ if ((r = sshbuf_put(c->extended, errmsg,
+ strlen(errmsg))) != 0)
+ fatal("%s: buffer error %s", __func__,
+ ssh_err(r));
} else
error("%s", errmsg);
if (cr->action == CONFIRM_TTY) {
@@ -819,23 +707,23 @@ client_status_confirm(int type, Channel *c, void *ctx)
if (c->self == session_ident)
leave_raw_mode(0);
else
- mux_tty_alloc_failed(c);
+ mux_tty_alloc_failed(ssh, c);
} else if (cr->action == CONFIRM_CLOSE) {
- chan_read_failed(c);
- chan_write_failed(c);
+ chan_read_failed(ssh, c);
+ chan_write_failed(ssh, c);
}
}
free(cr);
}
static void
-client_abandon_status_confirm(Channel *c, void *ctx)
+client_abandon_status_confirm(struct ssh *ssh, Channel *c, void *ctx)
{
free(ctx);
}
void
-client_expect_confirm(int id, const char *request,
+client_expect_confirm(struct ssh *ssh, int id, const char *request,
enum confirm_action action)
{
struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr));
@@ -843,7 +731,7 @@ client_expect_confirm(int id, const char *request,
cr->request_type = request;
cr->action = action;
- channel_register_status_confirm(id, client_status_confirm,
+ channel_register_status_confirm(ssh, id, client_status_confirm,
client_abandon_status_confirm, cr);
}
@@ -869,7 +757,7 @@ client_register_global_confirm(global_confirm_cb *cb, void *ctx)
}
static void
-process_cmdline(void)
+process_cmdline(struct ssh *ssh)
{
void (*handler)(int);
char *s, *cmd;
@@ -879,7 +767,7 @@ process_cmdline(void)
memset(&fwd, 0, sizeof(fwd));
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
- handler = signal(SIGINT, SIG_IGN);
+ handler = ssh_signal(SIGINT, SIG_IGN);
cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
if (s == NULL)
goto out;
@@ -932,11 +820,6 @@ process_cmdline(void)
goto out;
}
- if (delete && !compat20) {
- logit("Not supported for SSH protocol version 1.");
- goto out;
- }
-
while (isspace((u_char)*++s))
;
@@ -948,16 +831,16 @@ process_cmdline(void)
goto out;
}
if (remote)
- ok = channel_request_rforward_cancel(&fwd) == 0;
+ ok = channel_request_rforward_cancel(ssh, &fwd) == 0;
else if (dynamic)
- ok = channel_cancel_lport_listener(&fwd,
+ ok = channel_cancel_lport_listener(ssh, &fwd,
0, &options.fwd_opts) > 0;
else
- ok = channel_cancel_lport_listener(&fwd,
+ ok = channel_cancel_lport_listener(ssh, &fwd,
CHANNEL_CANCEL_PORT_STATIC,
&options.fwd_opts) > 0;
if (!ok) {
- logit("Unkown port forwarding.");
+ logit("Unknown port forwarding.");
goto out;
}
logit("Canceled forwarding.");
@@ -967,13 +850,13 @@ process_cmdline(void)
goto out;
}
if (local || dynamic) {
- if (!channel_setup_local_fwd_listener(&fwd,
+ if (!channel_setup_local_fwd_listener(ssh, &fwd,
&options.fwd_opts)) {
logit("Port forwarding failed.");
goto out;
}
} else {
- if (channel_request_remote_forwarding(&fwd) < 0) {
+ if (channel_request_remote_forwarding(ssh, &fwd) < 0) {
logit("Port forwarding failed.");
goto out;
}
@@ -982,7 +865,7 @@ process_cmdline(void)
}
out:
- signal(SIGINT, handler);
+ ssh_signal(SIGINT, handler);
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
free(cmd);
free(fwd.listen_host);
@@ -993,10 +876,9 @@ out:
/* reasons to suppress output of an escape command in help output */
#define SUPPRESS_NEVER 0 /* never suppress, always show */
-#define SUPPRESS_PROTO1 1 /* don't show in protocol 1 sessions */
-#define SUPPRESS_MUXCLIENT 2 /* don't show in mux client sessions */
-#define SUPPRESS_MUXMASTER 4 /* don't show in mux master sessions */
-#define SUPPRESS_SYSLOG 8 /* don't show when logging to syslog */
+#define SUPPRESS_MUXCLIENT 1 /* don't show in mux client sessions */
+#define SUPPRESS_MUXMASTER 2 /* don't show in mux master sessions */
+#define SUPPRESS_SYSLOG 4 /* don't show when logging to syslog */
struct escape_help_text {
const char *cmd;
const char *text;
@@ -1006,9 +888,9 @@ static struct escape_help_text esc_txt[] = {
{".", "terminate session", SUPPRESS_MUXMASTER},
{".", "terminate connection (and any multiplexed sessions)",
SUPPRESS_MUXCLIENT},
- {"B", "send a BREAK to the remote system", SUPPRESS_PROTO1},
+ {"B", "send a BREAK to the remote system", SUPPRESS_NEVER},
{"C", "open a command line", SUPPRESS_MUXCLIENT},
- {"R", "request rekey", SUPPRESS_PROTO1},
+ {"R", "request rekey", SUPPRESS_NEVER},
{"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT},
{"^Z", "suspend ssh", SUPPRESS_MUXCLIENT},
{"#", "list forwarded connections", SUPPRESS_NEVER},
@@ -1018,17 +900,17 @@ static struct escape_help_text esc_txt[] = {
};
static void
-print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client,
+print_escape_help(struct sshbuf *b, int escape_char, int mux_client,
int using_stderr)
{
unsigned int i, suppress_flags;
- char string[1024];
+ int r;
- snprintf(string, sizeof string, "%c?\r\n"
- "Supported escape sequences:\r\n", escape_char);
- buffer_append(b, string, strlen(string));
+ if ((r = sshbuf_putf(b,
+ "%c?\r\nSupported escape sequences:\r\n", escape_char)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- suppress_flags = (protocol2 ? 0 : SUPPRESS_PROTO1) |
+ suppress_flags =
(mux_client ? SUPPRESS_MUXCLIENT : 0) |
(mux_client ? 0 : SUPPRESS_MUXMASTER) |
(using_stderr ? 0 : SUPPRESS_SYSLOG);
@@ -1036,45 +918,37 @@ print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client,
for (i = 0; i < sizeof(esc_txt)/sizeof(esc_txt[0]); i++) {
if (esc_txt[i].flags & suppress_flags)
continue;
- snprintf(string, sizeof string, " %c%-3s - %s\r\n",
- escape_char, esc_txt[i].cmd, esc_txt[i].text);
- buffer_append(b, string, strlen(string));
+ 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));
}
- snprintf(string, sizeof string,
+ 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);
- buffer_append(b, string, strlen(string));
+ "newline.)\r\n", escape_char, escape_char)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
-/*
- * Process the characters one by one, call with c==NULL for proto1 case.
+/*
+ * Process the characters one by one.
*/
static int
-process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
+process_escapes(struct ssh *ssh, Channel *c,
+ struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr,
char *buf, int len)
{
- char string[1024];
pid_t pid;
- int bytes = 0;
+ int r, bytes = 0;
u_int i;
u_char ch;
char *s;
- int *escape_pendingp, escape_char;
- struct escape_filter_ctx *efc;
+ struct escape_filter_ctx *efc = c->filter_ctx == NULL ?
+ NULL : (struct escape_filter_ctx *)c->filter_ctx;
+
+ if (c->filter_ctx == NULL)
+ return 0;
- if (c == NULL) {
- escape_pendingp = &escape_pending1;
- escape_char = escape_char1;
- } else {
- if (c->filter_ctx == NULL)
- return 0;
- efc = (struct escape_filter_ctx *)c->filter_ctx;
- escape_pendingp = &efc->escape_pending;
- escape_char = efc->escape_char;
- }
-
if (len <= 0)
return (0);
@@ -1082,27 +956,29 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
/* Get one character at a time. */
ch = buf[i];
- if (*escape_pendingp) {
+ if (efc->escape_pending) {
/* We have previously seen an escape character. */
/* Clear the flag now. */
- *escape_pendingp = 0;
+ efc->escape_pending = 0;
/* Process the escaped character. */
switch (ch) {
case '.':
/* Terminate the connection. */
- snprintf(string, sizeof string, "%c.\r\n",
- escape_char);
- buffer_append(berr, string, strlen(string));
-
+ if ((r = sshbuf_putf(berr, "%c.\r\n",
+ efc->escape_char)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
if (c && c->ctl_chan != -1) {
- chan_read_failed(c);
- chan_write_failed(c);
- if (c->detach_user)
- c->detach_user(c->self, NULL);
+ chan_read_failed(ssh, c);
+ chan_write_failed(ssh, c);
+ if (c->detach_user) {
+ c->detach_user(ssh,
+ c->self, NULL);
+ }
c->type = SSH_CHANNEL_ABANDONED;
- buffer_clear(&c->input);
- chan_ibuf_empty(c);
+ sshbuf_reset(c->input);
+ chan_ibuf_empty(ssh, c);
return 0;
} else
quit_pending = 1;
@@ -1117,18 +993,20 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
snprintf(b, sizeof b, "^Z");
else
snprintf(b, sizeof b, "%c", ch);
- snprintf(string, sizeof string,
+ if ((r = sshbuf_putf(berr,
"%c%s escape not available to "
"multiplexed sessions\r\n",
- escape_char, b);
- buffer_append(berr, string,
- strlen(string));
+ efc->escape_char, b)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
continue;
}
/* Suspend the program. Inform the user */
- snprintf(string, sizeof string,
- "%c^Z [suspend ssh]\r\n", escape_char);
- buffer_append(berr, string, strlen(string));
+ if ((r = sshbuf_putf(berr,
+ "%c^Z [suspend ssh]\r\n",
+ efc->escape_char)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
/* Restore terminal modes and suspend. */
client_suspend_self(bin, bout, berr);
@@ -1137,26 +1015,23 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
continue;
case 'B':
- if (compat20) {
- snprintf(string, sizeof string,
- "%cB\r\n", escape_char);
- buffer_append(berr, string,
- strlen(string));
- channel_request_start(c->self,
- "break", 0);
- packet_put_int(1000);
- packet_send();
- }
+ if ((r = sshbuf_putf(berr,
+ "%cB\r\n", efc->escape_char)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
+ channel_request_start(ssh, c->self, "break", 0);
+ if ((r = sshpkt_put_u32(ssh, 1000)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: send packet: %s", __func__,
+ ssh_err(r));
continue;
case 'R':
- if (compat20) {
- if (datafellows & SSH_BUG_NOREKEY)
- logit("Server does not "
- "support re-keying");
- else
- need_rekeying = 1;
- }
+ if (datafellows & SSH_BUG_NOREKEY)
+ logit("Server does not "
+ "support re-keying");
+ else
+ need_rekeying = 1;
continue;
case 'V':
@@ -1165,11 +1040,11 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
if (c && c->ctl_chan != -1)
goto noescape;
if (!log_is_on_stderr()) {
- snprintf(string, sizeof string,
+ if ((r = sshbuf_putf(berr,
"%c%c [Logging to syslog]\r\n",
- escape_char, ch);
- buffer_append(berr, string,
- strlen(string));
+ efc->escape_char, ch)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
continue;
}
if (ch == 'V' && options.log_level >
@@ -1178,10 +1053,12 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
if (ch == 'v' && options.log_level <
SYSLOG_LEVEL_DEBUG3)
log_change_level(++options.log_level);
- snprintf(string, sizeof string,
- "%c%c [LogLevel %s]\r\n", escape_char, ch,
- log_level_name(options.log_level));
- buffer_append(berr, string, strlen(string));
+ if ((r = sshbuf_putf(berr,
+ "%c%c [LogLevel %s]\r\n",
+ efc->escape_char, ch,
+ log_level_name(options.log_level))) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
continue;
case '&':
@@ -1197,15 +1074,17 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
options.request_tty == REQUEST_TTY_FORCE);
/* Stop listening for new connections. */
- channel_stop_listening();
+ channel_stop_listening(ssh);
- snprintf(string, sizeof string,
- "%c& [backgrounded]\n", escape_char);
- buffer_append(berr, string, strlen(string));
+ if ((r = sshbuf_putf(berr,
+ "%c& [backgrounded]\n", efc->escape_char))
+ != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
/* Fork into background. */
pid = fork();
- if (pid < 0) {
+ if (pid == -1) {
error("fork: %.100s", strerror(errno));
continue;
}
@@ -1214,52 +1093,41 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
exit(0);
}
/* The child continues serving connections. */
- if (compat20) {
- buffer_append(bin, "\004", 1);
- /* fake EOF on stdin */
- return -1;
- } else if (!stdin_eof) {
- /*
- * Sending SSH_CMSG_EOF alone does not
- * always appear to be enough. So we
- * try to send an EOF character first.
- */
- packet_start(SSH_CMSG_STDIN_DATA);
- packet_put_string("\004", 1);
- packet_send();
- /* Close stdin. */
- stdin_eof = 1;
- if (buffer_len(bin) == 0) {
- packet_start(SSH_CMSG_EOF);
- packet_send();
- }
- }
- continue;
-
+ /* fake EOF on stdin */
+ if ((r = sshbuf_put_u8(bin, 4)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
+ return -1;
case '?':
- print_escape_help(berr, escape_char, compat20,
+ print_escape_help(berr, efc->escape_char,
(c && c->ctl_chan != -1),
log_is_on_stderr());
continue;
case '#':
- snprintf(string, sizeof string, "%c#\r\n",
- escape_char);
- buffer_append(berr, string, strlen(string));
- s = channel_open_message();
- buffer_append(berr, s, strlen(s));
+ if ((r = sshbuf_putf(berr, "%c#\r\n",
+ efc->escape_char)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
+ s = channel_open_message(ssh);
+ if ((r = sshbuf_put(berr, s, strlen(s))) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
free(s);
continue;
case 'C':
if (c && c->ctl_chan != -1)
goto noescape;
- process_cmdline();
+ process_cmdline(ssh);
continue;
default:
- if (ch != escape_char) {
- buffer_put_char(bin, escape_char);
+ if (ch != efc->escape_char) {
+ if ((r = sshbuf_put_u8(bin,
+ efc->escape_char)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
bytes++;
}
/* Escaped characters fall through here */
@@ -1270,12 +1138,12 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
* The previous character was not an escape char.
* Check if this is an escape.
*/
- if (last_was_cr && ch == escape_char) {
+ if (last_was_cr && ch == efc->escape_char) {
/*
* It is. Set the flag and continue to
* next character.
*/
- *escape_pendingp = 1;
+ efc->escape_pending = 1;
continue;
}
}
@@ -1285,121 +1153,13 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
* and append it to the buffer.
*/
last_was_cr = (ch == '\r' || ch == '\n');
- buffer_put_char(bin, ch);
+ if ((r = sshbuf_put_u8(bin, ch)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
bytes++;
}
return bytes;
}
-static void
-client_process_input(fd_set *readset)
-{
- int len;
- char buf[SSH_IOBUFSZ];
-
- /* Read input from stdin. */
- if (FD_ISSET(fileno(stdin), readset)) {
- /* Read as much as possible. */
- len = read(fileno(stdin), buf, sizeof(buf));
- if (len < 0 &&
- (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
- return; /* we'll try again later */
- if (len <= 0) {
- /*
- * Received EOF or error. They are treated
- * similarly, except that an error message is printed
- * if it was an error condition.
- */
- if (len < 0) {
- snprintf(buf, sizeof buf, "read: %.100s\r\n",
- strerror(errno));
- buffer_append(&stderr_buffer, buf, strlen(buf));
- }
- /* Mark that we have seen EOF. */
- stdin_eof = 1;
- /*
- * Send an EOF message to the server unless there is
- * data in the buffer. If there is data in the
- * buffer, no message will be sent now. Code
- * elsewhere will send the EOF when the buffer
- * becomes empty if stdin_eof is set.
- */
- if (buffer_len(&stdin_buffer) == 0) {
- packet_start(SSH_CMSG_EOF);
- packet_send();
- }
- } else if (escape_char1 == SSH_ESCAPECHAR_NONE) {
- /*
- * Normal successful read, and no escape character.
- * Just append the data to buffer.
- */
- buffer_append(&stdin_buffer, buf, len);
- } else {
- /*
- * Normal, successful read. But we have an escape
- * character and have to process the characters one
- * by one.
- */
- if (process_escapes(NULL, &stdin_buffer,
- &stdout_buffer, &stderr_buffer, buf, len) == -1)
- return;
- }
- }
-}
-
-static void
-client_process_output(fd_set *writeset)
-{
- int len;
- char buf[100];
-
- /* Write buffered output to stdout. */
- if (FD_ISSET(fileno(stdout), writeset)) {
- /* Write as much data as possible. */
- len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
- buffer_len(&stdout_buffer));
- if (len <= 0) {
- if (errno == EINTR || errno == EAGAIN ||
- errno == EWOULDBLOCK)
- len = 0;
- else {
- /*
- * An error or EOF was encountered. Put an
- * error message to stderr buffer.
- */
- snprintf(buf, sizeof buf,
- "write stdout: %.50s\r\n", strerror(errno));
- buffer_append(&stderr_buffer, buf, strlen(buf));
- quit_pending = 1;
- return;
- }
- }
- /* Consume printed data from the buffer. */
- buffer_consume(&stdout_buffer, len);
- }
- /* Write buffered output to stderr. */
- if (FD_ISSET(fileno(stderr), writeset)) {
- /* Write as much data as possible. */
- len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
- buffer_len(&stderr_buffer));
- if (len <= 0) {
- if (errno == EINTR || errno == EAGAIN ||
- errno == EWOULDBLOCK)
- len = 0;
- else {
- /*
- * EOF or error, but can't even print
- * error message.
- */
- quit_pending = 1;
- return;
- }
- }
- /* Consume printed characters from the buffer. */
- buffer_consume(&stderr_buffer, len);
- }
-}
-
/*
* Get packets from the connection input buffer, and process them as long as
* there are packets available.
@@ -1413,9 +1173,9 @@ client_process_output(fd_set *writeset)
*/
static void
-client_process_buffered_input_packets(void)
+client_process_buffered_input_packets(struct ssh *ssh)
{
- dispatch_run(DISPATCH_NONBLOCK, &quit_pending, active_state);
+ ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, &quit_pending);
}
/* scan buf[] for '~' before sending data to the peer */
@@ -1434,25 +1194,25 @@ client_new_escape_filter_ctx(int escape_char)
/* Free the escape filter context on channel free */
void
-client_filter_cleanup(int cid, void *ctx)
+client_filter_cleanup(struct ssh *ssh, int cid, void *ctx)
{
free(ctx);
}
int
-client_simple_escape_filter(Channel *c, char *buf, int len)
+client_simple_escape_filter(struct ssh *ssh, Channel *c, char *buf, int len)
{
if (c->extended_usage != CHAN_EXTENDED_WRITE)
return 0;
- return process_escapes(c, &c->input, &c->output, &c->extended,
+ return process_escapes(ssh, c, c->input, c->output, c->extended,
buf, len);
}
static void
-client_channel_closed(int id, void *arg)
+client_channel_closed(struct ssh *ssh, int id, void *arg)
{
- channel_cancel_cleanup(id);
+ channel_cancel_cleanup(ssh, id);
session_closed = 1;
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
}
@@ -1463,121 +1223,128 @@ client_channel_closed(int id, void *arg)
* remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character
* used as an escape character for terminating or suspending the session.
*/
-
int
-client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
+client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
+ int ssh2_chan_id)
{
fd_set *readset = NULL, *writeset = NULL;
double start_time, total_time;
- int r, max_fd = 0, max_fd2 = 0, len, rekeying = 0;
+ 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.");
- start_time = get_current_time();
+ if (options.control_master &&
+ !option_clear_or_none(options.control_path)) {
+ debug("pledge: id");
+ if (pledge("stdio rpath wpath cpath unix inet dns recvfd sendfd proc exec id tty",
+ NULL) == -1)
+ fatal("%s pledge(): %s", __func__, strerror(errno));
+
+ } else if (options.forward_x11 || options.permit_local_command) {
+ debug("pledge: exec");
+ if (pledge("stdio rpath wpath cpath unix inet dns proc exec tty",
+ NULL) == -1)
+ fatal("%s pledge(): %s", __func__, strerror(errno));
+
+ } else if (options.update_hostkeys) {
+ debug("pledge: filesystem full");
+ if (pledge("stdio rpath wpath cpath unix inet dns proc tty",
+ NULL) == -1)
+ fatal("%s pledge(): %s", __func__, strerror(errno));
+
+ } else if (!option_clear_or_none(options.proxy_command) ||
+ fork_after_authentication_flag) {
+ debug("pledge: proc");
+ if (pledge("stdio cpath unix inet dns proc tty", NULL) == -1)
+ fatal("%s pledge(): %s", __func__, strerror(errno));
+
+ } else {
+ debug("pledge: network");
+ if (pledge("stdio unix inet dns proc tty", NULL) == -1)
+ fatal("%s pledge(): %s", __func__, strerror(errno));
+ }
+
+ start_time = monotime_double();
/* Initialize variables. */
- escape_pending1 = 0;
last_was_cr = 1;
exit_status = -1;
- stdin_eof = 0;
- buffer_high = 64 * 1024;
- connection_in = packet_get_connection_in();
- connection_out = packet_get_connection_out();
- max_fd = MAX(connection_in, connection_out);
-
- if (!compat20) {
- /* enable nonblocking unless tty */
- if (!isatty(fileno(stdin)))
- set_nonblock(fileno(stdin));
- if (!isatty(fileno(stdout)))
- set_nonblock(fileno(stdout));
- if (!isatty(fileno(stderr)))
- set_nonblock(fileno(stderr));
- max_fd = MAX(max_fd, fileno(stdin));
- max_fd = MAX(max_fd, fileno(stdout));
- max_fd = MAX(max_fd, fileno(stderr));
- }
+ connection_in = ssh_packet_get_connection_in(ssh);
+ connection_out = ssh_packet_get_connection_out(ssh);
+ max_fd = MAXIMUM(connection_in, connection_out);
+
quit_pending = 0;
- escape_char1 = escape_char_arg;
- /* Initialize buffers. */
- buffer_init(&stdin_buffer);
- buffer_init(&stdout_buffer);
- buffer_init(&stderr_buffer);
+ /* Initialize buffer. */
+ if ((stderr_buffer = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
- client_init_dispatch();
+ client_init_dispatch(ssh);
/*
* Set signal handlers, (e.g. to restore non-blocking mode)
* but don't overwrite SIG_IGN, matches behaviour from rsh(1)
*/
- if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
- signal(SIGHUP, signal_handler);
- if (signal(SIGINT, SIG_IGN) != SIG_IGN)
- signal(SIGINT, signal_handler);
- if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
- signal(SIGQUIT, signal_handler);
- if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
- signal(SIGTERM, signal_handler);
- signal(SIGWINCH, window_change_handler);
+ if (ssh_signal(SIGHUP, SIG_IGN) != SIG_IGN)
+ ssh_signal(SIGHUP, signal_handler);
+ if (ssh_signal(SIGINT, SIG_IGN) != SIG_IGN)
+ ssh_signal(SIGINT, signal_handler);
+ if (ssh_signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+ ssh_signal(SIGQUIT, signal_handler);
+ if (ssh_signal(SIGTERM, SIG_IGN) != SIG_IGN)
+ ssh_signal(SIGTERM, signal_handler);
+ ssh_signal(SIGWINCH, window_change_handler);
if (have_pty)
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
- if (compat20) {
- session_ident = ssh2_chan_id;
- if (session_ident != -1) {
- if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
- channel_register_filter(session_ident,
- client_simple_escape_filter, NULL,
- client_filter_cleanup,
- client_new_escape_filter_ctx(
- escape_char_arg));
- }
- channel_register_cleanup(session_ident,
- client_channel_closed, 0);
+ session_ident = ssh2_chan_id;
+ if (session_ident != -1) {
+ if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
+ channel_register_filter(ssh, session_ident,
+ client_simple_escape_filter, NULL,
+ client_filter_cleanup,
+ client_new_escape_filter_ctx(
+ escape_char_arg));
}
- } else {
- /* Check if we should immediately send eof on stdin. */
- client_check_initial_eof_on_stdin();
+ channel_register_cleanup(ssh, session_ident,
+ client_channel_closed, 0);
}
/* Main loop of the client for the interactive session mode. */
while (!quit_pending) {
/* Process buffered packets sent by the server. */
- client_process_buffered_input_packets();
+ client_process_buffered_input_packets(ssh);
- if (compat20 && session_closed && !channel_still_open())
+ if (session_closed && !channel_still_open(ssh))
break;
- rekeying = (active_state->kex != NULL && !active_state->kex->done);
-
- if (rekeying) {
+ if (ssh_packet_is_rekeying(ssh)) {
debug("rekeying in progress");
+ } else if (need_rekeying) {
+ /* manual rekey request */
+ debug("need rekeying");
+ if ((r = kex_start_rekex(ssh)) != 0)
+ fatal("%s: kex_start_rekex: %s", __func__,
+ ssh_err(r));
+ need_rekeying = 0;
} else {
/*
- * Make packets of buffered stdin data, and buffer
- * them for sending to the server.
- */
- if (!compat20)
- client_make_packets_from_stdin_data();
-
- /*
* Make packets from buffered channel data, and
* enqueue them for sending to the server.
*/
- if (packet_not_very_much_data_to_write())
- channel_output_poll();
+ if (ssh_packet_not_very_much_data_to_write(ssh))
+ channel_output_poll(ssh);
/*
* Check if the window size has changed, and buffer a
* message about it to the server if so.
*/
- client_check_window_change();
+ client_check_window_change(ssh);
if (quit_pending)
break;
@@ -1587,55 +1354,32 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
* available on one of the descriptors).
*/
max_fd2 = max_fd;
- client_wait_until_can_do_something(&readset, &writeset,
- &max_fd2, &nalloc, rekeying);
+ client_wait_until_can_do_something(ssh, &readset, &writeset,
+ &max_fd2, &nalloc, ssh_packet_is_rekeying(ssh));
if (quit_pending)
break;
/* Do channel operations unless rekeying in progress. */
- if (!rekeying) {
- channel_after_select(readset, writeset);
- if (need_rekeying || packet_need_rekeying()) {
- debug("need rekeying");
- active_state->kex->done = 0;
- if ((r = kex_send_kexinit(active_state)) != 0)
- fatal("%s: kex_send_kexinit: %s",
- __func__, ssh_err(r));
- need_rekeying = 0;
- }
- }
+ if (!ssh_packet_is_rekeying(ssh))
+ channel_after_select(ssh, readset, writeset);
/* Buffer input from the connection. */
- client_process_net_input(readset);
+ client_process_net_input(ssh, readset);
if (quit_pending)
break;
- if (!compat20) {
- /* Buffer data from stdin */
- client_process_input(readset);
- /*
- * Process output to stdout and stderr. Output to
- * the connection is processed elsewhere (above).
- */
- client_process_output(writeset);
- }
-
- if (session_resumed) {
- connection_in = packet_get_connection_in();
- connection_out = packet_get_connection_out();
- max_fd = MAX(max_fd, connection_out);
- max_fd = MAX(max_fd, connection_in);
- session_resumed = 0;
- }
-
/*
* Send as much buffered packet data as possible to the
* sender.
*/
- if (FD_ISSET(connection_out, writeset))
- packet_write_poll();
+ if (FD_ISSET(connection_out, writeset)) {
+ if ((r = ssh_packet_write_poll(ssh)) != 0) {
+ sshpkt_fatal(ssh, r,
+ "%s: ssh_packet_write_poll", __func__);
+ }
+ }
/*
* If we are a backgrounded control master, and the
@@ -1655,18 +1399,17 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
/* Terminate the session. */
/* Stop watching for window change. */
- signal(SIGWINCH, SIG_DFL);
-
- if (compat20) {
- packet_start(SSH2_MSG_DISCONNECT);
- packet_put_int(SSH2_DISCONNECT_BY_APPLICATION);
- packet_put_cstring("disconnected by user");
- packet_put_cstring(""); /* language tag */
- packet_send();
- packet_write_wait();
- }
+ ssh_signal(SIGWINCH, SIG_DFL);
- channel_free_all();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
+ (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_BY_APPLICATION)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "disconnected by user")) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language tag */
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ fatal("%s: send disconnect: %s", __func__, ssh_err(r));
+
+ channel_free_all(ssh);
if (have_pty)
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
@@ -1689,48 +1432,39 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
exit_status = 0;
}
- if (received_signal)
- fatal("Killed by signal %d.", (int) received_signal);
+ if (received_signal) {
+ verbose("Killed by signal %d.", (int) received_signal);
+ cleanup_exit(0);
+ }
/*
* In interactive mode (with pseudo tty) display a message indicating
* that the connection has been closed.
*/
if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
- snprintf(buf, sizeof buf,
- "Connection to %.64s closed.\r\n", host);
- buffer_append(&stderr_buffer, buf, strlen(buf));
- }
-
- /* Output any buffered data for stdout. */
- if (buffer_len(&stdout_buffer) > 0) {
- len = atomicio(vwrite, fileno(stdout),
- buffer_ptr(&stdout_buffer), buffer_len(&stdout_buffer));
- if (len < 0 || (u_int)len != buffer_len(&stdout_buffer))
- error("Write failed flushing stdout buffer.");
- else
- buffer_consume(&stdout_buffer, len);
+ if ((r = sshbuf_putf(stderr_buffer,
+ "Connection to %.64s closed.\r\n", host)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
/* Output any buffered data for stderr. */
- if (buffer_len(&stderr_buffer) > 0) {
+ if (sshbuf_len(stderr_buffer) > 0) {
len = atomicio(vwrite, fileno(stderr),
- buffer_ptr(&stderr_buffer), buffer_len(&stderr_buffer));
- if (len < 0 || (u_int)len != buffer_len(&stderr_buffer))
+ (u_char *)sshbuf_ptr(stderr_buffer),
+ sshbuf_len(stderr_buffer));
+ if (len < 0 || (u_int)len != sshbuf_len(stderr_buffer))
error("Write failed flushing stderr buffer.");
- else
- buffer_consume(&stderr_buffer, len);
+ else if ((r = sshbuf_consume(stderr_buffer, len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
/* Clear and free any buffers. */
- memset(buf, 0, sizeof(buf));
- buffer_free(&stdin_buffer);
- buffer_free(&stdout_buffer);
- buffer_free(&stderr_buffer);
+ explicit_bzero(buf, sizeof(buf));
+ sshbuf_free(stderr_buffer);
/* Report bytes transferred, and transfer rates. */
- total_time = get_current_time() - start_time;
- packet_get_bytes(&ibytes, &obytes);
+ total_time = monotime_double() - start_time;
+ ssh_packet_get_bytes(ssh, &ibytes, &obytes);
verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds",
(unsigned long long)obytes, (unsigned long long)ibytes, total_time);
if (total_time > 0)
@@ -1743,145 +1477,96 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
/*********/
-static int
-client_input_stdout_data(int type, u_int32_t seq, void *ctxt)
-{
- u_int data_len;
- char *data = packet_get_string(&data_len);
- packet_check_eom();
- buffer_append(&stdout_buffer, data, data_len);
- explicit_bzero(data, data_len);
- free(data);
- return 0;
-}
-static int
-client_input_stderr_data(int type, u_int32_t seq, void *ctxt)
-{
- u_int data_len;
- char *data = packet_get_string(&data_len);
- packet_check_eom();
- buffer_append(&stderr_buffer, data, data_len);
- explicit_bzero(data, data_len);
- free(data);
- return 0;
-}
-static int
-client_input_exit_status(int type, u_int32_t seq, void *ctxt)
-{
- exit_status = packet_get_int();
- packet_check_eom();
- /* Acknowledge the exit. */
- packet_start(SSH_CMSG_EXIT_CONFIRMATION);
- packet_send();
- /*
- * Must wait for packet to be sent since we are
- * exiting the loop.
- */
- packet_write_wait();
- /* Flag that we want to exit. */
- quit_pending = 1;
- return 0;
-}
-
-static int
-client_input_agent_open(int type, u_int32_t seq, void *ctxt)
-{
- Channel *c = NULL;
- int r, remote_id, sock;
-
- /* Read the remote channel number from the message. */
- remote_id = packet_get_int();
- packet_check_eom();
-
- /*
- * Get a connection to the local authentication agent (this may again
- * get forwarded).
- */
- if ((r = ssh_get_authentication_socket(&sock)) != 0 &&
- r != SSH_ERR_AGENT_NOT_PRESENT)
- debug("%s: ssh_get_authentication_socket: %s",
- __func__, ssh_err(r));
-
-
- /*
- * If we could not connect the agent, send an error message back to
- * the server. This should never happen unless the agent dies,
- * because authentication forwarding is only enabled if we have an
- * agent.
- */
- if (sock >= 0) {
- c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
- -1, 0, 0, 0, "authentication agent connection", 1);
- c->remote_id = remote_id;
- c->force_drain = 1;
- }
- if (c == NULL) {
- packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(remote_id);
- } else {
- /* Send a confirmation to the remote host. */
- debug("Forwarding authentication connection.");
- packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(remote_id);
- packet_put_int(c->self);
- }
- packet_send();
- return 0;
-}
-
static Channel *
-client_request_forwarded_tcpip(const char *request_type, int rchan)
+client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type,
+ int rchan, u_int rwindow, u_int rmaxpack)
{
Channel *c = NULL;
+ struct sshbuf *b = NULL;
char *listen_address, *originator_address;
- u_short listen_port, originator_port;
+ u_int listen_port, originator_port;
+ int r;
/* Get rest of the packet */
- listen_address = packet_get_string(NULL);
- listen_port = packet_get_int();
- originator_address = packet_get_string(NULL);
- originator_port = packet_get_int();
- packet_check_eom();
+ if ((r = sshpkt_get_cstring(ssh, &listen_address, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &listen_port)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &originator_address, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: parse packet: %s", __func__, ssh_err(r));
debug("%s: listen %s port %d, originator %s port %d", __func__,
listen_address, listen_port, originator_address, originator_port);
- c = channel_connect_by_listen_address(listen_address, listen_port,
- "forwarded-tcpip", originator_address);
+ if (listen_port > 0xffff)
+ error("%s: invalid listen port", __func__);
+ else if (originator_port > 0xffff)
+ error("%s: invalid originator port", __func__);
+ else {
+ c = channel_connect_by_listen_address(ssh,
+ listen_address, listen_port, "forwarded-tcpip",
+ originator_address);
+ }
+
+ if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) {
+ if ((b = sshbuf_new()) == NULL) {
+ error("%s: alloc reply", __func__);
+ goto out;
+ }
+ /* reconstruct and send to muxclient */
+ if ((r = sshbuf_put_u8(b, 0)) != 0 || /* padlen */
+ (r = sshbuf_put_u8(b, SSH2_MSG_CHANNEL_OPEN)) != 0 ||
+ (r = sshbuf_put_cstring(b, request_type)) != 0 ||
+ (r = sshbuf_put_u32(b, rchan)) != 0 ||
+ (r = sshbuf_put_u32(b, rwindow)) != 0 ||
+ (r = sshbuf_put_u32(b, rmaxpack)) != 0 ||
+ (r = sshbuf_put_cstring(b, listen_address)) != 0 ||
+ (r = sshbuf_put_u32(b, listen_port)) != 0 ||
+ (r = sshbuf_put_cstring(b, originator_address)) != 0 ||
+ (r = sshbuf_put_u32(b, originator_port)) != 0 ||
+ (r = sshbuf_put_stringb(c->output, b)) != 0) {
+ error("%s: compose for muxclient %s", __func__,
+ ssh_err(r));
+ goto out;
+ }
+ }
+ out:
+ sshbuf_free(b);
free(originator_address);
free(listen_address);
return c;
}
static Channel *
-client_request_forwarded_streamlocal(const char *request_type, int rchan)
+client_request_forwarded_streamlocal(struct ssh *ssh,
+ const char *request_type, int rchan)
{
Channel *c = NULL;
char *listen_path;
+ int r;
/* Get the remote path. */
- listen_path = packet_get_string(NULL);
- /* XXX: Skip reserved field for now. */
- if (packet_get_string_ptr(NULL) == NULL)
- fatal("%s: packet_get_string_ptr failed", __func__);
- packet_check_eom();
+ if ((r = sshpkt_get_cstring(ssh, &listen_path, NULL)) != 0 ||
+ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* reserved */
+ (r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: parse packet: %s", __func__, ssh_err(r));
- debug("%s: %s", __func__, listen_path);
+ debug("%s: request: %s", __func__, listen_path);
- c = channel_connect_by_listen_path(listen_path,
+ c = channel_connect_by_listen_path(ssh, listen_path,
"forwarded-streamlocal@openssh.com", "forwarded-streamlocal");
free(listen_path);
return c;
}
static Channel *
-client_request_x11(const char *request_type, int rchan)
+client_request_x11(struct ssh *ssh, const char *request_type, int rchan)
{
Channel *c = NULL;
char *originator;
- u_short originator_port;
- int sock;
+ u_int originator_port;
+ int r, sock;
if (!options.forward_x11) {
error("Warning: ssh server tried X11 forwarding.");
@@ -1889,27 +1574,24 @@ client_request_x11(const char *request_type, int rchan)
"malicious server.");
return NULL;
}
- if (x11_refuse_time != 0 && monotime() >= x11_refuse_time) {
+ if (x11_refuse_time != 0 && (u_int)monotime() >= x11_refuse_time) {
verbose("Rejected X11 connection after ForwardX11Timeout "
"expired");
return NULL;
}
- originator = packet_get_string(NULL);
- if (datafellows & SSH_BUG_X11FWD) {
- debug2("buggy server: x11 request w/o originator_port");
- originator_port = 0;
- } else {
- originator_port = packet_get_int();
- }
- packet_check_eom();
+ if ((r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: parse packet: %s", __func__, ssh_err(r));
/* XXX check permission */
- debug("client_request_x11: request from %s %d", originator,
+ /* XXX range check originator port? */
+ debug("client_request_x11: request from %s %u", originator,
originator_port);
free(originator);
- sock = x11_connect_display();
+ sock = x11_connect_display(ssh);
if (sock < 0)
return NULL;
- c = channel_new("x11",
+ c = channel_new(ssh, "x11",
SSH_CHANNEL_X11_OPEN, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
c->force_drain = 1;
@@ -1917,7 +1599,7 @@ client_request_x11(const char *request_type, int rchan)
}
static Channel *
-client_request_agent(const char *request_type, int rchan)
+client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
{
Channel *c = NULL;
int r, sock;
@@ -1928,13 +1610,18 @@ client_request_agent(const char *request_type, int rchan)
"malicious server.");
return NULL;
}
- if ((r = ssh_get_authentication_socket(&sock)) != 0) {
+ if (forward_agent_sock_path == NULL) {
+ r = ssh_get_authentication_socket(&sock);
+ } else {
+ r = ssh_get_authentication_socket_path(forward_agent_sock_path, &sock);
+ }
+ if (r != 0) {
if (r != SSH_ERR_AGENT_NOT_PRESENT)
debug("%s: ssh_get_authentication_socket: %s",
__func__, ssh_err(r));
return NULL;
}
- c = channel_new("authentication agent connection",
+ c = channel_new(ssh, "authentication agent connection",
SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
"authentication agent connection", 1);
@@ -1942,133 +1629,151 @@ client_request_agent(const char *request_type, int rchan)
return c;
}
-int
-client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun)
+char *
+client_request_tun_fwd(struct ssh *ssh, int tun_mode,
+ int local_tun, int remote_tun, channel_open_fn *cb, void *cbctx)
{
Channel *c;
- int fd;
+ int r, fd;
+ char *ifname = NULL;
if (tun_mode == SSH_TUNMODE_NO)
return 0;
- if (!compat20) {
- error("Tunnel forwarding is not supported for protocol 1");
- return -1;
- }
-
debug("Requesting tun unit %d in mode %d", local_tun, tun_mode);
/* Open local tunnel device */
- if ((fd = tun_open(local_tun, tun_mode)) == -1) {
+ if ((fd = tun_open(local_tun, tun_mode, &ifname)) == -1) {
error("Tunnel device open failed.");
- return -1;
+ return NULL;
}
+ debug("Tunnel forwarding using interface %s", ifname);
- c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
+ c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
c->datagram = 1;
#if defined(SSH_TUN_FILTER)
if (options.tun_open == SSH_TUNMODE_POINTOPOINT)
- channel_register_filter(c->self, sys_tun_infilter,
+ channel_register_filter(ssh, c->self, sys_tun_infilter,
sys_tun_outfilter, NULL, NULL);
#endif
- packet_start(SSH2_MSG_CHANNEL_OPEN);
- packet_put_cstring("tun@openssh.com");
- packet_put_int(c->self);
- packet_put_int(c->local_window_max);
- packet_put_int(c->local_maxpacket);
- packet_put_int(tun_mode);
- packet_put_int(remote_tun);
- packet_send();
+ if (cb != NULL)
+ channel_register_open_confirm(ssh, c->self, cb, cbctx);
- return 0;
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "tun@openssh.com")) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_window_max)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 ||
+ (r = sshpkt_put_u32(ssh, tun_mode)) != 0 ||
+ (r = sshpkt_put_u32(ssh, remote_tun)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send reply", __func__);
+
+ return ifname;
}
/* XXXX move to generic input handler */
static int
-client_input_channel_open(int type, u_int32_t seq, void *ctxt)
+client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c = NULL;
- char *ctype;
- int rchan;
- u_int rmaxpack, rwindow, len;
-
- ctype = packet_get_string(&len);
- rchan = packet_get_int();
- rwindow = packet_get_int();
- rmaxpack = packet_get_int();
+ char *ctype = NULL;
+ int r;
+ u_int rchan;
+ size_t len;
+ u_int rmaxpack, rwindow;
+
+ if ((r = sshpkt_get_cstring(ssh, &ctype, &len)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &rchan)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &rwindow)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0)
+ goto out;
debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
ctype, rchan, rwindow, rmaxpack);
if (strcmp(ctype, "forwarded-tcpip") == 0) {
- c = client_request_forwarded_tcpip(ctype, rchan);
+ c = client_request_forwarded_tcpip(ssh, ctype, rchan, rwindow,
+ rmaxpack);
} else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) {
- c = client_request_forwarded_streamlocal(ctype, rchan);
+ c = client_request_forwarded_streamlocal(ssh, ctype, rchan);
} else if (strcmp(ctype, "x11") == 0) {
- c = client_request_x11(ctype, rchan);
+ c = client_request_x11(ssh, ctype, rchan);
} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
- c = client_request_agent(ctype, rchan);
+ c = client_request_agent(ssh, ctype, rchan);
}
-/* XXX duplicate : */
- if (c != NULL) {
+ if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) {
+ debug3("proxied to downstream: %s", ctype);
+ } else if (c != NULL) {
debug("confirm %s", ctype);
c->remote_id = rchan;
+ c->have_remote_id = 1;
c->remote_window = rwindow;
c->remote_maxpacket = rmaxpack;
if (c->type != SSH_CHANNEL_CONNECTING) {
- packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(c->remote_id);
- packet_put_int(c->self);
- packet_put_int(c->local_window);
- packet_put_int(c->local_maxpacket);
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send reply", __func__);
}
} else {
debug("failure %s", ctype);
- packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(rchan);
- packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
- if (!(datafellows & SSH_BUG_OPENFAILURE)) {
- packet_put_cstring("open failed");
- packet_put_cstring("");
- }
- packet_send();
- }
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 ||
+ (r = sshpkt_put_u32(ssh, rchan)) != 0 ||
+ (r = sshpkt_put_u32(ssh, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "open failed")) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send failure", __func__);
+ }
+ r = 0;
+ out:
free(ctype);
- return 0;
+ return r;
}
static int
-client_input_channel_req(int type, u_int32_t seq, void *ctxt)
+client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c = NULL;
- int exitval, id, reply, success = 0;
- char *rtype;
-
- id = packet_get_int();
- rtype = packet_get_string(NULL);
- reply = packet_get_char();
+ char *rtype = NULL;
+ u_char reply;
+ u_int id, exitval;
+ int r, success = 0;
+
+ if ((r = sshpkt_get_u32(ssh, &id)) != 0)
+ return r;
+ if (id <= INT_MAX)
+ c = channel_lookup(ssh, id);
+ if (channel_proxy_upstream(c, type, seq, ssh))
+ return 0;
+ if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
+ (r = sshpkt_get_u8(ssh, &reply)) != 0)
+ goto out;
- debug("client_input_channel_req: channel %d rtype %s reply %d",
+ debug("client_input_channel_req: channel %u rtype %s reply %d",
id, rtype, reply);
- if (id == -1) {
- error("client_input_channel_req: request for channel -1");
- } else if ((c = channel_lookup(id)) == NULL) {
+ if (c == NULL) {
error("client_input_channel_req: channel %d: "
"unknown channel", id);
} else if (strcmp(rtype, "eow@openssh.com") == 0) {
- packet_check_eom();
- chan_rcvd_eow(c);
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ goto out;
+ chan_rcvd_eow(ssh, c);
} else if (strcmp(rtype, "exit-status") == 0) {
- exitval = packet_get_int();
+ if ((r = sshpkt_get_u32(ssh, &exitval)) != 0)
+ goto out;
if (c->ctl_chan != -1) {
- mux_exit_message(c, exitval);
+ mux_exit_message(ssh, c, exitval);
success = 1;
- } else if (id == session_ident) {
+ } else if ((int)id == session_ident) {
/* Record exit value of local session */
success = 1;
exit_status = exitval;
@@ -2077,16 +1782,23 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt)
debug("%s: no sink for exit-status on channel %d",
__func__, id);
}
- packet_check_eom();
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ goto out;
}
if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) {
- packet_start(success ?
- SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
- packet_put_int(c->remote_id);
- packet_send();
- }
+ if (!c->have_remote_id)
+ fatal("%s: channel %d: no remote_id",
+ __func__, c->self);
+ if ((r = sshpkt_start(ssh, success ?
+ SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send failure", __func__);
+ }
+ r = 0;
+ out:
free(rtype);
- return 0;
+ return r;
}
struct hostkeys_update_ctx {
@@ -2101,9 +1813,7 @@ struct hostkeys_update_ctx {
*/
struct sshkey **keys;
int *keys_seen;
- size_t nkeys;
-
- size_t nnew;
+ size_t nkeys, nnew;
/*
* Keys that are in known_hosts, but were not present in the update
@@ -2140,8 +1850,7 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx)
size_t i;
struct sshkey **tmp;
- if (l->status != HKF_STATUS_MATCHED || l->key == NULL ||
- l->key->type == KEY_RSA1)
+ if (l->status != HKF_STATUS_MATCHED || l->key == NULL)
return 0;
/* Mark off keys we've already seen for this host */
@@ -2156,9 +1865,9 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx)
/* This line contained a key that not offered by the server */
debug3("%s: deprecated %s key at %s:%ld", __func__,
sshkey_ssh_name(l->key), l->path, l->linenum);
- if ((tmp = reallocarray(ctx->old_keys, ctx->nold + 1,
+ if ((tmp = recallocarray(ctx->old_keys, ctx->nold, ctx->nold + 1,
sizeof(*ctx->old_keys))) == NULL)
- fatal("%s: reallocarray failed nold = %zu",
+ fatal("%s: recallocarray failed nold = %zu",
__func__, ctx->nold);
ctx->old_keys = tmp;
ctx->old_keys[ctx->nold++] = l->key;
@@ -2168,13 +1877,22 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx)
}
static void
+hostkey_change_preamble(LogLevel loglevel)
+{
+ do_log2(loglevel, "The server has updated its host keys.");
+ do_log2(loglevel, "These changes were verified by the server's "
+ "existing trusted key.");
+}
+
+static void
update_known_hosts(struct hostkeys_update_ctx *ctx)
{
- int r, was_raw = 0;
- int loglevel = options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK ?
- SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE;
+ int r, was_raw = 0, first = 1;
+ int asking = options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK;
+ LogLevel loglevel = asking ? SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE;
char *fp, *response;
size_t i;
+ struct stat sb;
for (i = 0; i < ctx->nkeys; i++) {
if (ctx->keys_seen[i] != 2)
@@ -2182,16 +1900,22 @@ update_known_hosts(struct hostkeys_update_ctx *ctx)
if ((fp = sshkey_fingerprint(ctx->keys[i],
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint failed", __func__);
+ if (first && asking)
+ hostkey_change_preamble(loglevel);
do_log2(loglevel, "Learned new hostkey: %s %s",
sshkey_type(ctx->keys[i]), fp);
+ first = 0;
free(fp);
}
for (i = 0; i < ctx->nold; i++) {
if ((fp = sshkey_fingerprint(ctx->old_keys[i],
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint failed", __func__);
+ if (first && asking)
+ hostkey_change_preamble(loglevel);
do_log2(loglevel, "Deprecating obsolete hostkey: %s %s",
sshkey_type(ctx->old_keys[i]), fp);
+ first = 0;
free(fp);
}
if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) {
@@ -2221,29 +1945,47 @@ update_known_hosts(struct hostkeys_update_ctx *ctx)
if (was_raw)
enter_raw_mode(1);
}
-
+ if (options.update_hostkeys == 0)
+ return;
/*
* Now that all the keys are verified, we can go ahead and replace
* them in known_hosts (assuming SSH_UPDATE_HOSTKEYS_ASK didn't
* cancel the operation).
*/
- if (options.update_hostkeys != 0 &&
- (r = hostfile_replace_entries(options.user_hostfiles[0],
- ctx->host_str, ctx->ip_str, ctx->keys, ctx->nkeys,
- options.hash_known_hosts, 0,
- options.fingerprint_hash)) != 0)
- error("%s: hostfile_replace_entries failed: %s",
- __func__, ssh_err(r));
+ for (i = 0; i < options.num_user_hostfiles; i++) {
+ /*
+ * NB. keys are only added to hostfiles[0], for the rest we
+ * just delete the hostname entries.
+ */
+ if (stat(options.user_hostfiles[i], &sb) != 0) {
+ if (errno == ENOENT) {
+ debug("%s: known hosts file %s does not exist",
+ __func__, strerror(errno));
+ } else {
+ error("%s: known hosts file %s inaccessible",
+ __func__, strerror(errno));
+ }
+ continue;
+ }
+ if ((r = hostfile_replace_entries(options.user_hostfiles[i],
+ ctx->host_str, ctx->ip_str,
+ i == 0 ? ctx->keys : NULL, i == 0 ? ctx->nkeys : 0,
+ options.hash_known_hosts, 0,
+ options.fingerprint_hash)) != 0) {
+ error("%s: hostfile_replace_entries failed for %s: %s",
+ __func__, options.user_hostfiles[i], ssh_err(r));
+ }
+ }
}
static void
-client_global_hostkeys_private_confirm(int type, u_int32_t seq, void *_ctx)
+client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
+ u_int32_t seq, void *_ctx)
{
- struct ssh *ssh = active_state; /* XXX */
struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
size_t i, ndone;
struct sshbuf *signdata;
- int r;
+ int r, kexsigtype, use_kexsigtype;
const u_char *sig;
size_t siglen;
@@ -2255,6 +1997,9 @@ client_global_hostkeys_private_confirm(int type, u_int32_t seq, void *_ctx)
hostkeys_update_ctx_free(ctx);
return;
}
+ kexsigtype = sshkey_type_plain(
+ sshkey_type_from_name(ssh->kex->hostkey_alg));
+
if ((signdata = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
/* Don't want to accidentally accept an unbound signature */
@@ -2283,8 +2028,16 @@ client_global_hostkeys_private_confirm(int type, u_int32_t seq, void *_ctx)
__func__, ssh_err(r));
goto out;
}
+ /*
+ * For RSA keys, prefer to use the signature type negotiated
+ * during KEX to the default (SHA1).
+ */
+ use_kexsigtype = kexsigtype == KEY_RSA &&
+ sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA;
if ((r = sshkey_verify(ctx->keys[i], sig, siglen,
- sshbuf_ptr(signdata), sshbuf_len(signdata), 0)) != 0) {
+ 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);
goto out;
@@ -2296,7 +2049,10 @@ client_global_hostkeys_private_confirm(int type, u_int32_t seq, void *_ctx)
if (ndone != ctx->nnew)
fatal("%s: ndone != ctx->nnew (%zu / %zu)", __func__,
ndone, ctx->nnew); /* Shouldn't happen */
- ssh_packet_check_eom(ssh);
+ if ((r = sshpkt_get_end(ssh)) != 0) {
+ error("%s: protocol error", __func__);
+ goto out;
+ }
/* Make the edits to known_hosts */
update_known_hosts(ctx);
@@ -2305,14 +2061,32 @@ client_global_hostkeys_private_confirm(int type, u_int32_t seq, void *_ctx)
}
/*
+ * Returns non-zero if the key is accepted by HostkeyAlgorithms.
+ * Made slightly less trivial by the multiple RSA signature algorithm names.
+ */
+static int
+key_accepted_by_hostkeyalgs(const struct sshkey *key)
+{
+ const char *ktype = sshkey_ssh_name(key);
+ const char *hostkeyalgs = options.hostkeyalgorithms;
+
+ if (key == NULL || key->type == KEY_UNSPEC)
+ return 0;
+ if (key->type == KEY_RSA &&
+ (match_pattern_list("rsa-sha2-256", hostkeyalgs, 0) == 1 ||
+ match_pattern_list("rsa-sha2-512", hostkeyalgs, 0) == 1))
+ return 1;
+ return match_pattern_list(ktype, hostkeyalgs, 0) == 1;
+}
+
+/*
* Handle hostkeys-00@openssh.com global request to inform the client of all
* the server's hostkeys. The keys are checked against the user's
* HostkeyAlgorithms preference before they are accepted.
*/
static int
-client_input_hostkeys(void)
+client_input_hostkeys(struct ssh *ssh)
{
- struct ssh *ssh = active_state; /* XXX */
const u_char *blob = NULL;
size_t i, len = 0;
struct sshbuf *buf = NULL;
@@ -2341,19 +2115,18 @@ client_input_hostkeys(void)
goto out;
}
if ((r = sshkey_from_blob(blob, len, &key)) != 0) {
- error("%s: parse key: %s", __func__, ssh_err(r));
- goto out;
+ do_log2(r == SSH_ERR_KEY_TYPE_UNKNOWN ?
+ SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_ERROR,
+ "%s: parse key: %s", __func__, ssh_err(r));
+ continue;
}
fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
debug3("%s: received %s key %s", __func__,
sshkey_type(key), fp);
free(fp);
- /* Check that the key is accepted in HostkeyAlgorithms */
- if (options.hostkeyalgorithms != NULL &&
- match_pattern_list(sshkey_ssh_name(key),
- options.hostkeyalgorithms,
- strlen(options.hostkeyalgorithms), 0) != 1) {
+
+ if (!key_accepted_by_hostkeyalgs(key)) {
debug3("%s: %s key not permitted by HostkeyAlgorithms",
__func__, sshkey_ssh_name(key));
continue;
@@ -2373,9 +2146,9 @@ client_input_hostkeys(void)
}
}
/* Key is good, record it */
- if ((tmp = reallocarray(ctx->keys, ctx->nkeys + 1,
+ if ((tmp = recallocarray(ctx->keys, ctx->nkeys, ctx->nkeys + 1,
sizeof(*ctx->keys))) == NULL)
- fatal("%s: reallocarray failed nkeys = %zu",
+ fatal("%s: recallocarray failed nkeys = %zu",
__func__, ctx->nkeys);
ctx->keys = tmp;
ctx->keys[ctx->nkeys++] = key;
@@ -2397,11 +2170,22 @@ client_input_hostkeys(void)
options.check_host_ip ? &ctx->ip_str : NULL);
/* Find which keys we already know about. */
- if ((r = hostkeys_foreach(options.user_hostfiles[0], hostkeys_find,
- ctx, ctx->host_str, ctx->ip_str,
- HKF_WANT_PARSE_KEY|HKF_WANT_MATCH)) != 0) {
- error("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
- goto out;
+ for (i = 0; i < options.num_user_hostfiles; i++) {
+ debug("%s: searching %s for %s / %s", __func__,
+ 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) {
+ if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) {
+ debug("%s: hostkeys file %s does not exist",
+ __func__, options.user_hostfiles[i]);
+ continue;
+ }
+ error("%s: hostkeys_foreach failed for %s: %s",
+ __func__, options.user_hostfiles[i], ssh_err(r));
+ goto out;
+ }
}
/* Figure out if we have any new keys to add */
@@ -2463,70 +2247,76 @@ client_input_hostkeys(void)
}
static int
-client_input_global_request(int type, u_int32_t seq, void *ctxt)
+client_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
{
char *rtype;
- int want_reply;
- int success = 0;
+ u_char want_reply;
+ int r, success = 0;
- rtype = packet_get_cstring(NULL);
- want_reply = packet_get_char();
+ if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
+ (r = sshpkt_get_u8(ssh, &want_reply)) != 0)
+ goto out;
debug("client_input_global_request: rtype %s want_reply %d",
rtype, want_reply);
if (strcmp(rtype, "hostkeys-00@openssh.com") == 0)
- success = client_input_hostkeys();
+ success = client_input_hostkeys(ssh);
if (want_reply) {
- packet_start(success ?
- SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
- packet_send();
- packet_write_wait();
+ if ((r = sshpkt_start(ssh, success ? SSH2_MSG_REQUEST_SUCCESS :
+ SSH2_MSG_REQUEST_FAILURE)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ goto out;
}
+ r = 0;
+ out:
free(rtype);
- return 0;
+ return r;
}
void
-client_session2_setup(int id, int want_tty, int want_subsystem,
- const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env)
+client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
+ const char *term, struct termios *tiop, int in_fd, struct sshbuf *cmd,
+ char **env)
{
- int len;
+ int i, j, matched, len, r;
+ char *name, *val;
Channel *c = NULL;
debug2("%s: id %d", __func__, id);
- if ((c = channel_lookup(id)) == NULL)
- fatal("client_session2_setup: channel %d: unknown channel", id);
+ if ((c = channel_lookup(ssh, id)) == NULL)
+ fatal("%s: channel %d: unknown channel", __func__, id);
- packet_set_interactive(want_tty,
+ ssh_packet_set_interactive(ssh, want_tty,
options.ip_qos_interactive, options.ip_qos_bulk);
if (want_tty) {
struct winsize ws;
/* Store window size in the packet. */
- if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
+ if (ioctl(in_fd, TIOCGWINSZ, &ws) == -1)
memset(&ws, 0, sizeof(ws));
- channel_request_start(id, "pty-req", 1);
- client_expect_confirm(id, "PTY allocation", CONFIRM_TTY);
- packet_put_cstring(term != NULL ? term : "");
- packet_put_int((u_int)ws.ws_col);
- packet_put_int((u_int)ws.ws_row);
- packet_put_int((u_int)ws.ws_xpixel);
- packet_put_int((u_int)ws.ws_ypixel);
+ channel_request_start(ssh, id, "pty-req", 1);
+ client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY);
+ if ((r = sshpkt_put_cstring(ssh, term != NULL ? term : ""))
+ != 0 ||
+ (r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 ||
+ (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 ||
+ (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 ||
+ (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0)
+ fatal("%s: build packet: %s", __func__, ssh_err(r));
if (tiop == NULL)
tiop = get_saved_tio();
- tty_make_modes(-1, tiop);
- packet_send();
+ ssh_tty_make_modes(ssh, -1, tiop);
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: send packet: %s", __func__, ssh_err(r));
/* XXX wait for reply */
c->client_tty = 1;
}
/* Transfer any environment variables from client to server */
if (options.num_send_env != 0 && env != NULL) {
- int i, j, matched;
- char *name, *val;
-
debug("Sending environment.");
for (i = 0; env[i] != NULL; i++) {
/* Split */
@@ -2551,101 +2341,87 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
}
debug("Sending env %s = %s", name, val);
- channel_request_start(id, "env", 0);
- packet_put_cstring(name);
- packet_put_cstring(val);
- packet_send();
+ 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));
+ }
free(name);
}
}
+ for (i = 0; i < options.num_setenv; i++) {
+ /* Split */
+ name = xstrdup(options.setenv[i]);
+ if ((val = strchr(name, '=')) == NULL) {
+ free(name);
+ continue;
+ }
+ *val++ = '\0';
- len = buffer_len(cmd);
+ 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));
+ free(name);
+ }
+
+ len = sshbuf_len(cmd);
if (len > 0) {
if (len > 900)
len = 900;
if (want_subsystem) {
debug("Sending subsystem: %.*s",
- len, (u_char*)buffer_ptr(cmd));
- channel_request_start(id, "subsystem", 1);
- client_expect_confirm(id, "subsystem", CONFIRM_CLOSE);
+ len, (const u_char*)sshbuf_ptr(cmd));
+ channel_request_start(ssh, id, "subsystem", 1);
+ client_expect_confirm(ssh, id, "subsystem",
+ CONFIRM_CLOSE);
} else {
debug("Sending command: %.*s",
- len, (u_char*)buffer_ptr(cmd));
- channel_request_start(id, "exec", 1);
- client_expect_confirm(id, "exec", CONFIRM_CLOSE);
+ len, (const u_char*)sshbuf_ptr(cmd));
+ channel_request_start(ssh, id, "exec", 1);
+ client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE);
}
- packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
- packet_send();
+ if ((r = sshpkt_put_stringb(ssh, cmd)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: send command: %s", __func__, ssh_err(r));
} else {
- channel_request_start(id, "shell", 1);
- client_expect_confirm(id, "shell", CONFIRM_CLOSE);
- packet_send();
+ 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));
+ }
}
}
static void
-client_init_dispatch_20(void)
+client_init_dispatch(struct ssh *ssh)
{
- dispatch_init(&dispatch_protocol_error);
-
- dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
- dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
- dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
- dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
- dispatch_set(SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open);
- dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
- dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
- dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
- dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
- dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm);
- dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm);
- dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
+ ssh_dispatch_init(ssh, &dispatch_protocol_error);
+
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_DATA, &channel_input_data);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm);
+ ssh_dispatch_set(ssh, SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
/* rekeying */
- dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
/* global request reply messages */
- dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
- dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
-}
-
-static void
-client_init_dispatch_13(void)
-{
- dispatch_init(NULL);
- dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
- dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
- dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
- dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
- dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
- dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
- dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
- dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
- dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
-
- dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
- &client_input_agent_open : &deny_input_open);
- dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
- &x11_input_open : &deny_input_open);
-}
-
-static void
-client_init_dispatch_15(void)
-{
- client_init_dispatch_13();
- dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
- dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
-}
-
-static void
-client_init_dispatch(void)
-{
- if (compat20)
- client_init_dispatch_20();
- else if (compat13)
- client_init_dispatch_13();
- else
- client_init_dispatch_15();
+ ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
+ ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
}
void
@@ -2668,7 +2444,6 @@ void
cleanup_exit(int i)
{
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
- leave_non_blocking();
if (options.control_path != NULL && muxserver_sock != -1)
unlink(options.control_path);
ssh_kill_proxy_command();
diff --git a/clientloop.h b/clientloop.h
index 338d4518..31630551 100644
--- a/clientloop.h
+++ b/clientloop.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.h,v 1.31 2013/06/02 23:36:29 dtucker Exp $ */
+/* $OpenBSD: clientloop.h,v 1.37 2020/04/03 02:40:32 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -37,28 +37,32 @@
#include <termios.h>
+struct ssh;
+
/* Client side main loop for the interactive session. */
-int client_loop(int, int, int);
-void client_x11_get_proto(const char *, const char *, u_int, u_int,
- char **, char **);
+int client_loop(struct ssh *, int, int, int);
+int client_x11_get_proto(struct ssh *, const char *, const char *,
+ u_int, u_int, char **, char **);
void client_global_request_reply_fwd(int, u_int32_t, void *);
-void client_session2_setup(int, int, int, const char *, struct termios *,
- int, Buffer *, char **);
-int client_request_tun_fwd(int, int, int);
+void client_session2_setup(struct ssh *, int, int, int,
+ const char *, struct termios *, int, struct sshbuf *, char **);
+char *client_request_tun_fwd(struct ssh *, int, int, int,
+ channel_open_fn *, void *);
void client_stop_mux(void);
/* Escape filter for protocol 2 sessions */
void *client_new_escape_filter_ctx(int);
-void client_filter_cleanup(int, void *);
-int client_simple_escape_filter(Channel *, char *, int);
+void client_filter_cleanup(struct ssh *, int, void *);
+int client_simple_escape_filter(struct ssh *, Channel *, char *, int);
/* Global request confirmation callbacks */
-typedef void global_confirm_cb(int, u_int32_t seq, void *);
+typedef void global_confirm_cb(struct ssh *, int, u_int32_t, void *);
void client_register_global_confirm(global_confirm_cb *, void *);
/* Channel request confirmation callbacks */
enum confirm_action { CONFIRM_WARN = 0, CONFIRM_CLOSE, CONFIRM_TTY };
-void client_expect_confirm(int, const char *, enum confirm_action);
+void client_expect_confirm(struct ssh *, int, const char *,
+ enum confirm_action);
/* Multiplexing protocol version */
#define SSHMUX_VER 4
@@ -71,9 +75,10 @@ void client_expect_confirm(int, const char *, enum confirm_action);
#define SSHMUX_COMMAND_FORWARD 5 /* Forward only, no command */
#define SSHMUX_COMMAND_STOP 6 /* Disable mux but not conn */
#define SSHMUX_COMMAND_CANCEL_FWD 7 /* Cancel forwarding(s) */
+#define SSHMUX_COMMAND_PROXY 8 /* Open new connection */
-void muxserver_listen(void);
-void muxclient(const char *);
-void mux_exit_message(Channel *, int);
-void mux_tty_alloc_failed(Channel *);
+void muxserver_listen(struct ssh *);
+int muxclient(const char *);
+void mux_exit_message(struct ssh *, Channel *, int);
+void mux_tty_alloc_failed(struct ssh *ssh, Channel *);
diff --git a/compat.c b/compat.c
index 4852fb70..0624dc6d 100644
--- a/compat.c
+++ b/compat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat.c,v 1.87 2015/01/19 20:20:20 markus Exp $ */
+/* $OpenBSD: compat.c,v 1.113 2018/08/13 02:41:05 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
@@ -32,30 +32,14 @@
#include <stdarg.h>
#include "xmalloc.h"
-#include "buffer.h"
#include "packet.h"
#include "compat.h"
#include "log.h"
#include "match.h"
+#include "kex.h"
-int compat13 = 0;
-int compat20 = 0;
int datafellows = 0;
-void
-enable_compat20(void)
-{
- if (compat20)
- return;
- debug("Enabling compatibility mode for protocol 2.0");
- compat20 = 1;
-}
-void
-enable_compat13(void)
-{
- debug("Enabling compatibility mode for protocol 1.3");
- compat13 = 1;
-}
/* datafellows bug compatibility */
u_int
compat_datafellows(const char *version)
@@ -65,83 +49,32 @@ compat_datafellows(const char *version)
char *pat;
int bugs;
} check[] = {
- { "OpenSSH-2.0*,"
- "OpenSSH-2.1*,"
- "OpenSSH_2.1*,"
- "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER|
- SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
- SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES|
- SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
- SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
- SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
- SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_2.5.0p1*,"
- "OpenSSH_2.5.1p1*",
- SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
- SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
- SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_2.5.0*,"
- "OpenSSH_2.5.1*,"
- "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
- SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
- SSH_OLD_FORWARD_ADDR},
{ "OpenSSH_2.*,"
"OpenSSH_3.0*,"
- "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR },
- { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
- { "OpenSSH_4*", 0 },
- { "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT},
- { "OpenSSH_6.6.1*", SSH_NEW_OPENSSH},
+ "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR|
+ SSH_BUG_SIGTYPE},
+ { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR|SSH_BUG_SIGTYPE },
+ { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
+ SSH_BUG_SIGTYPE},
+ { "OpenSSH_2*,"
+ "OpenSSH_3*,"
+ "OpenSSH_4*", SSH_BUG_SIGTYPE },
+ { "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT|
+ SSH_BUG_SIGTYPE},
+ { "OpenSSH_6.6.1*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE},
{ "OpenSSH_6.5*,"
- "OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD},
+ "OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD|
+ SSH_BUG_SIGTYPE},
+ { "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},
{ "OpenSSH*", SSH_NEW_OPENSSH },
{ "*MindTerm*", 0 },
- { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
- SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
- SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE|
- SSH_BUG_FIRSTKEX },
- { "2.1 *", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
- SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
- SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE|
- SSH_BUG_FIRSTKEX },
- { "2.0.13*,"
- "2.0.14*,"
- "2.0.15*,"
- "2.0.16*,"
- "2.0.17*,"
- "2.0.18*,"
- "2.0.19*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
- SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
- SSH_BUG_PKSERVICE|SSH_BUG_X11FWD|
- SSH_BUG_PKOK|SSH_BUG_RSASIGMD5|
- SSH_BUG_HBSERVICE|SSH_BUG_OPENFAILURE|
- SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX },
- { "2.0.11*,"
- "2.0.12*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
- SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
- SSH_BUG_PKSERVICE|SSH_BUG_X11FWD|
- SSH_BUG_PKAUTH|SSH_BUG_PKOK|
- SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE|
- SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX },
- { "2.0.*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
- SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
- SSH_BUG_PKSERVICE|SSH_BUG_X11FWD|
- SSH_BUG_PKAUTH|SSH_BUG_PKOK|
- SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE|
- SSH_BUG_DERIVEKEY|SSH_BUG_DUMMYCHAN|
- SSH_BUG_FIRSTKEX },
- { "2.2.0*,"
- "2.3.0*", SSH_BUG_HMAC|SSH_BUG_DEBUG|
- SSH_BUG_RSASIGMD5|SSH_BUG_FIRSTKEX },
- { "2.3.*", SSH_BUG_DEBUG|SSH_BUG_RSASIGMD5|
- SSH_BUG_FIRSTKEX },
- { "2.4", SSH_OLD_SESSIONID }, /* Van Dyke */
- { "2.*", SSH_BUG_DEBUG|SSH_BUG_FIRSTKEX|
- SSH_BUG_RFWD_ADDR },
{ "3.0.*", SSH_BUG_DEBUG },
{ "3.0 SecureCRT*", SSH_OLD_SESSIONID },
{ "1.7 SecureFX*", SSH_OLD_SESSIONID },
@@ -152,6 +85,8 @@ compat_datafellows(const char *version)
"1.2.22*", SSH_BUG_IGNOREMSG },
{ "1.3.2*", /* F-Secure */
SSH_BUG_IGNOREMSG },
+ { "Cisco-1.*", SSH_BUG_DHGEX_LARGE|
+ SSH_BUG_HOSTKEYS },
{ "*SSH Compatible Server*", /* Netscreen */
SSH_BUG_PASSWORDPAD },
{ "*OSU_0*,"
@@ -165,15 +100,53 @@ compat_datafellows(const char *version)
"OSU_1.5alpha3*", SSH_BUG_PASSWORDPAD },
{ "*SSH_Version_Mapper*",
SSH_BUG_SCANNER },
+ { "PuTTY_Local:*," /* dev versions < Sep 2014 */
+ "PuTTY-Release-0.5*," /* 0.50-0.57, DH-GEX in >=0.52 */
+ "PuTTY_Release_0.5*," /* 0.58-0.59 */
+ "PuTTY_Release_0.60*,"
+ "PuTTY_Release_0.61*,"
+ "PuTTY_Release_0.62*,"
+ "PuTTY_Release_0.63*,"
+ "PuTTY_Release_0.64*",
+ SSH_OLD_DHGEX },
+ { "FuTTY*", SSH_OLD_DHGEX }, /* Putty Fork */
{ "Probe-*",
SSH_BUG_PROBE },
+ { "TeraTerm SSH*,"
+ "TTSSH/1.5.*,"
+ "TTSSH/2.1*,"
+ "TTSSH/2.2*,"
+ "TTSSH/2.3*,"
+ "TTSSH/2.4*,"
+ "TTSSH/2.5*,"
+ "TTSSH/2.6*,"
+ "TTSSH/2.70*,"
+ "TTSSH/2.71*,"
+ "TTSSH/2.72*", SSH_BUG_HOSTKEYS },
+ { "WinSCP_release_4*,"
+ "WinSCP_release_5.0*,"
+ "WinSCP_release_5.1,"
+ "WinSCP_release_5.1.*,"
+ "WinSCP_release_5.5,"
+ "WinSCP_release_5.5.*,"
+ "WinSCP_release_5.6,"
+ "WinSCP_release_5.6.*,"
+ "WinSCP_release_5.7,"
+ "WinSCP_release_5.7.1,"
+ "WinSCP_release_5.7.2,"
+ "WinSCP_release_5.7.3,"
+ "WinSCP_release_5.7.4",
+ SSH_OLD_DHGEX },
+ { "ConfD-*",
+ SSH_BUG_UTF8TTYMODE },
+ { "Twisted_*", 0 },
+ { "Twisted*", SSH_BUG_DEBUG },
{ NULL, 0 }
};
/* process table, return first match */
for (i = 0; check[i].pat; i++) {
- if (match_pattern_list(version, check[i].pat,
- strlen(check[i].pat), 0) == 1) {
+ if (match_pattern_list(version, check[i].pat, 0) == 1) {
debug("match: %s pat %s compat 0x%08x",
version, check[i].pat, check[i].bugs);
datafellows = check[i].bugs; /* XXX for now */
@@ -198,11 +171,6 @@ proto_spec(const char *spec)
return ret;
for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) {
switch (atoi(p)) {
- case 1:
- if (ret == SSH_PROTO_UNKNOWN)
- ret |= SSH_PROTO_1_PREFERRED;
- ret |= SSH_PROTO_1;
- break;
case 2:
ret |= SSH_PROTO_2;
break;
@@ -215,42 +183,14 @@ proto_spec(const char *spec)
return ret;
}
-/*
- * Filters a proposal string, excluding any algorithm matching the 'filter'
- * pattern list.
- */
-static char *
-filter_proposal(char *proposal, const char *filter)
-{
- Buffer b;
- char *orig_prop, *fix_prop;
- char *cp, *tmp;
-
- buffer_init(&b);
- tmp = orig_prop = xstrdup(proposal);
- while ((cp = strsep(&tmp, ",")) != NULL) {
- if (match_pattern_list(cp, filter, strlen(cp), 0) != 1) {
- if (buffer_len(&b) > 0)
- buffer_append(&b, ",", 1);
- buffer_append(&b, cp, strlen(cp));
- } else
- debug2("Compat: skipping algorithm \"%s\"", cp);
- }
- buffer_append(&b, "\0", 1);
- fix_prop = xstrdup((char *)buffer_ptr(&b));
- buffer_free(&b);
- free(orig_prop);
-
- return fix_prop;
-}
-
char *
compat_cipher_proposal(char *cipher_prop)
{
if (!(datafellows & SSH_BUG_BIGENDIANAES))
return cipher_prop;
debug2("%s: original cipher proposal: %s", __func__, cipher_prop);
- cipher_prop = filter_proposal(cipher_prop, "aes*");
+ if ((cipher_prop = match_filter_blacklist(cipher_prop, "aes*")) == NULL)
+ fatal("match_filter_blacklist failed");
debug2("%s: compat cipher proposal: %s", __func__, cipher_prop);
if (*cipher_prop == '\0')
fatal("No supported ciphers found");
@@ -263,7 +203,8 @@ compat_pkalg_proposal(char *pkalg_prop)
if (!(datafellows & SSH_BUG_RSASIGMD5))
return pkalg_prop;
debug2("%s: original public key proposal: %s", __func__, pkalg_prop);
- pkalg_prop = filter_proposal(pkalg_prop, "ssh-rsa");
+ 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);
if (*pkalg_prop == '\0')
fatal("No supported PK algorithms found");
@@ -271,15 +212,24 @@ compat_pkalg_proposal(char *pkalg_prop)
}
char *
-compat_kex_proposal(char *kex_prop)
+compat_kex_proposal(char *p)
{
- if (!(datafellows & SSH_BUG_CURVE25519PAD))
- return kex_prop;
- debug2("%s: original KEX proposal: %s", __func__, kex_prop);
- kex_prop = filter_proposal(kex_prop, "curve25519-sha256@libssh.org");
- debug2("%s: compat KEX proposal: %s", __func__, kex_prop);
- if (*kex_prop == '\0')
+ if ((datafellows & (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,
+ "curve25519-sha256@libssh.org")) == NULL)
+ fatal("match_filter_blacklist failed");
+ if ((datafellows & SSH_OLD_DHGEX) != 0) {
+ if ((p = match_filter_blacklist(p,
+ "diffie-hellman-group-exchange-sha256,"
+ "diffie-hellman-group-exchange-sha1")) == NULL)
+ fatal("match_filter_blacklist failed");
+ }
+ debug2("%s: compat KEX proposal: %s", __func__, p);
+ if (*p == '\0')
fatal("No supported key exchange algorithms found");
- return kex_prop;
+ return p;
}
diff --git a/compat.h b/compat.h
index af2f0073..d611d33e 100644
--- a/compat.h
+++ b/compat.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat.h,v 1.46 2015/01/19 20:20:20 markus Exp $ */
+/* $OpenBSD: compat.h,v 1.54 2018/08/13 02:41:05 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
@@ -32,44 +32,42 @@
#define SSH_PROTO_1_PREFERRED 0x02
#define SSH_PROTO_2 0x04
-#define SSH_BUG_SIGBLOB 0x00000001
-#define SSH_BUG_PKSERVICE 0x00000002
-#define SSH_BUG_HMAC 0x00000004
-#define SSH_BUG_X11FWD 0x00000008
+#define SSH_BUG_UTF8TTYMODE 0x00000001
+#define SSH_BUG_SIGTYPE 0x00000002
+/* #define unused 0x00000004 */
+/* #define unused 0x00000008 */
#define SSH_OLD_SESSIONID 0x00000010
-#define SSH_BUG_PKAUTH 0x00000020
+/* #define unused 0x00000020 */
#define SSH_BUG_DEBUG 0x00000040
-#define SSH_BUG_BANNER 0x00000080
+/* #define unused 0x00000080 */
#define SSH_BUG_IGNOREMSG 0x00000100
-#define SSH_BUG_PKOK 0x00000200
+/* #define unused 0x00000200 */
#define SSH_BUG_PASSWORDPAD 0x00000400
#define SSH_BUG_SCANNER 0x00000800
#define SSH_BUG_BIGENDIANAES 0x00001000
#define SSH_BUG_RSASIGMD5 0x00002000
#define SSH_OLD_DHGEX 0x00004000
#define SSH_BUG_NOREKEY 0x00008000
-#define SSH_BUG_HBSERVICE 0x00010000
-#define SSH_BUG_OPENFAILURE 0x00020000
-#define SSH_BUG_DERIVEKEY 0x00040000
-#define SSH_BUG_DUMMYCHAN 0x00100000
+/* #define unused 0x00010000 */
+/* #define unused 0x00020000 */
+/* #define unused 0x00040000 */
+/* #define unused 0x00100000 */
#define SSH_BUG_EXTEOF 0x00200000
#define SSH_BUG_PROBE 0x00400000
-#define SSH_BUG_FIRSTKEX 0x00800000
+/* #define unused 0x00800000 */
#define SSH_OLD_FORWARD_ADDR 0x01000000
-#define SSH_BUG_RFWD_ADDR 0x02000000
+/* #define unused 0x02000000 */
#define SSH_NEW_OPENSSH 0x04000000
#define SSH_BUG_DYNAMIC_RPORT 0x08000000
#define SSH_BUG_CURVE25519PAD 0x10000000
+#define SSH_BUG_HOSTKEYS 0x20000000
+#define SSH_BUG_DHGEX_LARGE 0x40000000
-void enable_compat13(void);
-void enable_compat20(void);
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 *);
-extern int compat13;
-extern int compat20;
extern int datafellows;
#endif
diff --git a/config.guess b/config.guess
index b94cde8e..11fda528 100755
--- a/config.guess
+++ b/config.guess
@@ -1,14 +1,12 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012, 2013 Free Software Foundation, Inc.
+# Copyright 1992-2020 Free Software Foundation, Inc.
-timestamp='2012-12-23'
+timestamp='2020-04-26'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
@@ -17,24 +15,22 @@ timestamp='2012-12-23'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Originally written by Per Bothner. Please send patches (context
-# diff format) to <config-patches@gnu.org> and include a ChangeLog
-# entry.
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
#
-# This script attempts to guess a canonical system name similar to
-# config.sub. If it succeeds, it prints the system name on stdout, and
-# exits with 0. Otherwise, it exits with 1.
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
me=`echo "$0" | sed -e 's,.*/,,'`
@@ -43,7 +39,7 @@ Usage: $0 [OPTION]
Output the configuration name of the system \`$me' is run on.
-Operation modes:
+Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
@@ -54,9 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
-2012, 2013 Free Software Foundation, Inc.
+Copyright 1992-2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -90,8 +84,6 @@ if test $# != 0; then
exit 1
fi
-trap 'exit 1' 1 2 15
-
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
@@ -102,34 +94,40 @@ trap 'exit 1' 1 2 15
# Portable tmp directory creation inspired by the Autoconf team.
-set_cc_for_build='
-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
-: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
-dummy=$tmp/dummy ;
-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,) echo "int x;" > $dummy.c ;
- for c in cc gcc c89 c99 ; do
- if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$c"; break ;
- fi ;
- done ;
- if test x"$CC_FOR_BUILD" = x ; then
- CC_FOR_BUILD=no_compiler_found ;
- fi
- ;;
- ,,*) CC_FOR_BUILD=$CC ;;
- ,*,*) CC_FOR_BUILD=$HOST_CC ;;
-esac ; set_cc_for_build= ;'
+tmp=
+# shellcheck disable=SC2172
+trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
+
+set_cc_for_build() {
+ # prevent multiple calls if $tmp is already set
+ test "$tmp" && return 0
+ : "${TMPDIR=/tmp}"
+ # shellcheck disable=SC2039
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
+ dummy=$tmp/dummy
+ case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
+ ,,) echo "int x;" > "$dummy.c"
+ for driver in cc gcc c89 c99 ; do
+ if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$driver"
+ break
+ fi
+ done
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+ esac
+}
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+if test -f /.attbin/uname ; then
PATH=$PATH:/.attbin ; export PATH
fi
@@ -138,9 +136,37 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+case "$UNAME_SYSTEM" in
+Linux|GNU|GNU/*)
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ LIBC=gnu
+
+ set_cc_for_build
+ cat <<-EOF > "$dummy.c"
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #else
+ LIBC=gnu
+ #endif
+ EOF
+ eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
+
+ # If ldd exists, use it to detect musl libc.
+ if command -v ldd >/dev/null && \
+ ldd --version 2>&1 | grep -q ^musl
+ then
+ LIBC=musl
+ fi
+ ;;
+esac
+
# Note: order is significant - the case branches are not exclusive.
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
@@ -153,21 +179,31 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
sysctl="sysctl -n hw.machine_arch"
- UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
- /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
- case "${UNAME_MACHINE_ARCH}" in
+ UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+ "/sbin/$sysctl" 2>/dev/null || \
+ "/usr/sbin/$sysctl" 2>/dev/null || \
+ echo unknown)`
+ case "$UNAME_MACHINE_ARCH" in
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
- *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ earmv*)
+ arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine="${arch}${endian}"-unknown
+ ;;
+ *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
esac
# The Operating System including object format, if it has switched
- # to ELF recently, or will in the future.
- case "${UNAME_MACHINE_ARCH}" in
+ # to ELF recently (or will in the future) and ABI.
+ case "$UNAME_MACHINE_ARCH" in
+ earm*)
+ os=netbsdelf
+ ;;
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
- eval $set_cc_for_build
+ set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
then
@@ -182,43 +218,72 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
os=netbsd
;;
esac
+ # Determine ABI tags.
+ case "$UNAME_MACHINE_ARCH" in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
+ ;;
+ esac
# The OS release
# Debian GNU/NetBSD machines have a different userland, and
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
- case "${UNAME_VERSION}" in
+ case "$UNAME_VERSION" in
Debian*)
release='-gnu'
;;
*)
- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}${release}"
+ echo "$machine-${os}${release}${abi-}"
exit ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+ echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
+ exit ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
+ exit ;;
+ *:MidnightBSD:*:*)
+ echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
exit ;;
*:ekkoBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
exit ;;
*:SolidBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
+ exit ;;
+ *:OS108:*:*)
+ echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE"
exit ;;
macppc:MirBSD:*:*)
- echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
exit ;;
*:MirBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
+ exit ;;
+ *:Sortix:*:*)
+ echo "$UNAME_MACHINE"-unknown-sortix
+ exit ;;
+ *:Twizzler:*:*)
+ echo "$UNAME_MACHINE"-unknown-twizzler
+ exit ;;
+ *:Redox:*:*)
+ echo "$UNAME_MACHINE"-unknown-redox
+ exit ;;
+ mips:OSF1:*.*)
+ echo mips-dec-osf1
exit ;;
alpha:OSF1:*:*)
case $UNAME_RELEASE in
@@ -236,63 +301,54 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
case "$ALPHA_CPU_TYPE" in
"EV4 (21064)")
- UNAME_MACHINE="alpha" ;;
+ UNAME_MACHINE=alpha ;;
"EV4.5 (21064)")
- UNAME_MACHINE="alpha" ;;
+ UNAME_MACHINE=alpha ;;
"LCA4 (21066/21068)")
- UNAME_MACHINE="alpha" ;;
+ UNAME_MACHINE=alpha ;;
"EV5 (21164)")
- UNAME_MACHINE="alphaev5" ;;
+ UNAME_MACHINE=alphaev5 ;;
"EV5.6 (21164A)")
- UNAME_MACHINE="alphaev56" ;;
+ UNAME_MACHINE=alphaev56 ;;
"EV5.6 (21164PC)")
- UNAME_MACHINE="alphapca56" ;;
+ UNAME_MACHINE=alphapca56 ;;
"EV5.7 (21164PC)")
- UNAME_MACHINE="alphapca57" ;;
+ UNAME_MACHINE=alphapca57 ;;
"EV6 (21264)")
- UNAME_MACHINE="alphaev6" ;;
+ UNAME_MACHINE=alphaev6 ;;
"EV6.7 (21264A)")
- UNAME_MACHINE="alphaev67" ;;
+ UNAME_MACHINE=alphaev67 ;;
"EV6.8CB (21264C)")
- UNAME_MACHINE="alphaev68" ;;
+ UNAME_MACHINE=alphaev68 ;;
"EV6.8AL (21264B)")
- UNAME_MACHINE="alphaev68" ;;
+ UNAME_MACHINE=alphaev68 ;;
"EV6.8CX (21264D)")
- UNAME_MACHINE="alphaev68" ;;
+ UNAME_MACHINE=alphaev68 ;;
"EV6.9A (21264/EV69A)")
- UNAME_MACHINE="alphaev69" ;;
+ UNAME_MACHINE=alphaev69 ;;
"EV7 (21364)")
- UNAME_MACHINE="alphaev7" ;;
+ UNAME_MACHINE=alphaev7 ;;
"EV7.9 (21364A)")
- UNAME_MACHINE="alphaev79" ;;
+ UNAME_MACHINE=alphaev79 ;;
esac
# A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$?
trap '' 0
exit $exitcode ;;
- Alpha\ *:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # Should we change UNAME_MACHINE based on the output of uname instead
- # of the specific Alpha model?
- echo alpha-pc-interix
- exit ;;
- 21064:Windows_NT:50:3)
- echo alpha-dec-winnt3.5
- exit ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-unknown-sysv4
exit ;;
*:[Aa]miga[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-amigaos
+ echo "$UNAME_MACHINE"-unknown-amigaos
exit ;;
*:[Mm]orph[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-morphos
+ echo "$UNAME_MACHINE"-unknown-morphos
exit ;;
*:OS/390:*:*)
echo i370-ibm-openedition
@@ -304,7 +360,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo powerpc-ibm-os400
exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- echo arm-acorn-riscix${UNAME_RELEASE}
+ echo arm-acorn-riscix"$UNAME_RELEASE"
exit ;;
arm*:riscos:*:*|arm*:RISCOS:*:*)
echo arm-unknown-riscos
@@ -331,38 +387,38 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
sparc) echo sparc-icl-nx7; exit ;;
esac ;;
s390x:SunOS:*:*)
- echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
exit ;;
sun4H:SunOS:5.*:*)
- echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
- echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
exit ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
- echo i386-pc-auroraux${UNAME_RELEASE}
+ echo i386-pc-auroraux"$UNAME_RELEASE"
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
- eval $set_cc_for_build
- SUN_ARCH="i386"
+ set_cc_for_build
+ SUN_ARCH=i386
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
- SUN_ARCH="x86_64"
+ SUN_ARCH=x86_64
fi
fi
- echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
- echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
@@ -371,25 +427,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
- echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
exit ;;
sun3*:SunOS:*:*)
- echo m68k-sun-sunos${UNAME_RELEASE}
+ echo m68k-sun-sunos"$UNAME_RELEASE"
exit ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
case "`/bin/arch`" in
sun3)
- echo m68k-sun-sunos${UNAME_RELEASE}
+ echo m68k-sun-sunos"$UNAME_RELEASE"
;;
sun4)
- echo sparc-sun-sunos${UNAME_RELEASE}
+ echo sparc-sun-sunos"$UNAME_RELEASE"
;;
esac
exit ;;
aushp:SunOS:*:*)
- echo sparc-auspex-sunos${UNAME_RELEASE}
+ echo sparc-auspex-sunos"$UNAME_RELEASE"
exit ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
@@ -400,44 +456,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
+ echo m68k-atari-mint"$UNAME_RELEASE"
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
+ echo m68k-atari-mint"$UNAME_RELEASE"
exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
+ echo m68k-atari-mint"$UNAME_RELEASE"
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
+ echo m68k-milan-mint"$UNAME_RELEASE"
exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
+ echo m68k-hades-mint"$UNAME_RELEASE"
exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
+ echo m68k-unknown-mint"$UNAME_RELEASE"
exit ;;
m68k:machten:*:*)
- echo m68k-apple-machten${UNAME_RELEASE}
+ echo m68k-apple-machten"$UNAME_RELEASE"
exit ;;
powerpc:machten:*:*)
- echo powerpc-apple-machten${UNAME_RELEASE}
+ echo powerpc-apple-machten"$UNAME_RELEASE"
exit ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
exit ;;
RISC*:ULTRIX:*:*)
- echo mips-dec-ultrix${UNAME_RELEASE}
+ echo mips-dec-ultrix"$UNAME_RELEASE"
exit ;;
VAX*:ULTRIX*:*:*)
- echo vax-dec-ultrix${UNAME_RELEASE}
+ echo vax-dec-ultrix"$UNAME_RELEASE"
exit ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
- echo clipper-intergraph-clix${UNAME_RELEASE}
+ echo clipper-intergraph-clix"$UNAME_RELEASE"
exit ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#ifdef __cplusplus
#include <stdio.h> /* for printf() prototype */
int main (int argc, char *argv[]) {
@@ -446,23 +502,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
- printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
- printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
- printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c &&
- dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
- SYSTEM_NAME=`$dummy $dummyarg` &&
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+ dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
{ echo "$SYSTEM_NAME"; exit; }
- echo mips-mips-riscos${UNAME_RELEASE}
+ echo mips-mips-riscos"$UNAME_RELEASE"
exit ;;
Motorola:PowerMAX_OS:*:*)
echo powerpc-motorola-powermax
@@ -488,17 +544,17 @@ EOF
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
- if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
then
- if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
- [ ${TARGET_BINARY_INTERFACE}x = x ]
+ if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
+ [ "$TARGET_BINARY_INTERFACE"x = x ]
then
- echo m88k-dg-dgux${UNAME_RELEASE}
+ echo m88k-dg-dgux"$UNAME_RELEASE"
else
- echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ echo m88k-dg-dguxbcs"$UNAME_RELEASE"
fi
else
- echo i586-dg-dgux${UNAME_RELEASE}
+ echo i586-dg-dgux"$UNAME_RELEASE"
fi
exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
@@ -515,7 +571,7 @@ EOF
echo m68k-tektronix-bsd
exit ;;
*:IRIX*:*:*)
- echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
exit ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
@@ -527,14 +583,14 @@ EOF
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
fi
- echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
exit ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#include <sys/systemcfg.h>
main()
@@ -545,7 +601,7 @@ EOF
exit(0);
}
EOF
- if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
then
echo "$SYSTEM_NAME"
else
@@ -559,26 +615,27 @@ EOF
exit ;;
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
- if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
+ if [ -x /usr/bin/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
fi
- echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
exit ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit ;;
- ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
echo romp-ibm-bsd4.4
exit ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
- echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to
exit ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
@@ -593,28 +650,28 @@ EOF
echo m68k-hp-bsd4.4
exit ;;
9000/[34678]??:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- case "${UNAME_MACHINE}" in
- 9000/31? ) HP_ARCH=m68000 ;;
- 9000/[34]?? ) HP_ARCH=m68k ;;
+ HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+ case "$UNAME_MACHINE" in
+ 9000/31?) HP_ARCH=m68000 ;;
+ 9000/[34]??) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ case "$sc_cpu_version" in
+ 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
- '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ case "$sc_kernel_bits" in
+ 32) HP_ARCH=hppa2.0n ;;
+ 64) HP_ARCH=hppa2.0w ;;
+ '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
esac ;;
esac
fi
- if [ "${HP_ARCH}" = "" ]; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ if [ "$HP_ARCH" = "" ]; then
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#define _HPUX_SOURCE
#include <stdlib.h>
@@ -647,13 +704,13 @@ EOF
exit (0);
}
EOF
- (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
- if [ ${HP_ARCH} = "hppa2.0w" ]
+ if [ "$HP_ARCH" = hppa2.0w ]
then
- eval $set_cc_for_build
+ set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
@@ -664,23 +721,23 @@ EOF
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
# => hppa64-hp-hpux11.23
- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
- HP_ARCH="hppa2.0w"
+ HP_ARCH=hppa2.0w
else
- HP_ARCH="hppa64"
+ HP_ARCH=hppa64
fi
fi
- echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
exit ;;
ia64:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- echo ia64-hp-hpux${HPUX_REV}
+ HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux"$HPUX_REV"
exit ;;
3050*:HI-UX:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#include <unistd.h>
int
main ()
@@ -705,11 +762,11 @@ EOF
exit (0);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
{ echo "$SYSTEM_NAME"; exit; }
echo unknown-hitachi-hiuxwe2
exit ;;
- 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
echo hppa1.1-hp-bsd
exit ;;
9000/8??:4.3bsd:*:*)
@@ -718,7 +775,7 @@ EOF
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix
exit ;;
- hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
echo hppa1.1-hp-osf
exit ;;
hp8??:OSF1:*:*)
@@ -726,9 +783,9 @@ EOF
exit ;;
i*86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
- echo ${UNAME_MACHINE}-unknown-osf1mk
+ echo "$UNAME_MACHINE"-unknown-osf1mk
else
- echo ${UNAME_MACHINE}-unknown-osf1
+ echo "$UNAME_MACHINE"-unknown-osf1
fi
exit ;;
parisc*:Lites*:*:*)
@@ -753,130 +810,123 @@ EOF
echo c4-convex-bsd
exit ;;
CRAY*Y-MP:*:*:*)
- echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*[A-Z]90:*:*:*)
- echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
- echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*T3E:*:*:*)
- echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*SV1:*:*:*)
- echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
*:UNICOS/mp:*:*)
- echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
- FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
exit ;;
sparc*:BSD/OS:*:*)
- echo sparc-unknown-bsdi${UNAME_RELEASE}
+ echo sparc-unknown-bsdi"$UNAME_RELEASE"
exit ;;
*:BSD/OS:*:*)
- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
+ exit ;;
+ arm:FreeBSD:*:*)
+ UNAME_PROCESSOR=`uname -p`
+ set_cc_for_build
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi
+ else
+ echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf
+ fi
exit ;;
*:FreeBSD:*:*)
UNAME_PROCESSOR=`/usr/bin/uname -p`
- case ${UNAME_PROCESSOR} in
+ case "$UNAME_PROCESSOR" in
amd64)
- echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- *)
- echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
esac
+ echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
exit ;;
i*:CYGWIN*:*)
- echo ${UNAME_MACHINE}-pc-cygwin
+ echo "$UNAME_MACHINE"-pc-cygwin
exit ;;
*:MINGW64*:*)
- echo ${UNAME_MACHINE}-pc-mingw64
+ echo "$UNAME_MACHINE"-pc-mingw64
exit ;;
*:MINGW*:*)
- echo ${UNAME_MACHINE}-pc-mingw32
- exit ;;
- i*:MSYS*:*)
- echo ${UNAME_MACHINE}-pc-msys
+ echo "$UNAME_MACHINE"-pc-mingw32
exit ;;
- i*:windows32*:*)
- # uname -m includes "-pc" on this system.
- echo ${UNAME_MACHINE}-mingw32
+ *:MSYS*:*)
+ echo "$UNAME_MACHINE"-pc-msys
exit ;;
i*:PW*:*)
- echo ${UNAME_MACHINE}-pc-pw32
+ echo "$UNAME_MACHINE"-pc-pw32
exit ;;
*:Interix*:*)
- case ${UNAME_MACHINE} in
+ case "$UNAME_MACHINE" in
x86)
- echo i586-pc-interix${UNAME_RELEASE}
+ echo i586-pc-interix"$UNAME_RELEASE"
exit ;;
authenticamd | genuineintel | EM64T)
- echo x86_64-unknown-interix${UNAME_RELEASE}
+ echo x86_64-unknown-interix"$UNAME_RELEASE"
exit ;;
IA64)
- echo ia64-unknown-interix${UNAME_RELEASE}
+ echo ia64-unknown-interix"$UNAME_RELEASE"
exit ;;
esac ;;
- [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
- echo i${UNAME_MACHINE}-pc-mks
- exit ;;
- 8664:Windows_NT:*)
- echo x86_64-pc-mks
- exit ;;
- i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
- # UNAME_MACHINE based on the output of uname instead of i386?
- echo i586-pc-interix
- exit ;;
i*:UWIN*:*)
- echo ${UNAME_MACHINE}-pc-uwin
+ echo "$UNAME_MACHINE"-pc-uwin
exit ;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
- echo x86_64-unknown-cygwin
- exit ;;
- p*:CYGWIN*:*)
- echo powerpcle-unknown-cygwin
+ echo x86_64-pc-cygwin
exit ;;
prep*:SunOS:5.*:*)
- echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;;
*:GNU:*:*)
# the GNU system
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
exit ;;
- i*86:Minix:*:*)
- echo ${UNAME_MACHINE}-pc-minix
+ *:Minix:*:*)
+ echo "$UNAME_MACHINE"-unknown-minix
exit ;;
aarch64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
alpha:Linux:*:*)
- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
@@ -886,125 +936,169 @@ EOF
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
arm*:Linux:*:*)
- eval $set_cc_for_build
+ set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
- echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
else
- echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
cris:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-gnu
+ echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
exit ;;
crisv32:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-gnu
+ echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
+ exit ;;
+ e2k:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
frv:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
hexagon:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
i*86:Linux:*:*)
- LIBC=gnu
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #ifdef __dietlibc__
- LIBC=dietlibc
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
exit ;;
ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ k1om:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ IS_GLIBC=0
+ test x"${LIBC}" = xgnu && IS_GLIBC=1
+ sed 's/^ //' << EOF > "$dummy.c"
#undef CPU
- #undef ${UNAME_MACHINE}
- #undef ${UNAME_MACHINE}el
+ #undef mips
+ #undef mipsel
+ #undef mips64
+ #undef mips64el
+ #if ${IS_GLIBC} && defined(_ABI64)
+ LIBCABI=gnuabi64
+ #else
+ #if ${IS_GLIBC} && defined(_ABIN32)
+ LIBCABI=gnuabin32
+ #else
+ LIBCABI=${LIBC}
+ #endif
+ #endif
+
+ #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa64r6
+ #else
+ #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa32r6
+ #else
+ #if defined(__mips64)
+ CPU=mips64
+ #else
+ CPU=mips
+ #endif
+ #endif
+ #endif
+
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=${UNAME_MACHINE}el
+ MIPS_ENDIAN=el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=${UNAME_MACHINE}
+ MIPS_ENDIAN=
#else
- CPU=
+ MIPS_ENDIAN=
#endif
#endif
EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`"
+ test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
;;
- or32:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ mips64el:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ openrisc*:Linux:*:*)
+ echo or1k-unknown-linux-"$LIBC"
+ exit ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
padre:Linux:*:*)
- echo sparc-unknown-linux-gnu
+ echo sparc-unknown-linux-"$LIBC"
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-gnu
+ echo hppa64-unknown-linux-"$LIBC"
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux-gnu ;;
- PA8*) echo hppa2.0-unknown-linux-gnu ;;
- *) echo hppa-unknown-linux-gnu ;;
+ PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
+ PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
+ *) echo hppa-unknown-linux-"$LIBC" ;;
esac
exit ;;
ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-gnu
+ echo powerpc64-unknown-linux-"$LIBC"
exit ;;
ppc:Linux:*:*)
- echo powerpc-unknown-linux-gnu
+ echo powerpc-unknown-linux-"$LIBC"
+ exit ;;
+ ppc64le:Linux:*:*)
+ echo powerpc64le-unknown-linux-"$LIBC"
+ exit ;;
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-"$LIBC"
+ exit ;;
+ riscv32:Linux:*:* | riscv64:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux
+ echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
exit ;;
sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
tile*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
vax:Linux:*:*)
- echo ${UNAME_MACHINE}-dec-linux-gnu
+ echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
exit ;;
x86_64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
exit ;;
xtensa*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -1018,34 +1112,34 @@ EOF
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
- echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
exit ;;
i*86:OS/2:*:*)
# If we were able to find `uname', then EMX Unix compatibility
# is probably installed.
- echo ${UNAME_MACHINE}-pc-os2-emx
+ echo "$UNAME_MACHINE"-pc-os2-emx
exit ;;
i*86:XTS-300:*:STOP)
- echo ${UNAME_MACHINE}-unknown-stop
+ echo "$UNAME_MACHINE"-unknown-stop
exit ;;
i*86:atheos:*:*)
- echo ${UNAME_MACHINE}-unknown-atheos
+ echo "$UNAME_MACHINE"-unknown-atheos
exit ;;
i*86:syllable:*:*)
- echo ${UNAME_MACHINE}-pc-syllable
+ echo "$UNAME_MACHINE"-pc-syllable
exit ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
- echo i386-unknown-lynxos${UNAME_RELEASE}
+ echo i386-unknown-lynxos"$UNAME_RELEASE"
exit ;;
i*86:*DOS:*:*)
- echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ echo "$UNAME_MACHINE"-pc-msdosdjgpp
exit ;;
- i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
- UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ i*86:*:4.*:*)
+ UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
- echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
else
- echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
fi
exit ;;
i*86:*:5:[678]*)
@@ -1055,12 +1149,12 @@ EOF
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
- echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}"
exit ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
- echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
elif /bin/uname -X 2>/dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
@@ -1070,9 +1164,9 @@ EOF
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
- echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
else
- echo ${UNAME_MACHINE}-pc-sysv32
+ echo "$UNAME_MACHINE"-pc-sysv32
fi
exit ;;
pc:*:*:*)
@@ -1080,7 +1174,7 @@ EOF
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
- # prints for the "djgpp" host, or else GDB configury will decide that
+ # prints for the "djgpp" host, or else GDB configure will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
exit ;;
@@ -1092,9 +1186,9 @@ EOF
exit ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
- echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
- echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4
fi
exit ;;
mini*:CTIX:SYS*5:*)
@@ -1114,9 +1208,9 @@ EOF
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
@@ -1125,28 +1219,28 @@ EOF
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
- echo m68k-unknown-lynxos${UNAME_RELEASE}
+ echo m68k-unknown-lynxos"$UNAME_RELEASE"
exit ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit ;;
TSUNAMI:LynxOS:2.*:*)
- echo sparc-unknown-lynxos${UNAME_RELEASE}
+ echo sparc-unknown-lynxos"$UNAME_RELEASE"
exit ;;
rs6000:LynxOS:2.*:*)
- echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ echo rs6000-unknown-lynxos"$UNAME_RELEASE"
exit ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
- echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ echo powerpc-unknown-lynxos"$UNAME_RELEASE"
exit ;;
SM[BE]S:UNIX_SV:*:*)
- echo mips-dde-sysv${UNAME_RELEASE}
+ echo mips-dde-sysv"$UNAME_RELEASE"
exit ;;
RM*:ReliantUNIX-*:*:*)
echo mips-sni-sysv4
@@ -1157,7 +1251,7 @@ EOF
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
- echo ${UNAME_MACHINE}-sni-sysv4
+ echo "$UNAME_MACHINE"-sni-sysv4
else
echo ns32k-sni-sysv
fi
@@ -1177,23 +1271,23 @@ EOF
exit ;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
- echo ${UNAME_MACHINE}-stratus-vos
+ echo "$UNAME_MACHINE"-stratus-vos
exit ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
echo hppa1.1-stratus-vos
exit ;;
mc68*:A/UX:*:*)
- echo m68k-apple-aux${UNAME_RELEASE}
+ echo m68k-apple-aux"$UNAME_RELEASE"
exit ;;
news*:NEWS-OS:6*:*)
echo mips-sony-newsos6
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
+ echo mips-nec-sysv"$UNAME_RELEASE"
else
- echo mips-unknown-sysv${UNAME_RELEASE}
+ echo mips-unknown-sysv"$UNAME_RELEASE"
fi
exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
@@ -1212,65 +1306,94 @@ EOF
echo x86_64-unknown-haiku
exit ;;
SX-4:SUPER-UX:*:*)
- echo sx4-nec-superux${UNAME_RELEASE}
+ echo sx4-nec-superux"$UNAME_RELEASE"
exit ;;
SX-5:SUPER-UX:*:*)
- echo sx5-nec-superux${UNAME_RELEASE}
+ echo sx5-nec-superux"$UNAME_RELEASE"
exit ;;
SX-6:SUPER-UX:*:*)
- echo sx6-nec-superux${UNAME_RELEASE}
+ echo sx6-nec-superux"$UNAME_RELEASE"
exit ;;
SX-7:SUPER-UX:*:*)
- echo sx7-nec-superux${UNAME_RELEASE}
+ echo sx7-nec-superux"$UNAME_RELEASE"
exit ;;
SX-8:SUPER-UX:*:*)
- echo sx8-nec-superux${UNAME_RELEASE}
+ echo sx8-nec-superux"$UNAME_RELEASE"
exit ;;
SX-8R:SUPER-UX:*:*)
- echo sx8r-nec-superux${UNAME_RELEASE}
+ echo sx8r-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-ACE:SUPER-UX:*:*)
+ echo sxace-nec-superux"$UNAME_RELEASE"
exit ;;
Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ echo powerpc-apple-rhapsody"$UNAME_RELEASE"
exit ;;
*:Rhapsody:*:*)
- echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
exit ;;
*:Darwin:*:*)
- UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ UNAME_PROCESSOR=`uname -p`
case $UNAME_PROCESSOR in
- i386)
- eval $set_cc_for_build
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- UNAME_PROCESSOR="x86_64"
- fi
- fi ;;
unknown) UNAME_PROCESSOR=powerpc ;;
esac
- echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ if command -v xcode-select > /dev/null 2> /dev/null && \
+ ! xcode-select --print-path > /dev/null 2> /dev/null ; then
+ # Avoid executing cc if there is no toolchain installed as
+ # cc will be a stub that puts up a graphical alert
+ # prompting the user to install developer tools.
+ CC_FOR_BUILD=no_compiler_found
+ else
+ set_cc_for_build
+ fi
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+ if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_PPC >/dev/null
+ then
+ UNAME_PROCESSOR=powerpc
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # uname -m returns i386 or x86_64
+ UNAME_PROCESSOR=$UNAME_MACHINE
+ fi
+ echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
- if test "$UNAME_PROCESSOR" = "x86"; then
+ if test "$UNAME_PROCESSOR" = x86; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
- echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
exit ;;
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
- NEO-?:NONSTOP_KERNEL:*:*)
- echo neo-tandem-nsk${UNAME_RELEASE}
+ NEO-*:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk"$UNAME_RELEASE"
exit ;;
NSE-*:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk${UNAME_RELEASE}
+ echo nse-tandem-nsk"$UNAME_RELEASE"
exit ;;
- NSR-?:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk${UNAME_RELEASE}
+ NSR-*:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSV-*:NONSTOP_KERNEL:*:*)
+ echo nsv-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSX-*:NONSTOP_KERNEL:*:*)
+ echo nsx-tandem-nsk"$UNAME_RELEASE"
exit ;;
*:NonStop-UX:*:*)
echo mips-compaq-nonstopux
@@ -1279,18 +1402,19 @@ EOF
echo bs2000-siemens-sysv
exit ;;
DS/*:UNIX_System_V:*:*)
- echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
exit ;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
- if test "$cputype" = "386"; then
+ # shellcheck disable=SC2154
+ if test "$cputype" = 386; then
UNAME_MACHINE=i386
else
UNAME_MACHINE="$cputype"
fi
- echo ${UNAME_MACHINE}-unknown-plan9
+ echo "$UNAME_MACHINE"-unknown-plan9
exit ;;
*:TOPS-10:*:*)
echo pdp10-unknown-tops10
@@ -1311,14 +1435,14 @@ EOF
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
+ echo mips-sei-seiux"$UNAME_RELEASE"
exit ;;
*:DragonFly:*:*)
- echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
exit ;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
- case "${UNAME_MACHINE}" in
+ case "$UNAME_MACHINE" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
V*) echo vax-dec-vms ; exit ;;
@@ -1327,24 +1451,39 @@ EOF
echo i386-pc-xenix
exit ;;
i*86:skyos:*:*)
- echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
exit ;;
i*86:rdos:*:*)
- echo ${UNAME_MACHINE}-pc-rdos
+ echo "$UNAME_MACHINE"-pc-rdos
exit ;;
i*86:AROS:*:*)
- echo ${UNAME_MACHINE}-pc-aros
+ echo "$UNAME_MACHINE"-pc-aros
exit ;;
x86_64:VMkernel:*:*)
- echo ${UNAME_MACHINE}-unknown-esx
+ echo "$UNAME_MACHINE"-unknown-esx
+ exit ;;
+ amd64:Isilon\ OneFS:*:*)
+ echo x86_64-unknown-onefs
+ exit ;;
+ *:Unleashed:*:*)
+ echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE"
exit ;;
esac
-eval $set_cc_for_build
-cat >$dummy.c <<EOF
+# No uname command or uname output not recognized.
+set_cc_for_build
+cat > "$dummy.c" <<EOF
#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#include <signal.h>
+#if defined(_SIZE_T_) || defined(SIGLOST)
+#include <sys/utsname.h>
+#endif
+#endif
#endif
main ()
{
@@ -1357,20 +1496,12 @@ main ()
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
- "4"
+ "4"
#else
- ""
-#endif
- ); exit (0);
+ ""
#endif
+ ); exit (0);
#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
- printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
- printf ("m68k-hp-bsd\n"); exit (0);
#endif
#if defined (NeXT)
@@ -1412,39 +1543,54 @@ main ()
#endif
#if defined (_SEQUENT_)
- struct utsname un;
-
- uname(&un);
-
- if (strncmp(un.version, "V2", 2) == 0) {
- printf ("i386-sequent-ptx2\n"); exit (0);
- }
- if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
- printf ("i386-sequent-ptx1\n"); exit (0);
- }
- printf ("i386-sequent-ptx\n"); exit (0);
+ struct utsname un;
+ uname(&un);
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
#endif
#if defined (vax)
-# if !defined (ultrix)
-# include <sys/param.h>
-# if defined (BSD)
-# if BSD == 43
- printf ("vax-dec-bsd4.3\n"); exit (0);
-# else
-# if BSD == 199006
- printf ("vax-dec-bsd4.3reno\n"); exit (0);
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# endif
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# else
- printf ("vax-dec-ultrix\n"); exit (0);
-# endif
+#if !defined (ultrix)
+#include <sys/param.h>
+#if defined (BSD)
+#if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+#else
+#if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#endif
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#else
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname un;
+ uname (&un);
+ printf ("vax-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname *un;
+ uname (&un);
+ printf ("mips-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("mips-dec-ultrix\n"); exit (0);
+#endif
+#endif
#endif
#if defined (alliant) && defined (i860)
@@ -1455,54 +1601,44 @@ main ()
}
EOF
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` &&
{ echo "$SYSTEM_NAME"; exit; }
# Apollos put the system type in the environment.
+test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+echo "$0: unable to guess system type" >&2
-# Convex versions that predate uname can use getsysinfo(1)
+case "$UNAME_MACHINE:$UNAME_SYSTEM" in
+ mips:Linux | mips64:Linux)
+ # If we got here on MIPS GNU/Linux, output extra information.
+ cat >&2 <<EOF
-if [ -x /usr/convex/getsysinfo ]
-then
- case `getsysinfo -f cpu_type` in
- c1*)
- echo c1-convex-bsd
- exit ;;
- c2*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit ;;
- c34*)
- echo c34-convex-bsd
- exit ;;
- c38*)
- echo c38-convex-bsd
- exit ;;
- c4*)
- echo c4-convex-bsd
- exit ;;
- esac
-fi
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
+EOF
+ ;;
+esac
cat >&2 <<EOF
-$0: unable to guess system type
-This script, last modified $timestamp, has failed to recognize
-the operating system you are using. It is advised that you
-download the most up to date version of the config scripts from
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite *all*
+copies of config.guess and config.sub with the latest versions from:
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
and
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+EOF
-If the version you run ($0) is already up to date, please
-send the following data and any information you think might be
-pertinent to <config-patches@gnu.org> in order to provide the needed
-information to handle your system.
+year=`echo $timestamp | sed 's,-.*,,'`
+# shellcheck disable=SC2003
+if test "`expr "\`date +%Y\`" - "$year"`" -lt 3 ; then
+ cat >&2 <<EOF
+
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
config.guess timestamp = $timestamp
@@ -1521,16 +1657,17 @@ hostinfo = `(hostinfo) 2>/dev/null`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
-UNAME_MACHINE = ${UNAME_MACHINE}
-UNAME_RELEASE = ${UNAME_RELEASE}
-UNAME_SYSTEM = ${UNAME_SYSTEM}
-UNAME_VERSION = ${UNAME_VERSION}
+UNAME_MACHINE = "$UNAME_MACHINE"
+UNAME_RELEASE = "$UNAME_RELEASE"
+UNAME_SYSTEM = "$UNAME_SYSTEM"
+UNAME_VERSION = "$UNAME_VERSION"
EOF
+fi
exit 1
# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
diff --git a/config.h.in b/config.h.in
deleted file mode 100644
index 7e7e38ec..00000000
--- a/config.h.in
+++ /dev/null
@@ -1,1707 +0,0 @@
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address
- */
-#undef AIX_GETNAMEINFO_HACK
-
-/* Define if your AIX loginfailed() function takes 4 arguments (AIX >= 5.2) */
-#undef AIX_LOGINFAILED_4ARG
-
-/* System only supports IPv4 audit records */
-#undef AU_IPv4
-
-/* Define if your resolver libs need this for getrrsetbyname */
-#undef BIND_8_COMPAT
-
-/* The system has incomplete BSM API */
-#undef BROKEN_BSM_API
-
-/* Define if cmsg_type is not passed correctly */
-#undef BROKEN_CMSG_TYPE
-
-/* getaddrinfo is broken (if present) */
-#undef BROKEN_GETADDRINFO
-
-/* getgroups(0,NULL) will return -1 */
-#undef BROKEN_GETGROUPS
-
-/* FreeBSD glob does not do what we need */
-#undef BROKEN_GLOB
-
-/* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */
-#undef BROKEN_INET_NTOA
-
-/* ia_uinfo routines not supported by OS yet */
-#undef BROKEN_LIBIAF
-
-/* Ultrix mmap can't map files */
-#undef BROKEN_MMAP
-
-/* Define if your struct dirent expects you to allocate extra space for d_name
- */
-#undef BROKEN_ONE_BYTE_DIRENT_D_NAME
-
-/* Can't do comparisons on readv */
-#undef BROKEN_READV_COMPARISON
-
-/* NetBSD read function is sometimes redirected, breaking atomicio comparisons
- against it */
-#undef BROKEN_READ_COMPARISON
-
-/* Define if you have a broken realpath. */
-#undef BROKEN_REALPATH
-
-/* Needed for NeXT */
-#undef BROKEN_SAVED_UIDS
-
-/* Define if your setregid() is broken */
-#undef BROKEN_SETREGID
-
-/* Define if your setresgid() is broken */
-#undef BROKEN_SETRESGID
-
-/* Define if your setresuid() is broken */
-#undef BROKEN_SETRESUID
-
-/* Define if your setreuid() is broken */
-#undef BROKEN_SETREUID
-
-/* LynxOS has broken setvbuf() implementation */
-#undef BROKEN_SETVBUF
-
-/* QNX shadow support is broken */
-#undef BROKEN_SHADOW_EXPIRE
-
-/* Define if your snprintf is busted */
-#undef BROKEN_SNPRINTF
-
-/* FreeBSD strnvis argument order is swapped compared to OpenBSD */
-#undef BROKEN_STRNVIS
-
-/* tcgetattr with ICANON may hang */
-#undef BROKEN_TCGETATTR_ICANON
-
-/* updwtmpx is broken (if present) */
-#undef BROKEN_UPDWTMPX
-
-/* Define if you have BSD auth support */
-#undef BSD_AUTH
-
-/* Define if you want to specify the path to your lastlog file */
-#undef CONF_LASTLOG_FILE
-
-/* Define if you want to specify the path to your utmp file */
-#undef CONF_UTMP_FILE
-
-/* Define if you want to specify the path to your wtmpx file */
-#undef CONF_WTMPX_FILE
-
-/* Define if you want to specify the path to your wtmp file */
-#undef CONF_WTMP_FILE
-
-/* Define if your platform needs to skip post auth file descriptor passing */
-#undef DISABLE_FD_PASSING
-
-/* Define if you don't want to use lastlog */
-#undef DISABLE_LASTLOG
-
-/* Define if you don't want to use your system's login() call */
-#undef DISABLE_LOGIN
-
-/* Define if you don't want to use pututline() etc. to write [uw]tmp */
-#undef DISABLE_PUTUTLINE
-
-/* Define if you don't want to use pututxline() etc. to write [uw]tmpx */
-#undef DISABLE_PUTUTXLINE
-
-/* Define if you want to disable shadow passwords */
-#undef DISABLE_SHADOW
-
-/* Define if you don't want to use utmp */
-#undef DISABLE_UTMP
-
-/* Define if you don't want to use utmpx */
-#undef DISABLE_UTMPX
-
-/* Define if you don't want to use wtmp */
-#undef DISABLE_WTMP
-
-/* Define if you don't want to use wtmpx */
-#undef DISABLE_WTMPX
-
-/* Enable for PKCS#11 support */
-#undef ENABLE_PKCS11
-
-/* File names may not contain backslash characters */
-#undef FILESYSTEM_NO_BACKSLASH
-
-/* fsid_t has member val */
-#undef FSID_HAS_VAL
-
-/* fsid_t has member __val */
-#undef FSID_HAS___VAL
-
-/* Define to 1 if the `getpgrp' function requires zero arguments. */
-#undef GETPGRP_VOID
-
-/* Conflicting defs for getspnam */
-#undef GETSPNAM_CONFLICTING_DEFS
-
-/* Define if your system glob() function has the GLOB_ALTDIRFUNC extension */
-#undef GLOB_HAS_ALTDIRFUNC
-
-/* Define if your system glob() function has gl_matchc options in glob_t */
-#undef GLOB_HAS_GL_MATCHC
-
-/* Define if your system glob() function has gl_statv options in glob_t */
-#undef GLOB_HAS_GL_STATV
-
-/* Define this if you want GSSAPI support in the version 2 protocol */
-#undef GSSAPI
-
-/* Define if you want to use shadow password expire field */
-#undef HAS_SHADOW_EXPIRE
-
-/* Define if your system uses access rights style file descriptor passing */
-#undef HAVE_ACCRIGHTS_IN_MSGHDR
-
-/* Define if you have ut_addr in utmp.h */
-#undef HAVE_ADDR_IN_UTMP
-
-/* Define if you have ut_addr in utmpx.h */
-#undef HAVE_ADDR_IN_UTMPX
-
-/* Define if you have ut_addr_v6 in utmp.h */
-#undef HAVE_ADDR_V6_IN_UTMP
-
-/* Define if you have ut_addr_v6 in utmpx.h */
-#undef HAVE_ADDR_V6_IN_UTMPX
-
-/* Define to 1 if you have the `arc4random' function. */
-#undef HAVE_ARC4RANDOM
-
-/* Define to 1 if you have the `arc4random_buf' function. */
-#undef HAVE_ARC4RANDOM_BUF
-
-/* Define to 1 if you have the `arc4random_stir' function. */
-#undef HAVE_ARC4RANDOM_STIR
-
-/* Define to 1 if you have the `arc4random_uniform' function. */
-#undef HAVE_ARC4RANDOM_UNIFORM
-
-/* Define to 1 if you have the `asprintf' function. */
-#undef HAVE_ASPRINTF
-
-/* OpenBSD's gcc has bounded */
-#undef HAVE_ATTRIBUTE__BOUNDED__
-
-/* Have attribute nonnull */
-#undef HAVE_ATTRIBUTE__NONNULL__
-
-/* OpenBSD's gcc has sentinel */
-#undef HAVE_ATTRIBUTE__SENTINEL__
-
-/* Define to 1 if you have the `aug_get_machine' function. */
-#undef HAVE_AUG_GET_MACHINE
-
-/* Define to 1 if you have the `b64_ntop' function. */
-#undef HAVE_B64_NTOP
-
-/* Define to 1 if you have the `b64_pton' function. */
-#undef HAVE_B64_PTON
-
-/* Define if you have the basename function. */
-#undef HAVE_BASENAME
-
-/* Define to 1 if you have the `bcopy' function. */
-#undef HAVE_BCOPY
-
-/* Define to 1 if you have the `bcrypt_pbkdf' function. */
-#undef HAVE_BCRYPT_PBKDF
-
-/* Define to 1 if you have the `bindresvport_sa' function. */
-#undef HAVE_BINDRESVPORT_SA
-
-/* Define to 1 if you have the `blf_enc' function. */
-#undef HAVE_BLF_ENC
-
-/* Define to 1 if you have the <blf.h> header file. */
-#undef HAVE_BLF_H
-
-/* Define to 1 if you have the `Blowfish_expand0state' function. */
-#undef HAVE_BLOWFISH_EXPAND0STATE
-
-/* Define to 1 if you have the `Blowfish_expandstate' function. */
-#undef HAVE_BLOWFISH_EXPANDSTATE
-
-/* Define to 1 if you have the `Blowfish_initstate' function. */
-#undef HAVE_BLOWFISH_INITSTATE
-
-/* Define to 1 if you have the `Blowfish_stream2word' function. */
-#undef HAVE_BLOWFISH_STREAM2WORD
-
-/* Define to 1 if you have the `BN_is_prime_ex' function. */
-#undef HAVE_BN_IS_PRIME_EX
-
-/* Define to 1 if you have the <bsd/libutil.h> header file. */
-#undef HAVE_BSD_LIBUTIL_H
-
-/* Define to 1 if you have the <bsm/audit.h> header file. */
-#undef HAVE_BSM_AUDIT_H
-
-/* Define to 1 if you have the <bstring.h> header file. */
-#undef HAVE_BSTRING_H
-
-/* Define to 1 if you have the `cap_rights_limit' function. */
-#undef HAVE_CAP_RIGHTS_LIMIT
-
-/* Define to 1 if you have the `clock' function. */
-#undef HAVE_CLOCK
-
-/* Have clock_gettime */
-#undef HAVE_CLOCK_GETTIME
-
-/* define if you have clock_t data type */
-#undef HAVE_CLOCK_T
-
-/* Define to 1 if you have the `closefrom' function. */
-#undef HAVE_CLOSEFROM
-
-/* Define if gai_strerror() returns const char * */
-#undef HAVE_CONST_GAI_STRERROR_PROTO
-
-/* Define if your system uses ancillary data style file descriptor passing */
-#undef HAVE_CONTROL_IN_MSGHDR
-
-/* Define to 1 if you have the `crypt' function. */
-#undef HAVE_CRYPT
-
-/* Define to 1 if you have the <crypto/sha2.h> header file. */
-#undef HAVE_CRYPTO_SHA2_H
-
-/* Define to 1 if you have the <crypt.h> header file. */
-#undef HAVE_CRYPT_H
-
-/* Define if you are on Cygwin */
-#undef HAVE_CYGWIN
-
-/* Define if your libraries define daemon() */
-#undef HAVE_DAEMON
-
-/* Define to 1 if you have the declaration of `AI_NUMERICSERV', and to 0 if
- you don't. */
-#undef HAVE_DECL_AI_NUMERICSERV
-
-/* Define to 1 if you have the declaration of `authenticate', and to 0 if you
- don't. */
-#undef HAVE_DECL_AUTHENTICATE
-
-/* Define to 1 if you have the declaration of `GLOB_NOMATCH', and to 0 if you
- don't. */
-#undef HAVE_DECL_GLOB_NOMATCH
-
-/* Define to 1 if you have the declaration of `GSS_C_NT_HOSTBASED_SERVICE',
- and to 0 if you don't. */
-#undef HAVE_DECL_GSS_C_NT_HOSTBASED_SERVICE
-
-/* Define to 1 if you have the declaration of `howmany', and to 0 if you
- don't. */
-#undef HAVE_DECL_HOWMANY
-
-/* Define to 1 if you have the declaration of `h_errno', and to 0 if you
- don't. */
-#undef HAVE_DECL_H_ERRNO
-
-/* Define to 1 if you have the declaration of `loginfailed', and to 0 if you
- don't. */
-#undef HAVE_DECL_LOGINFAILED
-
-/* Define to 1 if you have the declaration of `loginrestrictions', and to 0 if
- you don't. */
-#undef HAVE_DECL_LOGINRESTRICTIONS
-
-/* Define to 1 if you have the declaration of `loginsuccess', and to 0 if you
- don't. */
-#undef HAVE_DECL_LOGINSUCCESS
-
-/* Define to 1 if you have the declaration of `MAXSYMLINKS', and to 0 if you
- don't. */
-#undef HAVE_DECL_MAXSYMLINKS
-
-/* Define to 1 if you have the declaration of `NFDBITS', and to 0 if you
- don't. */
-#undef HAVE_DECL_NFDBITS
-
-/* Define to 1 if you have the declaration of `offsetof', and to 0 if you
- don't. */
-#undef HAVE_DECL_OFFSETOF
-
-/* Define to 1 if you have the declaration of `O_NONBLOCK', and to 0 if you
- don't. */
-#undef HAVE_DECL_O_NONBLOCK
-
-/* Define to 1 if you have the declaration of `passwdexpired', and to 0 if you
- don't. */
-#undef HAVE_DECL_PASSWDEXPIRED
-
-/* Define to 1 if you have the declaration of `setauthdb', and to 0 if you
- don't. */
-#undef HAVE_DECL_SETAUTHDB
-
-/* Define to 1 if you have the declaration of `SHUT_RD', and to 0 if you
- don't. */
-#undef HAVE_DECL_SHUT_RD
-
-/* Define to 1 if you have the declaration of `writev', and to 0 if you don't.
- */
-#undef HAVE_DECL_WRITEV
-
-/* Define to 1 if you have the declaration of `_getlong', and to 0 if you
- don't. */
-#undef HAVE_DECL__GETLONG
-
-/* Define to 1 if you have the declaration of `_getshort', and to 0 if you
- don't. */
-#undef HAVE_DECL__GETSHORT
-
-/* Define to 1 if you have the `DES_crypt' function. */
-#undef HAVE_DES_CRYPT
-
-/* Define if you have /dev/ptmx */
-#undef HAVE_DEV_PTMX
-
-/* Define if you have /dev/ptc */
-#undef HAVE_DEV_PTS_AND_PTC
-
-/* Define to 1 if you have the <dirent.h> header file. */
-#undef HAVE_DIRENT_H
-
-/* Define to 1 if you have the `dirfd' function. */
-#undef HAVE_DIRFD
-
-/* Define to 1 if you have the `dirname' function. */
-#undef HAVE_DIRNAME
-
-/* Define to 1 if you have the `DSA_generate_parameters_ex' function. */
-#undef HAVE_DSA_GENERATE_PARAMETERS_EX
-
-/* Define to 1 if you have the <elf.h> header file. */
-#undef HAVE_ELF_H
-
-/* Define to 1 if you have the `endgrent' function. */
-#undef HAVE_ENDGRENT
-
-/* Define to 1 if you have the <endian.h> header file. */
-#undef HAVE_ENDIAN_H
-
-/* Define to 1 if you have the `endutent' function. */
-#undef HAVE_ENDUTENT
-
-/* Define to 1 if you have the `endutxent' function. */
-#undef HAVE_ENDUTXENT
-
-/* Define if your system has /etc/default/login */
-#undef HAVE_ETC_DEFAULT_LOGIN
-
-/* Define if libcrypto has EVP_CIPHER_CTX_ctrl */
-#undef HAVE_EVP_CIPHER_CTX_CTRL
-
-/* Define to 1 if you have the `EVP_DigestFinal_ex' function. */
-#undef HAVE_EVP_DIGESTFINAL_EX
-
-/* Define to 1 if you have the `EVP_DigestInit_ex' function. */
-#undef HAVE_EVP_DIGESTINIT_EX
-
-/* Define to 1 if you have the `EVP_MD_CTX_cleanup' function. */
-#undef HAVE_EVP_MD_CTX_CLEANUP
-
-/* Define to 1 if you have the `EVP_MD_CTX_copy_ex' function. */
-#undef HAVE_EVP_MD_CTX_COPY_EX
-
-/* Define to 1 if you have the `EVP_MD_CTX_init' function. */
-#undef HAVE_EVP_MD_CTX_INIT
-
-/* Define to 1 if you have the `EVP_ripemd160' function. */
-#undef HAVE_EVP_RIPEMD160
-
-/* Define to 1 if you have the `EVP_sha256' function. */
-#undef HAVE_EVP_SHA256
-
-/* Define if you have ut_exit in utmp.h */
-#undef HAVE_EXIT_IN_UTMP
-
-/* Define to 1 if you have the `explicit_bzero' function. */
-#undef HAVE_EXPLICIT_BZERO
-
-/* Define to 1 if you have the `fchmod' function. */
-#undef HAVE_FCHMOD
-
-/* Define to 1 if you have the `fchown' function. */
-#undef HAVE_FCHOWN
-
-/* Use F_CLOSEM fcntl for closefrom */
-#undef HAVE_FCNTL_CLOSEM
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#undef HAVE_FCNTL_H
-
-/* Define to 1 if the system has the type `fd_mask'. */
-#undef HAVE_FD_MASK
-
-/* Define to 1 if you have the <features.h> header file. */
-#undef HAVE_FEATURES_H
-
-/* Define to 1 if you have the <floatingpoint.h> header file. */
-#undef HAVE_FLOATINGPOINT_H
-
-/* Define to 1 if you have the `fmt_scaled' function. */
-#undef HAVE_FMT_SCALED
-
-/* Define to 1 if you have the `freeaddrinfo' function. */
-#undef HAVE_FREEADDRINFO
-
-/* Define to 1 if the system has the type `fsblkcnt_t'. */
-#undef HAVE_FSBLKCNT_T
-
-/* Define to 1 if the system has the type `fsfilcnt_t'. */
-#undef HAVE_FSFILCNT_T
-
-/* Define to 1 if you have the `fstatfs' function. */
-#undef HAVE_FSTATFS
-
-/* Define to 1 if you have the `fstatvfs' function. */
-#undef HAVE_FSTATVFS
-
-/* Define to 1 if you have the `futimes' function. */
-#undef HAVE_FUTIMES
-
-/* Define to 1 if you have the `gai_strerror' function. */
-#undef HAVE_GAI_STRERROR
-
-/* Define to 1 if you have the `getaddrinfo' function. */
-#undef HAVE_GETADDRINFO
-
-/* Define to 1 if you have the `getaudit' function. */
-#undef HAVE_GETAUDIT
-
-/* Define to 1 if you have the `getaudit_addr' function. */
-#undef HAVE_GETAUDIT_ADDR
-
-/* Define to 1 if you have the `getcwd' function. */
-#undef HAVE_GETCWD
-
-/* Define to 1 if you have the `getgrouplist' function. */
-#undef HAVE_GETGROUPLIST
-
-/* Define to 1 if you have the `getgrset' function. */
-#undef HAVE_GETGRSET
-
-/* Define to 1 if you have the `getlastlogxbyname' function. */
-#undef HAVE_GETLASTLOGXBYNAME
-
-/* Define to 1 if you have the `getluid' function. */
-#undef HAVE_GETLUID
-
-/* Define to 1 if you have the `getnameinfo' function. */
-#undef HAVE_GETNAMEINFO
-
-/* Define to 1 if you have the `getopt' function. */
-#undef HAVE_GETOPT
-
-/* Define to 1 if you have the <getopt.h> header file. */
-#undef HAVE_GETOPT_H
-
-/* Define if your getopt(3) defines and uses optreset */
-#undef HAVE_GETOPT_OPTRESET
-
-/* Define if your libraries define getpagesize() */
-#undef HAVE_GETPAGESIZE
-
-/* Define to 1 if you have the `getpeereid' function. */
-#undef HAVE_GETPEEREID
-
-/* Define to 1 if you have the `getpeerucred' function. */
-#undef HAVE_GETPEERUCRED
-
-/* Define to 1 if you have the `getpgid' function. */
-#undef HAVE_GETPGID
-
-/* Define to 1 if you have the `getpgrp' function. */
-#undef HAVE_GETPGRP
-
-/* Define to 1 if you have the `getpwanam' function. */
-#undef HAVE_GETPWANAM
-
-/* Define to 1 if you have the `getrlimit' function. */
-#undef HAVE_GETRLIMIT
-
-/* Define if getrrsetbyname() exists */
-#undef HAVE_GETRRSETBYNAME
-
-/* Define to 1 if you have the `getrusage' function. */
-#undef HAVE_GETRUSAGE
-
-/* Define to 1 if you have the `getseuserbyname' function. */
-#undef HAVE_GETSEUSERBYNAME
-
-/* Define to 1 if you have the `gettimeofday' function. */
-#undef HAVE_GETTIMEOFDAY
-
-/* Define to 1 if you have the `getttyent' function. */
-#undef HAVE_GETTTYENT
-
-/* Define to 1 if you have the `getutent' function. */
-#undef HAVE_GETUTENT
-
-/* Define to 1 if you have the `getutid' function. */
-#undef HAVE_GETUTID
-
-/* Define to 1 if you have the `getutline' function. */
-#undef HAVE_GETUTLINE
-
-/* Define to 1 if you have the `getutxent' function. */
-#undef HAVE_GETUTXENT
-
-/* Define to 1 if you have the `getutxid' function. */
-#undef HAVE_GETUTXID
-
-/* Define to 1 if you have the `getutxline' function. */
-#undef HAVE_GETUTXLINE
-
-/* Define to 1 if you have the `getutxuser' function. */
-#undef HAVE_GETUTXUSER
-
-/* Define to 1 if you have the `get_default_context_with_level' function. */
-#undef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
-
-/* Define to 1 if you have the `glob' function. */
-#undef HAVE_GLOB
-
-/* Define to 1 if you have the <glob.h> header file. */
-#undef HAVE_GLOB_H
-
-/* Define to 1 if you have the `group_from_gid' function. */
-#undef HAVE_GROUP_FROM_GID
-
-/* Define to 1 if you have the <gssapi_generic.h> header file. */
-#undef HAVE_GSSAPI_GENERIC_H
-
-/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
-#undef HAVE_GSSAPI_GSSAPI_GENERIC_H
-
-/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
-#undef HAVE_GSSAPI_GSSAPI_H
-
-/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
-#undef HAVE_GSSAPI_GSSAPI_KRB5_H
-
-/* Define to 1 if you have the <gssapi.h> header file. */
-#undef HAVE_GSSAPI_H
-
-/* Define to 1 if you have the <gssapi_krb5.h> header file. */
-#undef HAVE_GSSAPI_KRB5_H
-
-/* Define if HEADER.ad exists in arpa/nameser.h */
-#undef HAVE_HEADER_AD
-
-/* Define to 1 if you have the `HMAC_CTX_init' function. */
-#undef HAVE_HMAC_CTX_INIT
-
-/* Define if you have ut_host in utmp.h */
-#undef HAVE_HOST_IN_UTMP
-
-/* Define if you have ut_host in utmpx.h */
-#undef HAVE_HOST_IN_UTMPX
-
-/* Define to 1 if you have the <iaf.h> header file. */
-#undef HAVE_IAF_H
-
-/* Define to 1 if you have the <ia.h> header file. */
-#undef HAVE_IA_H
-
-/* Define if you have ut_id in utmp.h */
-#undef HAVE_ID_IN_UTMP
-
-/* Define if you have ut_id in utmpx.h */
-#undef HAVE_ID_IN_UTMPX
-
-/* Define to 1 if you have the `inet_aton' function. */
-#undef HAVE_INET_ATON
-
-/* Define to 1 if you have the `inet_ntoa' function. */
-#undef HAVE_INET_NTOA
-
-/* Define to 1 if you have the `inet_ntop' function. */
-#undef HAVE_INET_NTOP
-
-/* Define to 1 if you have the `innetgr' function. */
-#undef HAVE_INNETGR
-
-/* define if you have int64_t data type */
-#undef HAVE_INT64_T
-
-/* Define to 1 if the system has the type `intmax_t'. */
-#undef HAVE_INTMAX_T
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* define if you have intxx_t data type */
-#undef HAVE_INTXX_T
-
-/* Define to 1 if the system has the type `in_addr_t'. */
-#undef HAVE_IN_ADDR_T
-
-/* Define to 1 if the system has the type `in_port_t'. */
-#undef HAVE_IN_PORT_T
-
-/* Define if you have isblank(3C). */
-#undef HAVE_ISBLANK
-
-/* Define to 1 if you have the `krb5_cc_new_unique' function. */
-#undef HAVE_KRB5_CC_NEW_UNIQUE
-
-/* Define to 1 if you have the `krb5_free_error_message' function. */
-#undef HAVE_KRB5_FREE_ERROR_MESSAGE
-
-/* Define to 1 if you have the `krb5_get_error_message' function. */
-#undef HAVE_KRB5_GET_ERROR_MESSAGE
-
-/* Define to 1 if you have the <lastlog.h> header file. */
-#undef HAVE_LASTLOG_H
-
-/* Define if you want ldns support */
-#undef HAVE_LDNS
-
-/* Define to 1 if you have the <libaudit.h> header file. */
-#undef HAVE_LIBAUDIT_H
-
-/* Define to 1 if you have the `bsm' library (-lbsm). */
-#undef HAVE_LIBBSM
-
-/* Define to 1 if you have the `crypt' library (-lcrypt). */
-#undef HAVE_LIBCRYPT
-
-/* Define to 1 if you have the `dl' library (-ldl). */
-#undef HAVE_LIBDL
-
-/* Define to 1 if you have the <libgen.h> header file. */
-#undef HAVE_LIBGEN_H
-
-/* Define if system has libiaf that supports set_id */
-#undef HAVE_LIBIAF
-
-/* Define to 1 if you have the `network' library (-lnetwork). */
-#undef HAVE_LIBNETWORK
-
-/* Define to 1 if you have the `nsl' library (-lnsl). */
-#undef HAVE_LIBNSL
-
-/* Define to 1 if you have the `pam' library (-lpam). */
-#undef HAVE_LIBPAM
-
-/* Define to 1 if you have the `socket' library (-lsocket). */
-#undef HAVE_LIBSOCKET
-
-/* Define to 1 if you have the <libutil.h> header file. */
-#undef HAVE_LIBUTIL_H
-
-/* Define to 1 if you have the `xnet' library (-lxnet). */
-#undef HAVE_LIBXNET
-
-/* Define to 1 if you have the `z' library (-lz). */
-#undef HAVE_LIBZ
-
-/* Define to 1 if you have the <limits.h> header file. */
-#undef HAVE_LIMITS_H
-
-/* Define to 1 if you have the <linux/audit.h> header file. */
-#undef HAVE_LINUX_AUDIT_H
-
-/* Define to 1 if you have the <linux/filter.h> header file. */
-#undef HAVE_LINUX_FILTER_H
-
-/* Define to 1 if you have the <linux/if_tun.h> header file. */
-#undef HAVE_LINUX_IF_TUN_H
-
-/* Define to 1 if you have the <linux/seccomp.h> header file. */
-#undef HAVE_LINUX_SECCOMP_H
-
-/* Define to 1 if you have the <locale.h> header file. */
-#undef HAVE_LOCALE_H
-
-/* Define to 1 if you have the `login' function. */
-#undef HAVE_LOGIN
-
-/* Define to 1 if you have the <login_cap.h> header file. */
-#undef HAVE_LOGIN_CAP_H
-
-/* Define to 1 if you have the `login_getcapbool' function. */
-#undef HAVE_LOGIN_GETCAPBOOL
-
-/* Define to 1 if you have the <login.h> header file. */
-#undef HAVE_LOGIN_H
-
-/* Define to 1 if you have the `logout' function. */
-#undef HAVE_LOGOUT
-
-/* Define to 1 if you have the `logwtmp' function. */
-#undef HAVE_LOGWTMP
-
-/* Define to 1 if the system has the type `long double'. */
-#undef HAVE_LONG_DOUBLE
-
-/* Define to 1 if the system has the type `long long'. */
-#undef HAVE_LONG_LONG
-
-/* Define to 1 if you have the <maillock.h> header file. */
-#undef HAVE_MAILLOCK_H
-
-/* Define to 1 if you have the `mblen' function. */
-#undef HAVE_MBLEN
-
-/* Define to 1 if you have the `md5_crypt' function. */
-#undef HAVE_MD5_CRYPT
-
-/* Define if you want to allow MD5 passwords */
-#undef HAVE_MD5_PASSWORDS
-
-/* Define to 1 if you have the `memmove' function. */
-#undef HAVE_MEMMOVE
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if you have the `memset_s' function. */
-#undef HAVE_MEMSET_S
-
-/* Define to 1 if you have the `mkdtemp' function. */
-#undef HAVE_MKDTEMP
-
-/* Define to 1 if you have the `mmap' function. */
-#undef HAVE_MMAP
-
-/* define if you have mode_t data type */
-#undef HAVE_MODE_T
-
-/* Some systems put nanosleep outside of libc */
-#undef HAVE_NANOSLEEP
-
-/* Define to 1 if you have the <ndir.h> header file. */
-#undef HAVE_NDIR_H
-
-/* Define to 1 if you have the <netdb.h> header file. */
-#undef HAVE_NETDB_H
-
-/* Define to 1 if you have the <netgroup.h> header file. */
-#undef HAVE_NETGROUP_H
-
-/* Define to 1 if you have the <net/if_tun.h> header file. */
-#undef HAVE_NET_IF_TUN_H
-
-/* Define if you are on NeXT */
-#undef HAVE_NEXT
-
-/* Define to 1 if you have the `ngetaddrinfo' function. */
-#undef HAVE_NGETADDRINFO
-
-/* Define to 1 if you have the `nsleep' function. */
-#undef HAVE_NSLEEP
-
-/* Define to 1 if you have the `ogetaddrinfo' function. */
-#undef HAVE_OGETADDRINFO
-
-/* Define if you have an old version of PAM which takes only one argument to
- pam_strerror */
-#undef HAVE_OLD_PAM
-
-/* Define to 1 if you have the `openlog_r' function. */
-#undef HAVE_OPENLOG_R
-
-/* Define to 1 if you have the `openpty' function. */
-#undef HAVE_OPENPTY
-
-/* Define if your ssl headers are included with #include <openssl/header.h> */
-#undef HAVE_OPENSSL
-
-/* Define if you have Digital Unix Security Integration Architecture */
-#undef HAVE_OSF_SIA
-
-/* Define to 1 if you have the `pam_getenvlist' function. */
-#undef HAVE_PAM_GETENVLIST
-
-/* Define to 1 if you have the <pam/pam_appl.h> header file. */
-#undef HAVE_PAM_PAM_APPL_H
-
-/* Define to 1 if you have the `pam_putenv' function. */
-#undef HAVE_PAM_PUTENV
-
-/* Define to 1 if you have the <paths.h> header file. */
-#undef HAVE_PATHS_H
-
-/* Define if you have ut_pid in utmp.h */
-#undef HAVE_PID_IN_UTMP
-
-/* define if you have pid_t data type */
-#undef HAVE_PID_T
-
-/* Define to 1 if you have the `poll' function. */
-#undef HAVE_POLL
-
-/* Define to 1 if you have the <poll.h> header file. */
-#undef HAVE_POLL_H
-
-/* Define to 1 if you have the `prctl' function. */
-#undef HAVE_PRCTL
-
-/* Define if you have /proc/$pid/fd */
-#undef HAVE_PROC_PID
-
-/* Define to 1 if you have the `pstat' function. */
-#undef HAVE_PSTAT
-
-/* Define to 1 if you have the <pty.h> header file. */
-#undef HAVE_PTY_H
-
-/* Define to 1 if you have the `pututline' function. */
-#undef HAVE_PUTUTLINE
-
-/* Define to 1 if you have the `pututxline' function. */
-#undef HAVE_PUTUTXLINE
-
-/* Define to 1 if you have the `readpassphrase' function. */
-#undef HAVE_READPASSPHRASE
-
-/* Define to 1 if you have the <readpassphrase.h> header file. */
-#undef HAVE_READPASSPHRASE_H
-
-/* Define to 1 if you have the `reallocarray' function. */
-#undef HAVE_REALLOCARRAY
-
-/* Define to 1 if you have the `realpath' function. */
-#undef HAVE_REALPATH
-
-/* Define to 1 if you have the `recvmsg' function. */
-#undef HAVE_RECVMSG
-
-/* sys/resource.h has RLIMIT_NPROC */
-#undef HAVE_RLIMIT_NPROC
-
-/* Define to 1 if you have the <rpc/types.h> header file. */
-#undef HAVE_RPC_TYPES_H
-
-/* Define to 1 if you have the `rresvport_af' function. */
-#undef HAVE_RRESVPORT_AF
-
-/* Define to 1 if you have the `RSA_generate_key_ex' function. */
-#undef HAVE_RSA_GENERATE_KEY_EX
-
-/* Define to 1 if you have the `RSA_get_default_method' function. */
-#undef HAVE_RSA_GET_DEFAULT_METHOD
-
-/* Define to 1 if you have the <sandbox.h> header file. */
-#undef HAVE_SANDBOX_H
-
-/* Define to 1 if you have the `sandbox_init' function. */
-#undef HAVE_SANDBOX_INIT
-
-/* define if you have sa_family_t data type */
-#undef HAVE_SA_FAMILY_T
-
-/* Define to 1 if you have the `scan_scaled' function. */
-#undef HAVE_SCAN_SCALED
-
-/* Define if you have SecureWare-based protected password database */
-#undef HAVE_SECUREWARE
-
-/* Define to 1 if you have the <security/pam_appl.h> header file. */
-#undef HAVE_SECURITY_PAM_APPL_H
-
-/* Define to 1 if you have the `sendmsg' function. */
-#undef HAVE_SENDMSG
-
-/* Define to 1 if you have the `setauthdb' function. */
-#undef HAVE_SETAUTHDB
-
-/* Define to 1 if you have the `setdtablesize' function. */
-#undef HAVE_SETDTABLESIZE
-
-/* Define to 1 if you have the `setegid' function. */
-#undef HAVE_SETEGID
-
-/* Define to 1 if you have the `setenv' function. */
-#undef HAVE_SETENV
-
-/* Define to 1 if you have the `seteuid' function. */
-#undef HAVE_SETEUID
-
-/* Define to 1 if you have the `setgroupent' function. */
-#undef HAVE_SETGROUPENT
-
-/* Define to 1 if you have the `setgroups' function. */
-#undef HAVE_SETGROUPS
-
-/* Define to 1 if you have the `setlinebuf' function. */
-#undef HAVE_SETLINEBUF
-
-/* Define to 1 if you have the `setlogin' function. */
-#undef HAVE_SETLOGIN
-
-/* Define to 1 if you have the `setluid' function. */
-#undef HAVE_SETLUID
-
-/* Define to 1 if you have the `setpassent' function. */
-#undef HAVE_SETPASSENT
-
-/* Define to 1 if you have the `setpcred' function. */
-#undef HAVE_SETPCRED
-
-/* Define to 1 if you have the `setproctitle' function. */
-#undef HAVE_SETPROCTITLE
-
-/* Define to 1 if you have the `setregid' function. */
-#undef HAVE_SETREGID
-
-/* Define to 1 if you have the `setresgid' function. */
-#undef HAVE_SETRESGID
-
-/* Define to 1 if you have the `setresuid' function. */
-#undef HAVE_SETRESUID
-
-/* Define to 1 if you have the `setreuid' function. */
-#undef HAVE_SETREUID
-
-/* Define to 1 if you have the `setrlimit' function. */
-#undef HAVE_SETRLIMIT
-
-/* Define to 1 if you have the `setsid' function. */
-#undef HAVE_SETSID
-
-/* Define to 1 if you have the `setutent' function. */
-#undef HAVE_SETUTENT
-
-/* Define to 1 if you have the `setutxdb' function. */
-#undef HAVE_SETUTXDB
-
-/* Define to 1 if you have the `setutxent' function. */
-#undef HAVE_SETUTXENT
-
-/* Define to 1 if you have the `setvbuf' function. */
-#undef HAVE_SETVBUF
-
-/* Define to 1 if you have the `set_id' function. */
-#undef HAVE_SET_ID
-
-/* Define to 1 if you have the `SHA256_Update' function. */
-#undef HAVE_SHA256_UPDATE
-
-/* Define to 1 if you have the <sha2.h> header file. */
-#undef HAVE_SHA2_H
-
-/* Define to 1 if you have the <shadow.h> header file. */
-#undef HAVE_SHADOW_H
-
-/* Define to 1 if you have the `sigaction' function. */
-#undef HAVE_SIGACTION
-
-/* Define to 1 if you have the `sigvec' function. */
-#undef HAVE_SIGVEC
-
-/* Define to 1 if the system has the type `sig_atomic_t'. */
-#undef HAVE_SIG_ATOMIC_T
-
-/* define if you have size_t data type */
-#undef HAVE_SIZE_T
-
-/* Define to 1 if you have the `snprintf' function. */
-#undef HAVE_SNPRINTF
-
-/* Define to 1 if you have the `socketpair' function. */
-#undef HAVE_SOCKETPAIR
-
-/* Have PEERCRED socket option */
-#undef HAVE_SO_PEERCRED
-
-/* define if you have ssize_t data type */
-#undef HAVE_SSIZE_T
-
-/* Fields in struct sockaddr_storage */
-#undef HAVE_SS_FAMILY_IN_SS
-
-/* Define to 1 if you have the `statfs' function. */
-#undef HAVE_STATFS
-
-/* Define to 1 if you have the `statvfs' function. */
-#undef HAVE_STATVFS
-
-/* Define to 1 if you have the <stddef.h> header file. */
-#undef HAVE_STDDEF_H
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the `strdup' function. */
-#undef HAVE_STRDUP
-
-/* Define to 1 if you have the `strerror' function. */
-#undef HAVE_STRERROR
-
-/* Define to 1 if you have the `strftime' function. */
-#undef HAVE_STRFTIME
-
-/* Silly mkstemp() */
-#undef HAVE_STRICT_MKSTEMP
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the `strlcat' function. */
-#undef HAVE_STRLCAT
-
-/* Define to 1 if you have the `strlcpy' function. */
-#undef HAVE_STRLCPY
-
-/* Define to 1 if you have the `strmode' function. */
-#undef HAVE_STRMODE
-
-/* Define to 1 if you have the `strnlen' function. */
-#undef HAVE_STRNLEN
-
-/* Define to 1 if you have the `strnvis' function. */
-#undef HAVE_STRNVIS
-
-/* Define to 1 if you have the `strptime' function. */
-#undef HAVE_STRPTIME
-
-/* Define to 1 if you have the `strsep' function. */
-#undef HAVE_STRSEP
-
-/* Define to 1 if you have the `strtoll' function. */
-#undef HAVE_STRTOLL
-
-/* Define to 1 if you have the `strtonum' function. */
-#undef HAVE_STRTONUM
-
-/* Define to 1 if you have the `strtoul' function. */
-#undef HAVE_STRTOUL
-
-/* Define to 1 if you have the `strtoull' function. */
-#undef HAVE_STRTOULL
-
-/* define if you have struct addrinfo data type */
-#undef HAVE_STRUCT_ADDRINFO
-
-/* define if you have struct in6_addr data type */
-#undef HAVE_STRUCT_IN6_ADDR
-
-/* Define to 1 if `pw_change' is member of `struct passwd'. */
-#undef HAVE_STRUCT_PASSWD_PW_CHANGE
-
-/* Define to 1 if `pw_class' is member of `struct passwd'. */
-#undef HAVE_STRUCT_PASSWD_PW_CLASS
-
-/* Define to 1 if `pw_expire' is member of `struct passwd'. */
-#undef HAVE_STRUCT_PASSWD_PW_EXPIRE
-
-/* Define to 1 if `pw_gecos' is member of `struct passwd'. */
-#undef HAVE_STRUCT_PASSWD_PW_GECOS
-
-/* define if you have struct sockaddr_in6 data type */
-#undef HAVE_STRUCT_SOCKADDR_IN6
-
-/* Define to 1 if `sin6_scope_id' is member of `struct sockaddr_in6'. */
-#undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
-
-/* define if you have struct sockaddr_storage data type */
-#undef HAVE_STRUCT_SOCKADDR_STORAGE
-
-/* Define to 1 if `st_blksize' is member of `struct stat'. */
-#undef HAVE_STRUCT_STAT_ST_BLKSIZE
-
-/* Define to 1 if the system has the type `struct timespec'. */
-#undef HAVE_STRUCT_TIMESPEC
-
-/* define if you have struct timeval */
-#undef HAVE_STRUCT_TIMEVAL
-
-/* Define to 1 if you have the `swap32' function. */
-#undef HAVE_SWAP32
-
-/* Define to 1 if you have the `sysconf' function. */
-#undef HAVE_SYSCONF
-
-/* Define if you have syslen in utmpx.h */
-#undef HAVE_SYSLEN_IN_UTMPX
-
-/* Define to 1 if you have the <sys/audit.h> header file. */
-#undef HAVE_SYS_AUDIT_H
-
-/* Define to 1 if you have the <sys/bitypes.h> header file. */
-#undef HAVE_SYS_BITYPES_H
-
-/* Define to 1 if you have the <sys/bsdtty.h> header file. */
-#undef HAVE_SYS_BSDTTY_H
-
-/* Define to 1 if you have the <sys/capability.h> header file. */
-#undef HAVE_SYS_CAPABILITY_H
-
-/* Define to 1 if you have the <sys/cdefs.h> header file. */
-#undef HAVE_SYS_CDEFS_H
-
-/* Define to 1 if you have the <sys/dir.h> header file. */
-#undef HAVE_SYS_DIR_H
-
-/* Define if your system defines sys_errlist[] */
-#undef HAVE_SYS_ERRLIST
-
-/* Define to 1 if you have the <sys/mman.h> header file. */
-#undef HAVE_SYS_MMAN_H
-
-/* Define to 1 if you have the <sys/mount.h> header file. */
-#undef HAVE_SYS_MOUNT_H
-
-/* Define to 1 if you have the <sys/ndir.h> header file. */
-#undef HAVE_SYS_NDIR_H
-
-/* Define if your system defines sys_nerr */
-#undef HAVE_SYS_NERR
-
-/* Define to 1 if you have the <sys/poll.h> header file. */
-#undef HAVE_SYS_POLL_H
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-#undef HAVE_SYS_PRCTL_H
-
-/* Define to 1 if you have the <sys/pstat.h> header file. */
-#undef HAVE_SYS_PSTAT_H
-
-/* Define to 1 if you have the <sys/ptms.h> header file. */
-#undef HAVE_SYS_PTMS_H
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-#undef HAVE_SYS_SELECT_H
-
-/* Define to 1 if you have the <sys/statvfs.h> header file. */
-#undef HAVE_SYS_STATVFS_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/stream.h> header file. */
-#undef HAVE_SYS_STREAM_H
-
-/* Define to 1 if you have the <sys/stropts.h> header file. */
-#undef HAVE_SYS_STROPTS_H
-
-/* Define to 1 if you have the <sys/strtio.h> header file. */
-#undef HAVE_SYS_STRTIO_H
-
-/* Force use of sys/syslog.h on Ultrix */
-#undef HAVE_SYS_SYSLOG_H
-
-/* Define to 1 if you have the <sys/sysmacros.h> header file. */
-#undef HAVE_SYS_SYSMACROS_H
-
-/* Define to 1 if you have the <sys/timers.h> header file. */
-#undef HAVE_SYS_TIMERS_H
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#undef HAVE_SYS_TIME_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <sys/un.h> header file. */
-#undef HAVE_SYS_UN_H
-
-/* Define to 1 if you have the `tcgetpgrp' function. */
-#undef HAVE_TCGETPGRP
-
-/* Define to 1 if you have the `tcsendbreak' function. */
-#undef HAVE_TCSENDBREAK
-
-/* Define to 1 if you have the `time' function. */
-#undef HAVE_TIME
-
-/* Define to 1 if you have the <time.h> header file. */
-#undef HAVE_TIME_H
-
-/* Define if you have ut_time in utmp.h */
-#undef HAVE_TIME_IN_UTMP
-
-/* Define if you have ut_time in utmpx.h */
-#undef HAVE_TIME_IN_UTMPX
-
-/* Define to 1 if you have the `timingsafe_bcmp' function. */
-#undef HAVE_TIMINGSAFE_BCMP
-
-/* Define to 1 if you have the <tmpdir.h> header file. */
-#undef HAVE_TMPDIR_H
-
-/* Define to 1 if you have the `truncate' function. */
-#undef HAVE_TRUNCATE
-
-/* Define to 1 if you have the <ttyent.h> header file. */
-#undef HAVE_TTYENT_H
-
-/* Define if you have ut_tv in utmp.h */
-#undef HAVE_TV_IN_UTMP
-
-/* Define if you have ut_tv in utmpx.h */
-#undef HAVE_TV_IN_UTMPX
-
-/* Define if you have ut_type in utmp.h */
-#undef HAVE_TYPE_IN_UTMP
-
-/* Define if you have ut_type in utmpx.h */
-#undef HAVE_TYPE_IN_UTMPX
-
-/* Define to 1 if you have the <ucred.h> header file. */
-#undef HAVE_UCRED_H
-
-/* Define to 1 if the system has the type `uintmax_t'. */
-#undef HAVE_UINTMAX_T
-
-/* define if you have uintxx_t data type */
-#undef HAVE_UINTXX_T
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if you have the `unsetenv' function. */
-#undef HAVE_UNSETENV
-
-/* Define to 1 if the system has the type `unsigned long long'. */
-#undef HAVE_UNSIGNED_LONG_LONG
-
-/* Define to 1 if you have the `updwtmp' function. */
-#undef HAVE_UPDWTMP
-
-/* Define to 1 if you have the `updwtmpx' function. */
-#undef HAVE_UPDWTMPX
-
-/* Define to 1 if you have the <usersec.h> header file. */
-#undef HAVE_USERSEC_H
-
-/* Define to 1 if you have the `user_from_uid' function. */
-#undef HAVE_USER_FROM_UID
-
-/* Define to 1 if you have the `usleep' function. */
-#undef HAVE_USLEEP
-
-/* Define to 1 if you have the <util.h> header file. */
-#undef HAVE_UTIL_H
-
-/* Define to 1 if you have the `utimes' function. */
-#undef HAVE_UTIMES
-
-/* Define to 1 if you have the <utime.h> header file. */
-#undef HAVE_UTIME_H
-
-/* Define to 1 if you have the `utmpname' function. */
-#undef HAVE_UTMPNAME
-
-/* Define to 1 if you have the `utmpxname' function. */
-#undef HAVE_UTMPXNAME
-
-/* Define to 1 if you have the <utmpx.h> header file. */
-#undef HAVE_UTMPX_H
-
-/* Define to 1 if you have the <utmp.h> header file. */
-#undef HAVE_UTMP_H
-
-/* define if you have u_char data type */
-#undef HAVE_U_CHAR
-
-/* define if you have u_int data type */
-#undef HAVE_U_INT
-
-/* define if you have u_int64_t data type */
-#undef HAVE_U_INT64_T
-
-/* define if you have u_intxx_t data type */
-#undef HAVE_U_INTXX_T
-
-/* Define to 1 if you have the `vasprintf' function. */
-#undef HAVE_VASPRINTF
-
-/* Define if va_copy exists */
-#undef HAVE_VA_COPY
-
-/* Define to 1 if you have the <vis.h> header file. */
-#undef HAVE_VIS_H
-
-/* Define to 1 if you have the `vsnprintf' function. */
-#undef HAVE_VSNPRINTF
-
-/* Define to 1 if you have the `waitpid' function. */
-#undef HAVE_WAITPID
-
-/* Define to 1 if you have the `_getlong' function. */
-#undef HAVE__GETLONG
-
-/* Define to 1 if you have the `_getpty' function. */
-#undef HAVE__GETPTY
-
-/* Define to 1 if you have the `_getshort' function. */
-#undef HAVE__GETSHORT
-
-/* Define if you have struct __res_state _res as an extern */
-#undef HAVE__RES_EXTERN
-
-/* Define to 1 if you have the `__b64_ntop' function. */
-#undef HAVE___B64_NTOP
-
-/* Define to 1 if you have the `__b64_pton' function. */
-#undef HAVE___B64_PTON
-
-/* Define if compiler implements __FUNCTION__ */
-#undef HAVE___FUNCTION__
-
-/* Define if libc defines __progname */
-#undef HAVE___PROGNAME
-
-/* Fields in struct sockaddr_storage */
-#undef HAVE___SS_FAMILY_IN_SS
-
-/* Define if __va_copy exists */
-#undef HAVE___VA_COPY
-
-/* Define if compiler implements __func__ */
-#undef HAVE___func__
-
-/* Define this if you are using the Heimdal version of Kerberos V5 */
-#undef HEIMDAL
-
-/* Define if you need to use IP address instead of hostname in $DISPLAY */
-#undef IPADDR_IN_DISPLAY
-
-/* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */
-#undef IPV4_IN_IPV6
-
-/* Define if your system choked on IP TOS setting */
-#undef IP_TOS_IS_BROKEN
-
-/* Define if you want Kerberos 5 support */
-#undef KRB5
-
-/* Define if pututxline updates lastlog too */
-#undef LASTLOG_WRITE_PUTUTXLINE
-
-/* Define to whatever link() returns for "not supported" if it doesn't return
- EOPNOTSUPP. */
-#undef LINK_OPNOTSUPP_ERRNO
-
-/* Adjust Linux out-of-memory killer */
-#undef LINUX_OOM_ADJUST
-
-/* max value of long long calculated by configure */
-#undef LLONG_MAX
-
-/* min value of long long calculated by configure */
-#undef LLONG_MIN
-
-/* Account locked with pw(1) */
-#undef LOCKED_PASSWD_PREFIX
-
-/* String used in /etc/passwd to denote locked account */
-#undef LOCKED_PASSWD_STRING
-
-/* String used in /etc/passwd to denote locked account */
-#undef LOCKED_PASSWD_SUBSTR
-
-/* Some versions of /bin/login need the TERM supplied on the commandline */
-#undef LOGIN_NEEDS_TERM
-
-/* Some systems need a utmpx entry for /bin/login to work */
-#undef LOGIN_NEEDS_UTMPX
-
-/* Define if your login program cannot handle end of options ("--") */
-#undef LOGIN_NO_ENDOPT
-
-/* If your header files don't define LOGIN_PROGRAM, then use this (detected)
- from environment and PATH */
-#undef LOGIN_PROGRAM_FALLBACK
-
-/* Set this to your mail directory if you do not have _PATH_MAILDIR */
-#undef MAIL_DIRECTORY
-
-/* Need setpgrp to acquire controlling tty */
-#undef NEED_SETPGRP
-
-/* compiler does not accept __attribute__ on return types */
-#undef NO_ATTRIBUTE_ON_RETURN_TYPE
-
-/* Define if the concept of ports only accessible to superusers isn't known */
-#undef NO_IPPORT_RESERVED_CONCEPT
-
-/* Define if you don't want to use lastlog in session.c */
-#undef NO_SSH_LASTLOG
-
-/* Define if X11 doesn't support AF_UNIX sockets on that system */
-#undef NO_X11_UNIX_SOCKETS
-
-/* Define if EVP_DigestUpdate returns void */
-#undef OPENSSL_EVP_DIGESTUPDATE_VOID
-
-/* OpenSSL has ECC */
-#undef OPENSSL_HAS_ECC
-
-/* libcrypto has NID_X9_62_prime256v1 */
-#undef OPENSSL_HAS_NISTP256
-
-/* libcrypto has NID_secp384r1 */
-#undef OPENSSL_HAS_NISTP384
-
-/* libcrypto has NID_secp521r1 */
-#undef OPENSSL_HAS_NISTP521
-
-/* libcrypto has EVP AES CTR */
-#undef OPENSSL_HAVE_EVPCTR
-
-/* libcrypto has EVP AES GCM */
-#undef OPENSSL_HAVE_EVPGCM
-
-/* libcrypto is missing AES 192 and 256 bit functions */
-#undef OPENSSL_LOBOTOMISED_AES
-
-/* Define if you want the OpenSSL internally seeded PRNG only */
-#undef OPENSSL_PRNG_ONLY
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* Define if you are using Solaris-derived PAM which passes pam_messages to
- the conversation function with an extra level of indirection */
-#undef PAM_SUN_CODEBASE
-
-/* Work around problematic Linux PAM modules handling of PAM_TTY */
-#undef PAM_TTY_KLUDGE
-
-/* must supply username to passwd */
-#undef PASSWD_NEEDS_USERNAME
-
-/* System dirs owned by bin (uid 2) */
-#undef PLATFORM_SYS_DIR_UID
-
-/* Port number of PRNGD/EGD random number socket */
-#undef PRNGD_PORT
-
-/* Location of PRNGD/EGD random number socket */
-#undef PRNGD_SOCKET
-
-/* read(1) can return 0 for a non-closed fd */
-#undef PTY_ZEROREAD
-
-/* Sandbox using capsicum */
-#undef SANDBOX_CAPSICUM
-
-/* Sandbox using Darwin sandbox_init(3) */
-#undef SANDBOX_DARWIN
-
-/* no privsep sandboxing */
-#undef SANDBOX_NULL
-
-/* Sandbox using setrlimit(2) */
-#undef SANDBOX_RLIMIT
-
-/* Sandbox using seccomp filter */
-#undef SANDBOX_SECCOMP_FILTER
-
-/* setrlimit RLIMIT_FSIZE works */
-#undef SANDBOX_SKIP_RLIMIT_FSIZE
-
-/* define if setrlimit RLIMIT_NOFILE breaks things */
-#undef SANDBOX_SKIP_RLIMIT_NOFILE
-
-/* Sandbox using systrace(4) */
-#undef SANDBOX_SYSTRACE
-
-/* Specify the system call convention in use */
-#undef SECCOMP_AUDIT_ARCH
-
-/* Define if your platform breaks doing a seteuid before a setuid */
-#undef SETEUID_BREAKS_SETUID
-
-/* The size of `int', as computed by sizeof. */
-#undef SIZEOF_INT
-
-/* The size of `long int', as computed by sizeof. */
-#undef SIZEOF_LONG_INT
-
-/* The size of `long long int', as computed by sizeof. */
-#undef SIZEOF_LONG_LONG_INT
-
-/* The size of `short int', as computed by sizeof. */
-#undef SIZEOF_SHORT_INT
-
-/* Define if you want S/Key support */
-#undef SKEY
-
-/* Define if your skeychallenge() function takes 4 arguments (NetBSD) */
-#undef SKEYCHALLENGE_4ARG
-
-/* Define as const if snprintf() can declare const char *fmt */
-#undef SNPRINTF_CONST
-
-/* Define to a Set Process Title type if your system is supported by
- bsd-setproctitle.c */
-#undef SPT_TYPE
-
-/* Define if sshd somehow reacquires a controlling TTY after setsid() */
-#undef SSHD_ACQUIRES_CTTY
-
-/* Define if pam_chauthtok wants real uid set to the unpriv'ed user */
-#undef SSHPAM_CHAUTHTOK_NEEDS_RUID
-
-/* Use audit debugging module */
-#undef SSH_AUDIT_EVENTS
-
-/* Windows is sensitive to read buffer size */
-#undef SSH_IOBUFSZ
-
-/* non-privileged user for privilege separation */
-#undef SSH_PRIVSEP_USER
-
-/* Use tunnel device compatibility to OpenBSD */
-#undef SSH_TUN_COMPAT_AF
-
-/* Open tunnel devices the FreeBSD way */
-#undef SSH_TUN_FREEBSD
-
-/* Open tunnel devices the Linux tun/tap way */
-#undef SSH_TUN_LINUX
-
-/* No layer 2 tunnel support */
-#undef SSH_TUN_NO_L2
-
-/* Open tunnel devices the OpenBSD way */
-#undef SSH_TUN_OPENBSD
-
-/* Prepend the address family to IP tunnel traffic */
-#undef SSH_TUN_PREPEND_AF
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* Define if you want a different $PATH for the superuser */
-#undef SUPERUSER_PATH
-
-/* syslog_r function is safe to use in in a signal handler */
-#undef SYSLOG_R_SAFE_IN_SIGHAND
-
-/* Support passwords > 8 chars */
-#undef UNIXWARE_LONG_PASSWORDS
-
-/* Specify default $PATH */
-#undef USER_PATH
-
-/* Define this if you want to use libkafs' AFS support */
-#undef USE_AFS
-
-/* Use BSM audit module */
-#undef USE_BSM_AUDIT
-
-/* Use btmp to log bad logins */
-#undef USE_BTMP
-
-/* Use libedit for sftp */
-#undef USE_LIBEDIT
-
-/* Use Linux audit module */
-#undef USE_LINUX_AUDIT
-
-/* Enable OpenSSL engine support */
-#undef USE_OPENSSL_ENGINE
-
-/* Define if you want to enable PAM support */
-#undef USE_PAM
-
-/* Use PIPES instead of a socketpair() */
-#undef USE_PIPES
-
-/* Define if you have Solaris process contracts */
-#undef USE_SOLARIS_PROCESS_CONTRACTS
-
-/* Define if you have Solaris projects */
-#undef USE_SOLARIS_PROJECTS
-
-/* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */
-#undef WITH_ABBREV_NO_TTY
-
-/* Define if you want to enable AIX4's authenticate function */
-#undef WITH_AIXAUTHENTICATE
-
-/* Define if you have/want arrays (cluster-wide session managment, not C
- arrays) */
-#undef WITH_IRIX_ARRAY
-
-/* Define if you want IRIX audit trails */
-#undef WITH_IRIX_AUDIT
-
-/* Define if you want IRIX kernel jobs */
-#undef WITH_IRIX_JOBS
-
-/* Define if you want IRIX project management */
-#undef WITH_IRIX_PROJECT
-
-/* use libcrypto for cryptography */
-#undef WITH_OPENSSL
-
-/* Define if you want SELinux support. */
-#undef WITH_SELINUX
-
-/* include SSH protocol version 1 support */
-#undef WITH_SSH1
-
-/* Define to 1 if your processor stores words with the most significant byte
- first (like Motorola and SPARC, unlike Intel and VAX). */
-#undef WORDS_BIGENDIAN
-
-/* Define if xauth is found in your path */
-#undef XAUTH_PATH
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-#undef _FILE_OFFSET_BITS
-
-/* Define for large files, on AIX-style hosts. */
-#undef _LARGE_FILES
-
-/* log for bad login attempts */
-#undef _PATH_BTMP
-
-/* Full path of your "passwd" program */
-#undef _PATH_PASSWD_PROG
-
-/* Specify location of ssh.pid */
-#undef _PATH_SSH_PIDDIR
-
-/* Define if we don't have struct __res_state in resolv.h */
-#undef __res_state
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-#undef inline
-#endif
-
-/* type to use in place of socklen_t if not defined */
-#undef socklen_t
diff --git a/config.sub b/config.sub
index eee8dccb..973a2980 100755
--- a/config.sub
+++ b/config.sub
@@ -1,36 +1,31 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012, 2013 Free Software Foundation, Inc.
+# Copyright 1992-2020 Free Software Foundation, Inc.
-timestamp='2012-12-23'
+timestamp='2020-05-04'
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine. It does not imply ALL GNU software can.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted GNU ChangeLog entry.
+# Please send patches to <config-patches@gnu.org>.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
@@ -38,7 +33,7 @@ timestamp='2012-12-23'
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
@@ -58,12 +53,11 @@ timestamp='2012-12-23'
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS
- $0 [OPTION] ALIAS
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
-Operation modes:
+Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
@@ -73,9 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
-2012, 2013 Free Software Foundation, Inc.
+Copyright 1992-2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -97,12 +89,12 @@ while test $# -gt 0 ; do
- ) # Use stdin as input.
break ;;
-* )
- echo "$me: invalid option $1$help"
+ echo "$me: invalid option $1$help" >&2
exit 1 ;;
*local*)
# First pass through any local machine types.
- echo $1
+ echo "$1"
exit ;;
* )
@@ -118,1207 +110,1164 @@ case $# in
exit 1;;
esac
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
- nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
- linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
- knetbsd*-gnu* | netbsd*-gnu* | \
- kopensolaris*-gnu* | \
- storm-chaos* | os2-emx* | rtmk-nova*)
- os=-$maybe_os
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
- ;;
- android-linux)
- os=-linux-android
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
- ;;
- *)
- basic_machine=`echo $1 | sed 's/-[^-]*$//'`
- if [ $basic_machine != $1 ]
- then os=`echo $1 | sed 's/.*-/-/'`
- else os=; fi
- ;;
-esac
+# Split fields of configuration type
+# shellcheck disable=SC2162
+IFS="-" read field1 field2 field3 field4 <<EOF
+$1
+EOF
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work. We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
- -sun*os*)
- # Prevent following clause from handling this invalid input.
- ;;
- -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
- -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
- -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
- -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
- -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
- -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray | -microblaze*)
- os=
- basic_machine=$1
- ;;
- -bluegene*)
- os=-cnk
- ;;
- -sim | -cisco | -oki | -wec | -winbond)
- os=
- basic_machine=$1
- ;;
- -scout)
- ;;
- -wrs)
- os=-vxworks
- basic_machine=$1
- ;;
- -chorusos*)
- os=-chorusos
- basic_machine=$1
- ;;
- -chorusrdb)
- os=-chorusrdb
- basic_machine=$1
- ;;
- -hiux*)
- os=-hiuxwe2
- ;;
- -sco6)
- os=-sco5v6
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5)
- os=-sco3.2v5
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco4)
- os=-sco3.2v4
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2.[4-9]*)
- os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2v[4-9]*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5v6*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco*)
- os=-sco3.2v2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -udk*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -isc)
- os=-isc2.2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -clix*)
- basic_machine=clipper-intergraph
- ;;
- -isc*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -lynx*178)
- os=-lynxos178
- ;;
- -lynx*5)
- os=-lynxos5
- ;;
- -lynx*)
- os=-lynxos
+# Separate into logical components for further validation
+case $1 in
+ *-*-*-*-*)
+ echo Invalid configuration \`"$1"\': more than four components >&2
+ exit 1
;;
- -ptx*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ *-*-*-*)
+ basic_machine=$field1-$field2
+ os=$field3-$field4
;;
- -windowsnt*)
- os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ *-*-*)
+ # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
+ # parts
+ maybe_os=$field2-$field3
+ case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \
+ | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \
+ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+ | storm-chaos* | os2-emx* | rtmk-nova*)
+ basic_machine=$field1
+ os=$maybe_os
+ ;;
+ android-linux)
+ basic_machine=$field1-unknown
+ os=linux-android
+ ;;
+ *)
+ basic_machine=$field1-$field2
+ os=$field3
+ ;;
+ esac
;;
- -psos*)
- os=-psos
+ *-*)
+ # A lone config we happen to match not fitting any pattern
+ case $field1-$field2 in
+ decstation-3100)
+ basic_machine=mips-dec
+ os=
+ ;;
+ *-*)
+ # Second component is usually, but not always the OS
+ case $field2 in
+ # Prevent following clause from handling this valid os
+ sun*os*)
+ basic_machine=$field1
+ os=$field2
+ ;;
+ # Manufacturers
+ dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
+ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
+ | unicom* | ibm* | next | hp | isi* | apollo | altos* \
+ | convergent* | ncr* | news | 32* | 3600* | 3100* \
+ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
+ | ultra | tti* | harris | dolphin | highlevel | gould \
+ | cbm | ns | masscomp | apple | axis | knuth | cray \
+ | microblaze* | sim | cisco \
+ | oki | wec | wrs | winbond)
+ basic_machine=$field1-$field2
+ os=
+ ;;
+ *)
+ basic_machine=$field1
+ os=$field2
+ ;;
+ esac
+ ;;
+ esac
;;
- -mint | -mint[0-9]*)
- basic_machine=m68k-atari
- os=-mint
+ *)
+ # Convert single-component short-hands not valid as part of
+ # multi-component configurations.
+ case $field1 in
+ 386bsd)
+ basic_machine=i386-pc
+ os=bsd
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=scout
+ ;;
+ alliant)
+ basic_machine=fx80-alliant
+ os=
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ os=
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=sysv
+ ;;
+ amiga)
+ basic_machine=m68k-unknown
+ os=
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=linux
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=bsd
+ ;;
+ cray)
+ basic_machine=j90-cray
+ os=unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ os=
+ ;;
+ da30)
+ basic_machine=m68k-da30
+ os=
+ ;;
+ decstation | pmax | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ os=
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=msdosdjgpp
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=ebmon
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=ose
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=go32
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=sysv3
+ ;;
+ hp300 | hp300hpux)
+ basic_machine=m68k-hp
+ os=hpux
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=bsd
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=proelf
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=mach
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=linux
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=sysv
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ os=mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=mingw32ce
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=msdos
+ ;;
+ msys)
+ basic_machine=i686-pc
+ os=msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ os=nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-pc
+ os=netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=sysv
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=nonstopux
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=os68k
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=linux
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ os=rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=coff
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=udi
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ os=
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=sysv2
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ os=
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ os=
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=sunos4
+ ;;
+ sun3)
+ basic_machine=m68k-sun
+ os=
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=sunos4
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ os=
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=solaris2
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ os=
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=unicos
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=tops20
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=vms
+ ;;
+ vsta)
+ basic_machine=i386-pc
+ os=vsta
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=vxworks
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=mingw32
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=unicos
+ ;;
+ *)
+ basic_machine=$1
+ os=
+ ;;
+ esac
;;
esac
-# Decode aliases for certain CPU-COMPANY combinations.
+# Decode 1-component or ad-hoc basic machines
case $basic_machine in
- # Recognize the basic CPU types without company name.
- # Some are omitted here because they have special meanings below.
- 1750a | 580 \
- | a29k \
- | aarch64 | aarch64_be \
- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
- | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
- | am33_2.0 \
- | arc \
- | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
- | avr | avr32 \
- | be32 | be64 \
- | bfin \
- | c4x | clipper \
- | d10v | d30v | dlx | dsp16xx \
- | epiphany \
- | fido | fr30 | frv \
- | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
- | hexagon \
- | i370 | i860 | i960 | ia64 \
- | ip2k | iq2000 \
- | le32 | le64 \
- | lm32 \
- | m32c | m32r | m32rle | m68000 | m68k | m88k \
- | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64el \
- | mips64octeon | mips64octeonel \
- | mips64orion | mips64orionel \
- | mips64r5900 | mips64r5900el \
- | mips64vr | mips64vrel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipstx39 | mipstx39el \
- | mn10200 | mn10300 \
- | moxie \
- | mt \
- | msp430 \
- | nds32 | nds32le | nds32be \
- | nios | nios2 \
- | ns16k | ns32k \
- | open8 \
- | or32 \
- | pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle \
- | pyramid \
- | rl78 | rx \
- | score \
- | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
- | sh64 | sh64le \
- | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
- | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
- | spu \
- | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
- | ubicom32 \
- | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
- | we32k \
- | x86 | xc16x | xstormy16 | xtensa \
- | z8k | z80)
- basic_machine=$basic_machine-unknown
- ;;
- c54x)
- basic_machine=tic54x-unknown
- ;;
- c55x)
- basic_machine=tic55x-unknown
- ;;
- c6x)
- basic_machine=tic6x-unknown
- ;;
- m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
- basic_machine=$basic_machine-unknown
- os=-none
- ;;
- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
- ;;
- ms1)
- basic_machine=mt-unknown
+ # Here we handle the default manufacturer of certain CPU types. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ cpu=hppa1.1
+ vendor=winbond
;;
-
- strongarm | thumb | xscale)
- basic_machine=arm-unknown
+ op50n)
+ cpu=hppa1.1
+ vendor=oki
;;
- xgate)
- basic_machine=$basic_machine-unknown
- os=-none
+ op60c)
+ cpu=hppa1.1
+ vendor=oki
;;
- xscaleeb)
- basic_machine=armeb-unknown
+ ibm*)
+ cpu=i370
+ vendor=ibm
;;
-
- xscaleel)
- basic_machine=armel-unknown
+ orion105)
+ cpu=clipper
+ vendor=highlevel
;;
-
- # We use `pc' rather than `unknown'
- # because (1) that's what they normally are, and
- # (2) the word "unknown" tends to confuse beginning users.
- i*86 | x86_64)
- basic_machine=$basic_machine-pc
- ;;
- # Object if more than one company name word.
- *-*-*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
+ mac | mpw | mac-mpw)
+ cpu=m68k
+ vendor=apple
;;
- # Recognize the basic CPU types with company name.
- 580-* \
- | a29k-* \
- | aarch64-* | aarch64_be-* \
- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
- | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
- | avr-* | avr32-* \
- | be32-* | be64-* \
- | bfin-* | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* \
- | clipper-* | craynv-* | cydra-* \
- | d10v-* | d30v-* | dlx-* \
- | elxsi-* \
- | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
- | h8300-* | h8500-* \
- | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
- | hexagon-* \
- | i*86-* | i860-* | i960-* | ia64-* \
- | ip2k-* | iq2000-* \
- | le32-* | le64-* \
- | lm32-* \
- | m32c-* | m32r-* | m32rle-* \
- | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
- | microblaze-* | microblazeel-* \
- | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
- | mips16-* \
- | mips64-* | mips64el-* \
- | mips64octeon-* | mips64octeonel-* \
- | mips64orion-* | mips64orionel-* \
- | mips64r5900-* | mips64r5900el-* \
- | mips64vr-* | mips64vrel-* \
- | mips64vr4100-* | mips64vr4100el-* \
- | mips64vr4300-* | mips64vr4300el-* \
- | mips64vr5000-* | mips64vr5000el-* \
- | mips64vr5900-* | mips64vr5900el-* \
- | mipsisa32-* | mipsisa32el-* \
- | mipsisa32r2-* | mipsisa32r2el-* \
- | mipsisa64-* | mipsisa64el-* \
- | mipsisa64r2-* | mipsisa64r2el-* \
- | mipsisa64sb1-* | mipsisa64sb1el-* \
- | mipsisa64sr71k-* | mipsisa64sr71kel-* \
- | mipstx39-* | mipstx39el-* \
- | mmix-* \
- | mt-* \
- | msp430-* \
- | nds32-* | nds32le-* | nds32be-* \
- | nios-* | nios2-* \
- | none-* | np1-* | ns16k-* | ns32k-* \
- | open8-* \
- | orion-* \
- | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
- | pyramid-* \
- | rl78-* | romp-* | rs6000-* | rx-* \
- | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
- | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
- | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
- | sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
- | tahoe-* \
- | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
- | tile*-* \
- | tron-* \
- | ubicom32-* \
- | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
- | vax-* \
- | we32k-* \
- | x86-* | x86_64-* | xc16x-* | xps100-* \
- | xstormy16-* | xtensa*-* \
- | ymp-* \
- | z8k-* | z80-*)
- ;;
- # Recognize the basic CPU types without company name, with glob match.
- xtensa*)
- basic_machine=$basic_machine-unknown
+ pmac | pmac-mpw)
+ cpu=powerpc
+ vendor=apple
;;
+
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
- 386bsd)
- basic_machine=i386-unknown
- os=-bsd
- ;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
- basic_machine=m68000-att
+ cpu=m68000
+ vendor=att
;;
3b*)
- basic_machine=we32k-att
- ;;
- a29khif)
- basic_machine=a29k-amd
- os=-udi
- ;;
- abacus)
- basic_machine=abacus-unknown
- ;;
- adobe68k)
- basic_machine=m68010-adobe
- os=-scout
- ;;
- alliant | fx80)
- basic_machine=fx80-alliant
- ;;
- altos | altos3068)
- basic_machine=m68k-altos
- ;;
- am29k)
- basic_machine=a29k-none
- os=-bsd
- ;;
- amd64)
- basic_machine=x86_64-pc
- ;;
- amd64-*)
- basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- amdahl)
- basic_machine=580-amdahl
- os=-sysv
- ;;
- amiga | amiga-*)
- basic_machine=m68k-unknown
- ;;
- amigaos | amigados)
- basic_machine=m68k-unknown
- os=-amigaos
- ;;
- amigaunix | amix)
- basic_machine=m68k-unknown
- os=-sysv4
- ;;
- apollo68)
- basic_machine=m68k-apollo
- os=-sysv
- ;;
- apollo68bsd)
- basic_machine=m68k-apollo
- os=-bsd
- ;;
- aros)
- basic_machine=i386-pc
- os=-aros
- ;;
- aux)
- basic_machine=m68k-apple
- os=-aux
- ;;
- balance)
- basic_machine=ns32k-sequent
- os=-dynix
- ;;
- blackfin)
- basic_machine=bfin-unknown
- os=-linux
- ;;
- blackfin-*)
- basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
+ cpu=we32k
+ vendor=att
;;
bluegene*)
- basic_machine=powerpc-ibm
- os=-cnk
- ;;
- c54x-*)
- basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c55x-*)
- basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c6x-*)
- basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c90)
- basic_machine=c90-cray
- os=-unicos
- ;;
- cegcc)
- basic_machine=arm-unknown
- os=-cegcc
- ;;
- convex-c1)
- basic_machine=c1-convex
- os=-bsd
- ;;
- convex-c2)
- basic_machine=c2-convex
- os=-bsd
- ;;
- convex-c32)
- basic_machine=c32-convex
- os=-bsd
- ;;
- convex-c34)
- basic_machine=c34-convex
- os=-bsd
- ;;
- convex-c38)
- basic_machine=c38-convex
- os=-bsd
- ;;
- cray | j90)
- basic_machine=j90-cray
- os=-unicos
- ;;
- craynv)
- basic_machine=craynv-cray
- os=-unicosmp
- ;;
- cr16 | cr16-*)
- basic_machine=cr16-unknown
- os=-elf
- ;;
- crds | unos)
- basic_machine=m68k-crds
- ;;
- crisv32 | crisv32-* | etraxfs*)
- basic_machine=crisv32-axis
- ;;
- cris | cris-* | etrax*)
- basic_machine=cris-axis
- ;;
- crx)
- basic_machine=crx-unknown
- os=-elf
- ;;
- da30 | da30-*)
- basic_machine=m68k-da30
- ;;
- decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
- basic_machine=mips-dec
+ cpu=powerpc
+ vendor=ibm
+ os=cnk
;;
decsystem10* | dec10*)
- basic_machine=pdp10-dec
- os=-tops10
+ cpu=pdp10
+ vendor=dec
+ os=tops10
;;
decsystem20* | dec20*)
- basic_machine=pdp10-dec
- os=-tops20
+ cpu=pdp10
+ vendor=dec
+ os=tops20
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
- basic_machine=m68k-motorola
- ;;
- delta88)
- basic_machine=m88k-motorola
- os=-sysv3
- ;;
- dicos)
- basic_machine=i686-pc
- os=-dicos
+ cpu=m68k
+ vendor=motorola
;;
- djgpp)
- basic_machine=i586-pc
- os=-msdosdjgpp
- ;;
- dpx20 | dpx20-*)
- basic_machine=rs6000-bull
- os=-bosx
- ;;
- dpx2* | dpx2*-bull)
- basic_machine=m68k-bull
- os=-sysv3
- ;;
- ebmon29k)
- basic_machine=a29k-amd
- os=-ebmon
- ;;
- elxsi)
- basic_machine=elxsi-elxsi
- os=-bsd
+ dpx2*)
+ cpu=m68k
+ vendor=bull
+ os=sysv3
;;
encore | umax | mmax)
- basic_machine=ns32k-encore
+ cpu=ns32k
+ vendor=encore
;;
- es1800 | OSE68k | ose68k | ose | OSE)
- basic_machine=m68k-ericsson
- os=-ose
+ elxsi)
+ cpu=elxsi
+ vendor=elxsi
+ os=${os:-bsd}
;;
fx2800)
- basic_machine=i860-alliant
+ cpu=i860
+ vendor=alliant
;;
genix)
- basic_machine=ns32k-ns
- ;;
- gmicro)
- basic_machine=tron-gmicro
- os=-sysv
- ;;
- go32)
- basic_machine=i386-pc
- os=-go32
+ cpu=ns32k
+ vendor=ns
;;
h3050r* | hiux*)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- h8300hms)
- basic_machine=h8300-hitachi
- os=-hms
- ;;
- h8300xray)
- basic_machine=h8300-hitachi
- os=-xray
- ;;
- h8500hms)
- basic_machine=h8500-hitachi
- os=-hms
- ;;
- harris)
- basic_machine=m88k-harris
- os=-sysv3
- ;;
- hp300-*)
- basic_machine=m68k-hp
- ;;
- hp300bsd)
- basic_machine=m68k-hp
- os=-bsd
- ;;
- hp300hpux)
- basic_machine=m68k-hp
- os=-hpux
+ cpu=hppa1.1
+ vendor=hitachi
+ os=hiuxwe2
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
- basic_machine=hppa1.0-hp
+ cpu=hppa1.0
+ vendor=hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
- basic_machine=m68000-hp
+ cpu=m68000
+ vendor=hp
;;
hp9k3[2-9][0-9])
- basic_machine=m68k-hp
+ cpu=m68k
+ vendor=hp
;;
hp9k6[0-9][0-9] | hp6[0-9][0-9])
- basic_machine=hppa1.0-hp
+ cpu=hppa1.0
+ vendor=hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
- basic_machine=hppa1.1-hp
+ cpu=hppa1.1
+ vendor=hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
+ cpu=hppa1.1
+ vendor=hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
+ cpu=hppa1.1
+ vendor=hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
- basic_machine=hppa1.1-hp
+ cpu=hppa1.1
+ vendor=hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hppa-next)
- os=-nextstep3
- ;;
- hppaosf)
- basic_machine=hppa1.1-hp
- os=-osf
- ;;
- hppro)
- basic_machine=hppa1.1-hp
- os=-proelf
- ;;
- i370-ibm* | ibm*)
- basic_machine=i370-ibm
+ cpu=hppa1.0
+ vendor=hp
;;
i*86v32)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv32
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ os=sysv32
;;
i*86v4*)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv4
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ os=sysv4
;;
i*86v)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ os=sysv
;;
i*86sol2)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-solaris2
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ os=solaris2
;;
- i386mach)
- basic_machine=i386-mach
- os=-mach
- ;;
- i386-vsta | vsta)
- basic_machine=i386-unknown
- os=-vsta
+ j90 | j90-cray)
+ cpu=j90
+ vendor=cray
+ os=${os:-unicos}
;;
iris | iris4d)
- basic_machine=mips-sgi
+ cpu=mips
+ vendor=sgi
case $os in
- -irix*)
+ irix*)
;;
*)
- os=-irix4
+ os=irix4
;;
esac
;;
- isi68 | isi)
- basic_machine=m68k-isi
- os=-sysv
- ;;
- m68knommu)
- basic_machine=m68k-unknown
- os=-linux
- ;;
- m68knommu-*)
- basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
- ;;
- m88k-omron*)
- basic_machine=m88k-omron
- ;;
- magnum | m3230)
- basic_machine=mips-mips
- os=-sysv
- ;;
- merlin)
- basic_machine=ns32k-utek
- os=-sysv
- ;;
- microblaze*)
- basic_machine=microblaze-xilinx
- ;;
- mingw64)
- basic_machine=x86_64-pc
- os=-mingw64
- ;;
- mingw32)
- basic_machine=i386-pc
- os=-mingw32
- ;;
- mingw32ce)
- basic_machine=arm-unknown
- os=-mingw32ce
- ;;
miniframe)
- basic_machine=m68000-convergent
- ;;
- *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
- mips3*-*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
- ;;
- mips3*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
- ;;
- monitor)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- morphos)
- basic_machine=powerpc-unknown
- os=-morphos
- ;;
- msdos)
- basic_machine=i386-pc
- os=-msdos
- ;;
- ms1-*)
- basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
- ;;
- msys)
- basic_machine=i386-pc
- os=-msys
- ;;
- mvs)
- basic_machine=i370-ibm
- os=-mvs
- ;;
- nacl)
- basic_machine=le32-unknown
- os=-nacl
- ;;
- ncr3000)
- basic_machine=i486-ncr
- os=-sysv4
+ cpu=m68000
+ vendor=convergent
;;
- netbsd386)
- basic_machine=i386-unknown
- os=-netbsd
- ;;
- netwinder)
- basic_machine=armv4l-rebel
- os=-linux
- ;;
- news | news700 | news800 | news900)
- basic_machine=m68k-sony
- os=-newsos
- ;;
- news1000)
- basic_machine=m68030-sony
- os=-newsos
+ *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ cpu=m68k
+ vendor=atari
+ os=mint
;;
news-3600 | risc-news)
- basic_machine=mips-sony
- os=-newsos
- ;;
- necv70)
- basic_machine=v70-nec
- os=-sysv
+ cpu=mips
+ vendor=sony
+ os=newsos
;;
- next | m*-next )
- basic_machine=m68k-next
+ next | m*-next)
+ cpu=m68k
+ vendor=next
case $os in
- -nextstep* )
+ openstep*)
+ ;;
+ nextstep*)
;;
- -ns2*)
- os=-nextstep2
+ ns2*)
+ os=nextstep2
;;
*)
- os=-nextstep3
+ os=nextstep3
;;
esac
;;
- nh3000)
- basic_machine=m68k-harris
- os=-cxux
- ;;
- nh[45]000)
- basic_machine=m88k-harris
- os=-cxux
- ;;
- nindy960)
- basic_machine=i960-intel
- os=-nindy
- ;;
- mon960)
- basic_machine=i960-intel
- os=-mon960
- ;;
- nonstopux)
- basic_machine=mips-compaq
- os=-nonstopux
- ;;
np1)
- basic_machine=np1-gould
- ;;
- neo-tandem)
- basic_machine=neo-tandem
- ;;
- nse-tandem)
- basic_machine=nse-tandem
- ;;
- nsr-tandem)
- basic_machine=nsr-tandem
+ cpu=np1
+ vendor=gould
;;
op50n-* | op60c-*)
- basic_machine=hppa1.1-oki
- os=-proelf
- ;;
- openrisc | openrisc-*)
- basic_machine=or32-unknown
- ;;
- os400)
- basic_machine=powerpc-ibm
- os=-os400
- ;;
- OSE68000 | ose68000)
- basic_machine=m68000-ericsson
- os=-ose
- ;;
- os68k)
- basic_machine=m68k-none
- os=-os68k
+ cpu=hppa1.1
+ vendor=oki
+ os=proelf
;;
pa-hitachi)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- paragon)
- basic_machine=i860-intel
- os=-osf
- ;;
- parisc)
- basic_machine=hppa-unknown
- os=-linux
- ;;
- parisc-*)
- basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
+ cpu=hppa1.1
+ vendor=hitachi
+ os=hiuxwe2
;;
pbd)
- basic_machine=sparc-tti
+ cpu=sparc
+ vendor=tti
;;
pbb)
- basic_machine=m68k-tti
+ cpu=m68k
+ vendor=tti
;;
- pc532 | pc532-*)
- basic_machine=ns32k-pc532
- ;;
- pc98)
- basic_machine=i386-pc
- ;;
- pc98-*)
- basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentium | p5 | k5 | k6 | nexgen | viac3)
- basic_machine=i586-pc
- ;;
- pentiumpro | p6 | 6x86 | athlon | athlon_*)
- basic_machine=i686-pc
- ;;
- pentiumii | pentium2 | pentiumiii | pentium3)
- basic_machine=i686-pc
- ;;
- pentium4)
- basic_machine=i786-pc
- ;;
- pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
- basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumpro-* | p6-* | 6x86-* | athlon-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentium4-*)
- basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ pc532)
+ cpu=ns32k
+ vendor=pc532
;;
pn)
- basic_machine=pn-gould
- ;;
- power) basic_machine=power-ibm
+ cpu=pn
+ vendor=gould
;;
- ppc | ppcbe) basic_machine=powerpc-unknown
- ;;
- ppc-* | ppcbe-*)
- basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppcle | powerpclittle | ppc-le | powerpc-little)
- basic_machine=powerpcle-unknown
- ;;
- ppcle-* | powerpclittle-*)
- basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64) basic_machine=powerpc64-unknown
- ;;
- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64le | powerpc64little | ppc64-le | powerpc64-little)
- basic_machine=powerpc64le-unknown
- ;;
- ppc64le-* | powerpc64little-*)
- basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ power)
+ cpu=power
+ vendor=ibm
;;
ps2)
- basic_machine=i386-ibm
- ;;
- pw32)
- basic_machine=i586-unknown
- os=-pw32
- ;;
- rdos | rdos64)
- basic_machine=x86_64-pc
- os=-rdos
- ;;
- rdos32)
- basic_machine=i386-pc
- os=-rdos
- ;;
- rom68k)
- basic_machine=m68k-rom68k
- os=-coff
+ cpu=i386
+ vendor=ibm
;;
rm[46]00)
- basic_machine=mips-siemens
+ cpu=mips
+ vendor=siemens
;;
rtpc | rtpc-*)
- basic_machine=romp-ibm
- ;;
- s390 | s390-*)
- basic_machine=s390-ibm
- ;;
- s390x | s390x-*)
- basic_machine=s390x-ibm
+ cpu=romp
+ vendor=ibm
;;
- sa29200)
- basic_machine=a29k-amd
- os=-udi
- ;;
- sb1)
- basic_machine=mipsisa64sb1-unknown
+ sde)
+ cpu=mipsisa32
+ vendor=sde
+ os=${os:-elf}
;;
- sb1el)
- basic_machine=mipsisa64sb1el-unknown
+ simso-wrs)
+ cpu=sparclite
+ vendor=wrs
+ os=vxworks
;;
- sde)
- basic_machine=mipsisa32-sde
- os=-elf
+ tower | tower-32)
+ cpu=m68k
+ vendor=ncr
;;
- sei)
- basic_machine=mips-sei
- os=-seiux
+ vpp*|vx|vx-*)
+ cpu=f301
+ vendor=fujitsu
;;
- sequent)
- basic_machine=i386-sequent
+ w65)
+ cpu=w65
+ vendor=wdc
;;
- sh)
- basic_machine=sh-hitachi
- os=-hms
+ w89k-*)
+ cpu=hppa1.1
+ vendor=winbond
+ os=proelf
;;
- sh5el)
- basic_machine=sh5le-unknown
+ none)
+ cpu=none
+ vendor=none
;;
- sh64)
- basic_machine=sh64-unknown
+ leon|leon[3-9])
+ cpu=sparc
+ vendor=$basic_machine
;;
- sparclite-wrs | simso-wrs)
- basic_machine=sparclite-wrs
- os=-vxworks
+ leon-*|leon[3-9]-*)
+ cpu=sparc
+ vendor=`echo "$basic_machine" | sed 's/-.*//'`
;;
- sps7)
- basic_machine=m68k-bull
- os=-sysv2
+
+ *-*)
+ # shellcheck disable=SC2162
+ IFS="-" read cpu vendor <<EOF
+$basic_machine
+EOF
;;
- spur)
- basic_machine=spur-unknown
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ cpu=$basic_machine
+ vendor=pc
;;
- st2000)
- basic_machine=m68k-tandem
+ # These rules are duplicated from below for sake of the special case above;
+ # i.e. things that normalized to x86 arches should also default to "pc"
+ pc98)
+ cpu=i386
+ vendor=pc
;;
- stratus)
- basic_machine=i860-stratus
- os=-sysv4
+ x64 | amd64)
+ cpu=x86_64
+ vendor=pc
;;
- strongarm-* | thumb-*)
- basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ # Recognize the basic CPU types without company name.
+ *)
+ cpu=$basic_machine
+ vendor=unknown
;;
- sun2)
- basic_machine=m68000-sun
+esac
+
+unset -v basic_machine
+
+# Decode basic machines in the full and proper CPU-Company form.
+case $cpu-$vendor in
+ # Here we handle the default manufacturer of certain CPU types in canonical form. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ craynv-unknown)
+ vendor=cray
+ os=${os:-unicosmp}
;;
- sun2os3)
- basic_machine=m68000-sun
- os=-sunos3
+ c90-unknown | c90-cray)
+ vendor=cray
+ os=${os:-unicos}
;;
- sun2os4)
- basic_machine=m68000-sun
- os=-sunos4
+ fx80-unknown)
+ vendor=alliant
;;
- sun3os3)
- basic_machine=m68k-sun
- os=-sunos3
+ romp-unknown)
+ vendor=ibm
;;
- sun3os4)
- basic_machine=m68k-sun
- os=-sunos4
+ mmix-unknown)
+ vendor=knuth
;;
- sun4os3)
- basic_machine=sparc-sun
- os=-sunos3
+ microblaze-unknown | microblazeel-unknown)
+ vendor=xilinx
;;
- sun4os4)
- basic_machine=sparc-sun
- os=-sunos4
+ rs6000-unknown)
+ vendor=ibm
;;
- sun4sol2)
- basic_machine=sparc-sun
- os=-solaris2
+ vax-unknown)
+ vendor=dec
;;
- sun3 | sun3-*)
- basic_machine=m68k-sun
+ pdp11-unknown)
+ vendor=dec
;;
- sun4)
- basic_machine=sparc-sun
+ we32k-unknown)
+ vendor=att
;;
- sun386 | sun386i | roadrunner)
- basic_machine=i386-sun
+ cydra-unknown)
+ vendor=cydrome
;;
- sv1)
- basic_machine=sv1-cray
- os=-unicos
+ i370-ibm*)
+ vendor=ibm
;;
- symmetry)
- basic_machine=i386-sequent
- os=-dynix
+ orion-unknown)
+ vendor=highlevel
;;
- t3e)
- basic_machine=alphaev5-cray
- os=-unicos
+ xps-unknown | xps100-unknown)
+ cpu=xps100
+ vendor=honeywell
;;
- t90)
- basic_machine=t90-cray
- os=-unicos
+
+ # Here we normalize CPU types with a missing or matching vendor
+ dpx20-unknown | dpx20-bull)
+ cpu=rs6000
+ vendor=bull
+ os=${os:-bosx}
;;
- tile*)
- basic_machine=$basic_machine-unknown
- os=-linux-gnu
+
+ # Here we normalize CPU types irrespective of the vendor
+ amd64-*)
+ cpu=x86_64
;;
- tx39)
- basic_machine=mipstx39-unknown
+ blackfin-*)
+ cpu=bfin
+ os=linux
;;
- tx39el)
- basic_machine=mipstx39el-unknown
+ c54x-*)
+ cpu=tic54x
;;
- toad1)
- basic_machine=pdp10-xkl
- os=-tops20
+ c55x-*)
+ cpu=tic55x
;;
- tower | tower-32)
- basic_machine=m68k-ncr
+ c6x-*)
+ cpu=tic6x
;;
- tpf)
- basic_machine=s390x-ibm
- os=-tpf
+ e500v[12]-*)
+ cpu=powerpc
+ os=$os"spe"
;;
- udi29k)
- basic_machine=a29k-amd
- os=-udi
+ mips3*-*)
+ cpu=mips64
;;
- ultra3)
- basic_machine=a29k-nyu
- os=-sym1
+ ms1-*)
+ cpu=mt
;;
- v810 | necv810)
- basic_machine=v810-nec
- os=-none
+ m68knommu-*)
+ cpu=m68k
+ os=linux
;;
- vaxv)
- basic_machine=vax-dec
- os=-sysv
+ m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
+ cpu=s12z
;;
- vms)
- basic_machine=vax-dec
- os=-vms
+ openrisc-*)
+ cpu=or32
;;
- vpp*|vx|vx-*)
- basic_machine=f301-fujitsu
+ parisc-*)
+ cpu=hppa
+ os=linux
;;
- vxworks960)
- basic_machine=i960-wrs
- os=-vxworks
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ cpu=i586
;;
- vxworks68)
- basic_machine=m68k-wrs
- os=-vxworks
+ pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
+ cpu=i686
;;
- vxworks29k)
- basic_machine=a29k-wrs
- os=-vxworks
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ cpu=i686
;;
- w65*)
- basic_machine=w65-wdc
- os=-none
+ pentium4-*)
+ cpu=i786
;;
- w89k-*)
- basic_machine=hppa1.1-winbond
- os=-proelf
+ pc98-*)
+ cpu=i386
;;
- xbox)
- basic_machine=i686-pc
- os=-mingw32
+ ppc-* | ppcbe-*)
+ cpu=powerpc
;;
- xps | xps100)
- basic_machine=xps100-honeywell
+ ppcle-* | powerpclittle-*)
+ cpu=powerpcle
;;
- xscale-* | xscalee[bl]-*)
- basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ppc64-*)
+ cpu=powerpc64
;;
- ymp)
- basic_machine=ymp-cray
- os=-unicos
+ ppc64le-* | powerpc64little-*)
+ cpu=powerpc64le
;;
- z8k-*-coff)
- basic_machine=z8k-unknown
- os=-sim
+ sb1-*)
+ cpu=mipsisa64sb1
;;
- z80-*-coff)
- basic_machine=z80-unknown
- os=-sim
+ sb1el-*)
+ cpu=mipsisa64sb1el
;;
- none)
- basic_machine=none-none
- os=-none
+ sh5e[lb]-*)
+ cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
;;
-
-# Here we handle the default manufacturer of certain CPU types. It is in
-# some cases the only manufacturer, in others, it is the most popular.
- w89k)
- basic_machine=hppa1.1-winbond
+ spur-*)
+ cpu=spur
;;
- op50n)
- basic_machine=hppa1.1-oki
+ strongarm-* | thumb-*)
+ cpu=arm
;;
- op60c)
- basic_machine=hppa1.1-oki
+ tx39-*)
+ cpu=mipstx39
;;
- romp)
- basic_machine=romp-ibm
+ tx39el-*)
+ cpu=mipstx39el
;;
- mmix)
- basic_machine=mmix-knuth
+ x64-*)
+ cpu=x86_64
;;
- rs6000)
- basic_machine=rs6000-ibm
+ xscale-* | xscalee[bl]-*)
+ cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
;;
- vax)
- basic_machine=vax-dec
+
+ # Recognize the canonical CPU Types that limit and/or modify the
+ # company names they are paired with.
+ cr16-*)
+ os=${os:-elf}
;;
- pdp10)
- # there are many clones, so DEC is not a safe bet
- basic_machine=pdp10-unknown
+ crisv32-* | etraxfs*-*)
+ cpu=crisv32
+ vendor=axis
;;
- pdp11)
- basic_machine=pdp11-dec
+ cris-* | etrax*-*)
+ cpu=cris
+ vendor=axis
;;
- we32k)
- basic_machine=we32k-att
+ crx-*)
+ os=${os:-elf}
;;
- sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
- basic_machine=sh-unknown
+ neo-tandem)
+ cpu=neo
+ vendor=tandem
;;
- sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
- basic_machine=sparc-sun
+ nse-tandem)
+ cpu=nse
+ vendor=tandem
;;
- cydra)
- basic_machine=cydra-cydrome
+ nsr-tandem)
+ cpu=nsr
+ vendor=tandem
;;
- orion)
- basic_machine=orion-highlevel
+ nsv-tandem)
+ cpu=nsv
+ vendor=tandem
;;
- orion105)
- basic_machine=clipper-highlevel
+ nsx-tandem)
+ cpu=nsx
+ vendor=tandem
;;
- mac | mpw | mac-mpw)
- basic_machine=m68k-apple
+ s390-*)
+ cpu=s390
+ vendor=ibm
;;
- pmac | pmac-mpw)
- basic_machine=powerpc-apple
+ s390x-*)
+ cpu=s390x
+ vendor=ibm
;;
- *-unknown)
- # Make sure to match an already-canonicalized machine name.
+ tile*-*)
+ os=${os:-linux-gnu}
;;
+
*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
+ # Recognize the canonical CPU types that are allowed with any
+ # company name.
+ case $cpu in
+ 1750a | 580 \
+ | a29k \
+ | aarch64 | aarch64_be \
+ | abacus \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
+ | alphapca5[67] | alpha64pca5[67] \
+ | am33_2.0 \
+ | amdgcn \
+ | arc | arceb \
+ | arm | arm[lb]e | arme[lb] | armv* \
+ | avr | avr32 \
+ | asmjs \
+ | ba \
+ | be32 | be64 \
+ | bfin | bpf | bs2000 \
+ | c[123]* | c30 | [cjt]90 | c4x \
+ | c8051 | clipper | craynv | csky | cydra \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | elxsi | epiphany \
+ | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+ | h8300 | h8500 \
+ | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i*86 | i860 | i960 | ia16 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle \
+ | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
+ | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
+ | m88110 | m88k | maxq | mb | mcore | mep | metag \
+ | microblaze | microblazeel \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64eb | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mmix \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nfp \
+ | nios | nios2 | nios2eb | nios2el \
+ | none | np1 | ns16k | ns32k | nvptx \
+ | open8 \
+ | or1k* \
+ | or32 \
+ | orion \
+ | picochip \
+ | pdp10 | pdp11 | pj | pjl | pn | power \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
+ | pru \
+ | pyramid \
+ | riscv | riscv32 | riscv64 \
+ | rl78 | romp | rs6000 | rx \
+ | score \
+ | sh | shl \
+ | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
+ | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
+ | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
+ | spu \
+ | tahoe \
+ | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
+ | tron \
+ | ubicom32 \
+ | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
+ | vax \
+ | visium \
+ | w65 \
+ | wasm32 | wasm64 \
+ | we32k \
+ | x86 | x86_64 | xc16x | xgate | xps100 \
+ | xstormy16 | xtensa* \
+ | ymp \
+ | z8k | z80)
+ ;;
+
+ *)
+ echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+ exit 1
+ ;;
+ esac
;;
esac
# Here we canonicalize certain aliases for manufacturers.
-case $basic_machine in
- *-digital*)
- basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+case $vendor in
+ digital*)
+ vendor=dec
;;
- *-commodore*)
- basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ commodore*)
+ vendor=cbm
;;
*)
;;
@@ -1326,200 +1275,244 @@ esac
# Decode manufacturer-specific aliases for certain operating systems.
-if [ x"$os" != x"" ]
+if [ x$os != x ]
then
case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
- # -solaris* is a basic system type, with this one exception.
- -auroraux)
- os=-auroraux
+ # First match some system type aliases that might get confused
+ # with valid system types.
+ # solaris* is a basic system type, with this one exception.
+ auroraux)
+ os=auroraux
;;
- -solaris1 | -solaris1.*)
- os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ bluegene*)
+ os=cnk
;;
- -solaris)
- os=-solaris2
+ solaris1 | solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
- -svr4*)
- os=-sysv4
+ solaris)
+ os=solaris2
;;
- -unixware*)
- os=-sysv4.2uw
+ unixware*)
+ os=sysv4.2uw
;;
- -gnu/linux*)
+ gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
- # First accept the basic system types.
+ # es1800 is here to avoid being matched by es* (a different OS)
+ es1800*)
+ os=ose
+ ;;
+ # Some version numbers need modification
+ chorusos*)
+ os=chorusos
+ ;;
+ isc)
+ os=isc2.2
+ ;;
+ sco6)
+ os=sco5v6
+ ;;
+ sco5)
+ os=sco3.2v5
+ ;;
+ sco4)
+ os=sco3.2v4
+ ;;
+ sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ ;;
+ sco3.2v[4-9]* | sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ ;;
+ scout)
+ # Don't match below
+ ;;
+ sco*)
+ os=sco3.2v2
+ ;;
+ psos*)
+ os=psos
+ ;;
+ # Now accept the basic system types.
# The portable systems comes first.
- # Each alternative MUST END IN A *, to match a version number.
- # -sysv* is not here because it comes later, after sysvr4.
- -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
- | -sym* | -kopensolaris* \
- | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* | -aros* \
- | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
- | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
- | -bitrig* | -openbsd* | -solidbsd* \
- | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
- | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
- | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
- | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -chorusos* | -chorusrdb* | -cegcc* \
- | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
- | -linux-newlib* | -linux-musl* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* \
- | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
- | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
- | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
- | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
- | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
- | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+ # Each alternative MUST end in a * to match a version number.
+ # sysv* is not here because it comes later, after sysvr4.
+ gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
+ | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\
+ | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+ | sym* | kopensolaris* | plan9* \
+ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
+ | aos* | aros* | cloudabi* | sortix* | twizzler* \
+ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
+ | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
+ | knetbsd* | mirbsd* | netbsd* \
+ | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \
+ | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \
+ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
+ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+ | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \
+ | chorusrdb* | cegcc* | glidix* \
+ | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+ | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \
+ | linux-newlib* | linux-musl* | linux-uclibc* \
+ | uxpv* | beos* | mpeix* | udk* | moxiebox* \
+ | interix* | uwin* | mks* | rhapsody* | darwin* \
+ | openstep* | oskit* | conix* | pw32* | nonstopux* \
+ | storm-chaos* | tops10* | tenex* | tops20* | its* \
+ | os2* | vos* | palmos* | uclinux* | nucleus* \
+ | morphos* | superux* | rtmk* | windiss* \
+ | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
+ | skyos* | haiku* | rdos* | toppers* | drops* | es* \
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+ | nsk* | powerunix* | genode*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
- -qnx*)
- case $basic_machine in
- x86-* | i*86-*)
+ qnx*)
+ case $cpu in
+ x86 | i*86)
;;
*)
- os=-nto$os
+ os=nto-$os
;;
esac
;;
- -nto-qnx*)
+ hiux*)
+ os=hiuxwe2
;;
- -nto*)
- os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ nto-qnx*)
;;
- -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
- | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
- | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
- -mac*)
- os=`echo $os | sed -e 's|mac|macos|'`
+ sim | xray | os68k* | v88r* \
+ | windows* | osx | abug | netware* | os9* \
+ | macos* | mpw* | magic* | mmixware* | mon960* | lnews*)
;;
- -linux-dietlibc)
- os=-linux-dietlibc
+ linux-dietlibc)
+ os=linux-dietlibc
;;
- -linux*)
+ linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
- -sunos5*)
- os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ lynx*178)
+ os=lynxos178
;;
- -sunos6*)
- os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ lynx*5)
+ os=lynxos5
;;
- -opened*)
- os=-openedition
+ lynx*)
+ os=lynxos
;;
- -os400*)
- os=-os400
+ mac*)
+ os=`echo "$os" | sed -e 's|mac|macos|'`
;;
- -wince*)
- os=-wince
+ opened*)
+ os=openedition
;;
- -osfrose*)
- os=-osfrose
+ os400*)
+ os=os400
;;
- -osf*)
- os=-osf
+ sunos5*)
+ os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
;;
- -utek*)
- os=-bsd
+ sunos6*)
+ os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
;;
- -dynix*)
- os=-bsd
+ wince*)
+ os=wince
;;
- -acis*)
- os=-aos
+ utek*)
+ os=bsd
;;
- -atheos*)
- os=-atheos
+ dynix*)
+ os=bsd
;;
- -syllable*)
- os=-syllable
+ acis*)
+ os=aos
;;
- -386bsd)
- os=-bsd
+ atheos*)
+ os=atheos
;;
- -ctix* | -uts*)
- os=-sysv
+ syllable*)
+ os=syllable
;;
- -nova*)
- os=-rtmk-nova
+ 386bsd)
+ os=bsd
;;
- -ns2 )
- os=-nextstep2
+ ctix* | uts*)
+ os=sysv
;;
- -nsk*)
- os=-nsk
+ nova*)
+ os=rtmk-nova
+ ;;
+ ns2)
+ os=nextstep2
;;
# Preserve the version number of sinix5.
- -sinix5.*)
+ sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
;;
- -sinix*)
- os=-sysv4
- ;;
- -tpf*)
- os=-tpf
+ sinix*)
+ os=sysv4
;;
- -triton*)
- os=-sysv3
+ tpf*)
+ os=tpf
;;
- -oss*)
- os=-sysv3
+ triton*)
+ os=sysv3
;;
- -svr4)
- os=-sysv4
+ oss*)
+ os=sysv3
;;
- -svr3)
- os=-sysv3
+ svr4*)
+ os=sysv4
;;
- -sysvr4)
- os=-sysv4
+ svr3)
+ os=sysv3
;;
- # This must come after -sysvr4.
- -sysv*)
+ sysvr4)
+ os=sysv4
;;
- -ose*)
- os=-ose
+ # This must come after sysvr4.
+ sysv*)
;;
- -es1800*)
- os=-ose
+ ose*)
+ os=ose
;;
- -xenix)
- os=-xenix
+ *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
+ os=mint
;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- os=-mint
+ zvmoe)
+ os=zvmoe
;;
- -aros*)
- os=-aros
+ dicos*)
+ os=dicos
;;
- -kaos*)
- os=-kaos
+ pikeos*)
+ # Until real need of OS specific support for
+ # particular features comes up, bare metal
+ # configurations are quite functional.
+ case $cpu in
+ arm*)
+ os=eabi
+ ;;
+ *)
+ os=elf
+ ;;
+ esac
;;
- -zvmoe)
- os=-zvmoe
+ nacl*)
;;
- -dicos*)
- os=-dicos
+ ios)
;;
- -nacl*)
+ none)
;;
- -none)
+ *-eabi)
;;
*)
- # Get rid of the `-' at the beginning of $os.
- os=`echo $os | sed 's/[^-]*-//'`
- echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
exit 1
;;
esac
@@ -1535,258 +1528,265 @@ else
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
-case $basic_machine in
+case $cpu-$vendor in
score-*)
- os=-elf
+ os=elf
;;
spu-*)
- os=-elf
+ os=elf
;;
*-acorn)
- os=-riscix1.2
+ os=riscix1.2
;;
arm*-rebel)
- os=-linux
+ os=linux
;;
arm*-semi)
- os=-aout
+ os=aout
;;
c4x-* | tic4x-*)
- os=-coff
+ os=coff
+ ;;
+ c8051-*)
+ os=elf
+ ;;
+ clipper-intergraph)
+ os=clix
;;
hexagon-*)
- os=-elf
+ os=elf
;;
tic54x-*)
- os=-coff
+ os=coff
;;
tic55x-*)
- os=-coff
+ os=coff
;;
tic6x-*)
- os=-coff
+ os=coff
;;
# This must come before the *-dec entry.
pdp10-*)
- os=-tops20
+ os=tops20
;;
pdp11-*)
- os=-none
+ os=none
;;
*-dec | vax-*)
- os=-ultrix4.2
+ os=ultrix4.2
;;
m68*-apollo)
- os=-domain
+ os=domain
;;
i386-sun)
- os=-sunos4.0.2
+ os=sunos4.0.2
;;
m68000-sun)
- os=-sunos3
+ os=sunos3
;;
m68*-cisco)
- os=-aout
+ os=aout
;;
mep-*)
- os=-elf
+ os=elf
;;
mips*-cisco)
- os=-elf
+ os=elf
;;
mips*-*)
- os=-elf
+ os=elf
;;
or32-*)
- os=-coff
+ os=coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
- os=-sysv3
+ os=sysv3
;;
sparc-* | *-sun)
- os=-sunos4.1.1
+ os=sunos4.1.1
;;
- *-be)
- os=-beos
+ pru-*)
+ os=elf
;;
- *-haiku)
- os=-haiku
+ *-be)
+ os=beos
;;
*-ibm)
- os=-aix
+ os=aix
;;
*-knuth)
- os=-mmixware
+ os=mmixware
;;
*-wec)
- os=-proelf
+ os=proelf
;;
*-winbond)
- os=-proelf
+ os=proelf
;;
*-oki)
- os=-proelf
+ os=proelf
;;
*-hp)
- os=-hpux
+ os=hpux
;;
*-hitachi)
- os=-hiux
+ os=hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
- os=-sysv
+ os=sysv
;;
*-cbm)
- os=-amigaos
+ os=amigaos
;;
*-dg)
- os=-dgux
+ os=dgux
;;
*-dolphin)
- os=-sysv3
+ os=sysv3
;;
m68k-ccur)
- os=-rtu
+ os=rtu
;;
m88k-omron*)
- os=-luna
+ os=luna
;;
- *-next )
- os=-nextstep
+ *-next)
+ os=nextstep
;;
*-sequent)
- os=-ptx
+ os=ptx
;;
*-crds)
- os=-unos
+ os=unos
;;
*-ns)
- os=-genix
+ os=genix
;;
i370-*)
- os=-mvs
- ;;
- *-next)
- os=-nextstep3
+ os=mvs
;;
*-gould)
- os=-sysv
+ os=sysv
;;
*-highlevel)
- os=-bsd
+ os=bsd
;;
*-encore)
- os=-bsd
+ os=bsd
;;
*-sgi)
- os=-irix
+ os=irix
;;
*-siemens)
- os=-sysv4
+ os=sysv4
;;
*-masscomp)
- os=-rtu
+ os=rtu
;;
f30[01]-fujitsu | f700-fujitsu)
- os=-uxpv
+ os=uxpv
;;
*-rom68k)
- os=-coff
+ os=coff
;;
*-*bug)
- os=-coff
+ os=coff
;;
*-apple)
- os=-macos
+ os=macos
;;
*-atari*)
- os=-mint
+ os=mint
+ ;;
+ *-wrs)
+ os=vxworks
;;
*)
- os=-none
+ os=none
;;
esac
fi
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
-vendor=unknown
-case $basic_machine in
- *-unknown)
+case $vendor in
+ unknown)
case $os in
- -riscix*)
+ riscix*)
vendor=acorn
;;
- -sunos*)
+ sunos*)
vendor=sun
;;
- -cnk*|-aix*)
+ cnk*|-aix*)
vendor=ibm
;;
- -beos*)
+ beos*)
vendor=be
;;
- -hpux*)
+ hpux*)
vendor=hp
;;
- -mpeix*)
+ mpeix*)
vendor=hp
;;
- -hiux*)
+ hiux*)
vendor=hitachi
;;
- -unos*)
+ unos*)
vendor=crds
;;
- -dgux*)
+ dgux*)
vendor=dg
;;
- -luna*)
+ luna*)
vendor=omron
;;
- -genix*)
+ genix*)
vendor=ns
;;
- -mvs* | -opened*)
+ clix*)
+ vendor=intergraph
+ ;;
+ mvs* | opened*)
vendor=ibm
;;
- -os400*)
+ os400*)
vendor=ibm
;;
- -ptx*)
+ ptx*)
vendor=sequent
;;
- -tpf*)
+ tpf*)
vendor=ibm
;;
- -vxsim* | -vxworks* | -windiss*)
+ vxsim* | vxworks* | windiss*)
vendor=wrs
;;
- -aux*)
+ aux*)
vendor=apple
;;
- -hms*)
+ hms*)
vendor=hitachi
;;
- -mpw* | -macos*)
+ mpw* | macos*)
vendor=apple
;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
vendor=atari
;;
- -vos*)
+ vos*)
vendor=stratus
;;
esac
- basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
-echo $basic_machine$os
+echo "$cpu-$vendor-$os"
exit
# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
diff --git a/configure b/configure
deleted file mode 100755
index 10267f66..00000000
--- a/configure
+++ /dev/null
@@ -1,36621 +0,0 @@
-#! /bin/sh
-# From configure.ac Revision: 1.583 .
-# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for OpenSSH Portable.
-#
-# Report bugs to <openssh-unix-dev@mindrot.org>.
-#
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-## --------------------- ##
-## M4sh Initialization. ##
-## --------------------- ##
-
-# Be more Bourne compatible
-DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in
- *posix*) set -o posix ;;
-esac
-
-fi
-
-
-
-
-# PATH needs CR
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- echo "#! /bin/sh" >conf$$.sh
- echo "exit 0" >>conf$$.sh
- chmod +x conf$$.sh
- if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
- PATH_SEPARATOR=';'
- else
- PATH_SEPARATOR=:
- fi
- rm -f conf$$.sh
-fi
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- as_unset=unset
-else
- as_unset=false
-fi
-
-
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-as_nl='
-'
-IFS=" "" $as_nl"
-
-# Find who we are. Look in the path if we contain no directory separator.
-case $0 in
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
-# in which case we are not to be found in the path.
-if test "x$as_myself" = x; then
- as_myself=$0
-fi
-if test ! -f "$as_myself"; then
- echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
- { (exit 1); exit 1; }
-fi
-
-# Work around bugs in pre-3.0 UWIN ksh.
-for as_var in ENV MAIL MAILPATH
-do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
- LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
- LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
- LC_TELEPHONE LC_TIME
-do
- if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
- eval $as_var=C; export $as_var
- else
- ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
- fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{
- s//\1/
- q
- }
- /^X\/\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\/\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
-
-# CDPATH.
-$as_unset CDPATH
-
-
-if test "x$CONFIG_SHELL" = x; then
- if (eval ":") 2>/dev/null; then
- as_have_required=yes
-else
- as_have_required=no
-fi
-
- if test $as_have_required = yes && (eval ":
-(as_func_return () {
- (exit \$1)
-}
-as_func_success () {
- as_func_return 0
-}
-as_func_failure () {
- as_func_return 1
-}
-as_func_ret_success () {
- return 0
-}
-as_func_ret_failure () {
- return 1
-}
-
-exitcode=0
-if as_func_success; then
- :
-else
- exitcode=1
- echo as_func_success failed.
-fi
-
-if as_func_failure; then
- exitcode=1
- echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
- :
-else
- exitcode=1
- echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
- exitcode=1
- echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
- :
-else
- exitcode=1
- echo positional parameters were not saved.
-fi
-
-test \$exitcode = 0) || { (exit 1); exit 1; }
-
-(
- as_lineno_1=\$LINENO
- as_lineno_2=\$LINENO
- test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
- test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
-") 2> /dev/null; then
- :
-else
- as_candidate_shells=
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- case $as_dir in
- /*)
- for as_base in sh bash ksh sh5; do
- as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
- done;;
- esac
-done
-IFS=$as_save_IFS
-
-
- for as_shell in $as_candidate_shells $SHELL; do
- # Try only shells that exist, to save several forks.
- if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { ("$as_shell") 2> /dev/null <<\_ASEOF
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in
- *posix*) set -o posix ;;
-esac
-
-fi
-
-
-:
-_ASEOF
-}; then
- CONFIG_SHELL=$as_shell
- as_have_required=yes
- if { "$as_shell" 2> /dev/null <<\_ASEOF
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in
- *posix*) set -o posix ;;
-esac
-
-fi
-
-
-:
-(as_func_return () {
- (exit $1)
-}
-as_func_success () {
- as_func_return 0
-}
-as_func_failure () {
- as_func_return 1
-}
-as_func_ret_success () {
- return 0
-}
-as_func_ret_failure () {
- return 1
-}
-
-exitcode=0
-if as_func_success; then
- :
-else
- exitcode=1
- echo as_func_success failed.
-fi
-
-if as_func_failure; then
- exitcode=1
- echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
- :
-else
- exitcode=1
- echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
- exitcode=1
- echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = "$1" ); then
- :
-else
- exitcode=1
- echo positional parameters were not saved.
-fi
-
-test $exitcode = 0) || { (exit 1); exit 1; }
-
-(
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
-
-_ASEOF
-}; then
- break
-fi
-
-fi
-
- done
-
- if test "x$CONFIG_SHELL" != x; then
- for as_var in BASH_ENV ENV
- do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
- done
- export CONFIG_SHELL
- exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
-fi
-
-
- if test $as_have_required = no; then
- echo This script requires a shell more modern than all the
- echo shells that I found on your system. Please install a
- echo modern shell, or manually run the script under such a
- echo shell if you do have one.
- { (exit 1); exit 1; }
-fi
-
-
-fi
-
-fi
-
-
-
-(eval "as_func_return () {
- (exit \$1)
-}
-as_func_success () {
- as_func_return 0
-}
-as_func_failure () {
- as_func_return 1
-}
-as_func_ret_success () {
- return 0
-}
-as_func_ret_failure () {
- return 1
-}
-
-exitcode=0
-if as_func_success; then
- :
-else
- exitcode=1
- echo as_func_success failed.
-fi
-
-if as_func_failure; then
- exitcode=1
- echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
- :
-else
- exitcode=1
- echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
- exitcode=1
- echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
- :
-else
- exitcode=1
- echo positional parameters were not saved.
-fi
-
-test \$exitcode = 0") || {
- echo No shell found that supports shell functions.
- echo Please tell autoconf@gnu.org about your system,
- echo including any error possibly output before this
- echo message
-}
-
-
-
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
-
- # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
- # uniformly replaced by the line number. The first 'sed' inserts a
- # line-number line after each line using $LINENO; the second 'sed'
- # does the real work. The second script uses 'N' to pair each
- # line-number line with the line containing $LINENO, and appends
- # trailing '-' during substitution so that $LINENO is not a special
- # case at line end.
- # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
- # scripts with optimization help from Paolo Bonzini. Blame Lee
- # E. McMahon (1931-1989) for sed's syntax. :-)
- sed -n '
- p
- /[$]LINENO/=
- ' <$as_myself |
- sed '
- s/[$]LINENO.*/&-/
- t lineno
- b
- :lineno
- N
- :loop
- s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
- t loop
- s/-\n.*//
- ' >$as_me.lineno &&
- chmod +x "$as_me.lineno" ||
- { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
- { (exit 1); exit 1; }; }
-
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensitive to this).
- . "./$as_me.lineno"
- # Exit status is that of the last command.
- exit
-}
-
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
- as_dirname=dirname
-else
- as_dirname=false
-fi
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in
--n*)
- case `echo 'x\c'` in
- *c*) ECHO_T=' ';; # ECHO_T is single tab character.
- *) ECHO_C='\c';;
- esac;;
-*)
- ECHO_N='-n';;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-if test -d conf$$.dir; then
- rm -f conf$$.dir/conf$$.file
-else
- rm -f conf$$.dir
- mkdir conf$$.dir
-fi
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
- as_ln_s='ln -s'
- # ... but there are two gotchas:
- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -p'.
- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -p'
-elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
-else
- as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
-rmdir conf$$.dir 2>/dev/null
-
-if mkdir -p . 2>/dev/null; then
- as_mkdir_p=:
-else
- test -d ./-p && rmdir ./-p
- as_mkdir_p=false
-fi
-
-if test -x / >/dev/null 2>&1; then
- as_test_x='test -x'
-else
- if ls -dL / >/dev/null 2>&1; then
- as_ls_L_option=L
- else
- as_ls_L_option=
- fi
- as_test_x='
- eval sh -c '\''
- if test -d "$1"; then
- test -d "$1/.";
- else
- case $1 in
- -*)set "./$1";;
- esac;
- case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
- ???[sx]*):;;*)false;;esac;fi
- '\'' sh
- '
-fi
-as_executable_p=$as_test_x
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-
-exec 7<&0 </dev/null 6>&1
-
-# Name of the host.
-# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
-# so uname gets run too.
-ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
-
-#
-# Initializations.
-#
-ac_default_prefix=/usr/local
-ac_clean_files=
-ac_config_libobj_dir=.
-LIBOBJS=
-cross_compiling=no
-subdirs=
-MFLAGS=
-MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-# Identity of this package.
-PACKAGE_NAME='OpenSSH'
-PACKAGE_TARNAME='openssh'
-PACKAGE_VERSION='Portable'
-PACKAGE_STRING='OpenSSH Portable'
-PACKAGE_BUGREPORT='openssh-unix-dev@mindrot.org'
-
-ac_unique_file="ssh.c"
-# Factoring default headers for most tests.
-ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif
-#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
-# include <string.h>
-#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif"
-
-ac_subst_vars='SHELL
-PATH_SEPARATOR
-PACKAGE_NAME
-PACKAGE_TARNAME
-PACKAGE_VERSION
-PACKAGE_STRING
-PACKAGE_BUGREPORT
-exec_prefix
-prefix
-program_transform_name
-bindir
-sbindir
-libexecdir
-datarootdir
-datadir
-sysconfdir
-sharedstatedir
-localstatedir
-includedir
-oldincludedir
-docdir
-infodir
-htmldir
-dvidir
-pdfdir
-psdir
-libdir
-localedir
-mandir
-DEFS
-ECHO_C
-ECHO_N
-ECHO_T
-LIBS
-build_alias
-host_alias
-target_alias
-CC
-CFLAGS
-LDFLAGS
-CPPFLAGS
-ac_ct_CC
-EXEEXT
-OBJEXT
-build
-build_cpu
-build_vendor
-build_os
-host
-host_cpu
-host_vendor
-host_os
-CPP
-GREP
-EGREP
-AWK
-RANLIB
-INSTALL_PROGRAM
-INSTALL_SCRIPT
-INSTALL_DATA
-AR
-CAT
-KILL
-PERL
-SED
-ENT
-TEST_MINUS_S_SH
-SH
-GROFF
-NROFF
-MANDOC
-TEST_SHELL
-MANFMT
-PATH_GROUPADD_PROG
-PATH_USERADD_PROG
-MAKE_PACKAGE_SUPPORTED
-STARTUP_SCRIPT_SHELL
-LOGIN_PROGRAM_FALLBACK
-PATH_PASSWD_PROG
-LD
-PKGCONFIG
-LIBEDIT
-TEST_SSH_ECC
-COMMENT_OUT_ECC
-SSH_PRIVSEP_USER
-SSHLIBS
-SSHDLIBS
-KRB5CONF
-GSSLIBS
-K5LIBS
-PRIVSEP_PATH
-xauth_path
-STRIP_OPT
-XAUTH_PATH
-MANTYPE
-mansubdir
-user_path
-piddir
-TEST_SSH_IPV6
-TEST_MALLOC_OPTIONS
-UNSUPPORTED_ALGORITHMS
-LIBOBJS
-LTLIBOBJS'
-ac_subst_files=''
- ac_precious_vars='build_alias
-host_alias
-target_alias
-CC
-CFLAGS
-LDFLAGS
-LIBS
-CPPFLAGS
-CPP'
-
-
-# Initialize some variables set by options.
-ac_init_help=
-ac_init_version=false
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-cache_file=/dev/null
-exec_prefix=NONE
-no_create=
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-verbose=
-x_includes=NONE
-x_libraries=NONE
-
-# Installation directory options.
-# These are left unexpanded so users can "make install exec_prefix=/foo"
-# and all the variables that are supposed to be based on exec_prefix
-# by default will actually change.
-# Use braces instead of parens because sh, perl, etc. also accept them.
-# (The list follows the same order as the GNU Coding Standards.)
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datarootdir='${prefix}/share'
-datadir='${datarootdir}'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
-infodir='${datarootdir}/info'
-htmldir='${docdir}'
-dvidir='${docdir}'
-pdfdir='${docdir}'
-psdir='${docdir}'
-libdir='${exec_prefix}/lib'
-localedir='${datarootdir}/locale'
-mandir='${datarootdir}/man'
-
-ac_prev=
-ac_dashdash=
-for ac_option
-do
- # If the previous option needs an argument, assign it.
- if test -n "$ac_prev"; then
- eval $ac_prev=\$ac_option
- ac_prev=
- continue
- fi
-
- case $ac_option in
- *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
- *) ac_optarg=yes ;;
- esac
-
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
- case $ac_dashdash$ac_option in
- --)
- ac_dashdash=yes ;;
-
- -bindir | --bindir | --bindi | --bind | --bin | --bi)
- ac_prev=bindir ;;
- -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir=$ac_optarg ;;
-
- -build | --build | --buil | --bui | --bu)
- ac_prev=build_alias ;;
- -build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build_alias=$ac_optarg ;;
-
- -cache-file | --cache-file | --cache-fil | --cache-fi \
- | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
- ac_prev=cache_file ;;
- -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
- | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file=$ac_optarg ;;
-
- --config-cache | -C)
- cache_file=config.cache ;;
-
- -datadir | --datadir | --datadi | --datad)
- ac_prev=datadir ;;
- -datadir=* | --datadir=* | --datadi=* | --datad=*)
- datadir=$ac_optarg ;;
-
- -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
- | --dataroo | --dataro | --datar)
- ac_prev=datarootdir ;;
- -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
- | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
- datarootdir=$ac_optarg ;;
-
- -disable-* | --disable-*)
- ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid feature name: $ac_feature" >&2
- { (exit 1); exit 1; }; }
- ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
- eval enable_$ac_feature=no ;;
-
- -docdir | --docdir | --docdi | --doc | --do)
- ac_prev=docdir ;;
- -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
- docdir=$ac_optarg ;;
-
- -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
- ac_prev=dvidir ;;
- -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
- dvidir=$ac_optarg ;;
-
- -enable-* | --enable-*)
- ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid feature name: $ac_feature" >&2
- { (exit 1); exit 1; }; }
- ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
- eval enable_$ac_feature=\$ac_optarg ;;
-
- -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
- | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
- | --exec | --exe | --ex)
- ac_prev=exec_prefix ;;
- -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
- | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
- | --exec=* | --exe=* | --ex=*)
- exec_prefix=$ac_optarg ;;
-
- -gas | --gas | --ga | --g)
- # Obsolete; use --with-gas.
- with_gas=yes ;;
-
- -help | --help | --hel | --he | -h)
- ac_init_help=long ;;
- -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
- ac_init_help=recursive ;;
- -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
- ac_init_help=short ;;
-
- -host | --host | --hos | --ho)
- ac_prev=host_alias ;;
- -host=* | --host=* | --hos=* | --ho=*)
- host_alias=$ac_optarg ;;
-
- -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
- ac_prev=htmldir ;;
- -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
- | --ht=*)
- htmldir=$ac_optarg ;;
-
- -includedir | --includedir | --includedi | --included | --include \
- | --includ | --inclu | --incl | --inc)
- ac_prev=includedir ;;
- -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
- | --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir=$ac_optarg ;;
-
- -infodir | --infodir | --infodi | --infod | --info | --inf)
- ac_prev=infodir ;;
- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir=$ac_optarg ;;
-
- -libdir | --libdir | --libdi | --libd)
- ac_prev=libdir ;;
- -libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir=$ac_optarg ;;
-
- -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
- | --libexe | --libex | --libe)
- ac_prev=libexecdir ;;
- -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
- | --libexe=* | --libex=* | --libe=*)
- libexecdir=$ac_optarg ;;
-
- -localedir | --localedir | --localedi | --localed | --locale)
- ac_prev=localedir ;;
- -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
- localedir=$ac_optarg ;;
-
- -localstatedir | --localstatedir | --localstatedi | --localstated \
- | --localstate | --localstat | --localsta | --localst | --locals)
- ac_prev=localstatedir ;;
- -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
- | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
- localstatedir=$ac_optarg ;;
-
- -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
- ac_prev=mandir ;;
- -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir=$ac_optarg ;;
-
- -nfp | --nfp | --nf)
- # Obsolete; use --without-fp.
- with_fp=no ;;
-
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c | -n)
- no_create=yes ;;
-
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
- no_recursion=yes ;;
-
- -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
- | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
- | --oldin | --oldi | --old | --ol | --o)
- ac_prev=oldincludedir ;;
- -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
- | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
- | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir=$ac_optarg ;;
-
- -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
- ac_prev=prefix ;;
- -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix=$ac_optarg ;;
-
- -program-prefix | --program-prefix | --program-prefi | --program-pref \
- | --program-pre | --program-pr | --program-p)
- ac_prev=program_prefix ;;
- -program-prefix=* | --program-prefix=* | --program-prefi=* \
- | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix=$ac_optarg ;;
-
- -program-suffix | --program-suffix | --program-suffi | --program-suff \
- | --program-suf | --program-su | --program-s)
- ac_prev=program_suffix ;;
- -program-suffix=* | --program-suffix=* | --program-suffi=* \
- | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix=$ac_optarg ;;
-
- -program-transform-name | --program-transform-name \
- | --program-transform-nam | --program-transform-na \
- | --program-transform-n | --program-transform- \
- | --program-transform | --program-transfor \
- | --program-transfo | --program-transf \
- | --program-trans | --program-tran \
- | --progr-tra | --program-tr | --program-t)
- ac_prev=program_transform_name ;;
- -program-transform-name=* | --program-transform-name=* \
- | --program-transform-nam=* | --program-transform-na=* \
- | --program-transform-n=* | --program-transform-=* \
- | --program-transform=* | --program-transfor=* \
- | --program-transfo=* | --program-transf=* \
- | --program-trans=* | --program-tran=* \
- | --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name=$ac_optarg ;;
-
- -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
- ac_prev=pdfdir ;;
- -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
- pdfdir=$ac_optarg ;;
-
- -psdir | --psdir | --psdi | --psd | --ps)
- ac_prev=psdir ;;
- -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
- psdir=$ac_optarg ;;
-
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- silent=yes ;;
-
- -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
- ac_prev=sbindir ;;
- -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
- | --sbi=* | --sb=*)
- sbindir=$ac_optarg ;;
-
- -sharedstatedir | --sharedstatedir | --sharedstatedi \
- | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
- | --sharedst | --shareds | --shared | --share | --shar \
- | --sha | --sh)
- ac_prev=sharedstatedir ;;
- -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
- | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
- | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
- | --sha=* | --sh=*)
- sharedstatedir=$ac_optarg ;;
-
- -site | --site | --sit)
- ac_prev=site ;;
- -site=* | --site=* | --sit=*)
- site=$ac_optarg ;;
-
- -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
- ac_prev=srcdir ;;
- -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir=$ac_optarg ;;
-
- -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
- | --syscon | --sysco | --sysc | --sys | --sy)
- ac_prev=sysconfdir ;;
- -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
- | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir=$ac_optarg ;;
-
- -target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target_alias ;;
- -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target_alias=$ac_optarg ;;
-
- -v | -verbose | --verbose | --verbos | --verbo | --verb)
- verbose=yes ;;
-
- -version | --version | --versio | --versi | --vers | -V)
- ac_init_version=: ;;
-
- -with-* | --with-*)
- ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid package name: $ac_package" >&2
- { (exit 1); exit 1; }; }
- ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
- eval with_$ac_package=\$ac_optarg ;;
-
- -without-* | --without-*)
- ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid package name: $ac_package" >&2
- { (exit 1); exit 1; }; }
- ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
- eval with_$ac_package=no ;;
-
- --x)
- # Obsolete; use --with-x.
- with_x=yes ;;
-
- -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
- | --x-incl | --x-inc | --x-in | --x-i)
- ac_prev=x_includes ;;
- -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
- | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes=$ac_optarg ;;
-
- -x-libraries | --x-libraries | --x-librarie | --x-librari \
- | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
- ac_prev=x_libraries ;;
- -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
- | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries=$ac_optarg ;;
-
- -*) { echo "$as_me: error: unrecognized option: $ac_option
-Try \`$0 --help' for more information." >&2
- { (exit 1); exit 1; }; }
- ;;
-
- *=*)
- ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
- # Reject names that are not valid shell variable names.
- expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
- { (exit 1); exit 1; }; }
- eval $ac_envvar=\$ac_optarg
- export $ac_envvar ;;
-
- *)
- # FIXME: should be removed in autoconf 3.0.
- echo "$as_me: WARNING: you should use --build, --host, --target" >&2
- expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- echo "$as_me: WARNING: invalid host type: $ac_option" >&2
- : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
- ;;
-
- esac
-done
-
-if test -n "$ac_prev"; then
- ac_option=--`echo $ac_prev | sed 's/_/-/g'`
- { echo "$as_me: error: missing argument to $ac_option" >&2
- { (exit 1); exit 1; }; }
-fi
-
-# Be sure to have absolute directory names.
-for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
- datadir sysconfdir sharedstatedir localstatedir includedir \
- oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
- libdir localedir mandir
-do
- eval ac_val=\$$ac_var
- case $ac_val in
- [\\/$]* | ?:[\\/]* ) continue;;
- NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
- esac
- { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
- { (exit 1); exit 1; }; }
-done
-
-# There might be people who depend on the old broken behavior: `$host'
-# used to hold the argument of --host etc.
-# FIXME: To remove some day.
-build=$build_alias
-host=$host_alias
-target=$target_alias
-
-# FIXME: To remove some day.
-if test "x$host_alias" != x; then
- if test "x$build_alias" = x; then
- cross_compiling=maybe
- echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
- If a cross compiler is detected then cross compile mode will be used." >&2
- elif test "x$build_alias" != "x$host_alias"; then
- cross_compiling=yes
- fi
-fi
-
-ac_tool_prefix=
-test -n "$host_alias" && ac_tool_prefix=$host_alias-
-
-test "$silent" = yes && exec 6>/dev/null
-
-
-ac_pwd=`pwd` && test -n "$ac_pwd" &&
-ac_ls_di=`ls -di .` &&
-ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
- { echo "$as_me: error: Working directory cannot be determined" >&2
- { (exit 1); exit 1; }; }
-test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
- { echo "$as_me: error: pwd does not report name of working directory" >&2
- { (exit 1); exit 1; }; }
-
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
- ac_srcdir_defaulted=yes
- # Try the directory containing this script, then the parent directory.
- ac_confdir=`$as_dirname -- "$0" ||
-$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$0" : 'X\(//\)[^/]' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-echo X"$0" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- srcdir=$ac_confdir
- if test ! -r "$srcdir/$ac_unique_file"; then
- srcdir=..
- fi
-else
- ac_srcdir_defaulted=no
-fi
-if test ! -r "$srcdir/$ac_unique_file"; then
- test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
- { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
- { (exit 1); exit 1; }; }
-fi
-ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
-ac_abs_confdir=`(
- cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
- { (exit 1); exit 1; }; }
- pwd)`
-# When building in place, set srcdir=.
-if test "$ac_abs_confdir" = "$ac_pwd"; then
- srcdir=.
-fi
-# Remove unnecessary trailing slashes from srcdir.
-# Double slashes in file names in object file debugging info
-# mess up M-x gdb in Emacs.
-case $srcdir in
-*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
-esac
-for ac_var in $ac_precious_vars; do
- eval ac_env_${ac_var}_set=\${${ac_var}+set}
- eval ac_env_${ac_var}_value=\$${ac_var}
- eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
- eval ac_cv_env_${ac_var}_value=\$${ac_var}
-done
-
-#
-# Report the --help message.
-#
-if test "$ac_init_help" = "long"; then
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat <<_ACEOF
-\`configure' configures OpenSSH Portable to adapt to many kinds of systems.
-
-Usage: $0 [OPTION]... [VAR=VALUE]...
-
-To assign environment variables (e.g., CC, CFLAGS...), specify them as
-VAR=VALUE. See below for descriptions of some of the useful variables.
-
-Defaults for the options are specified in brackets.
-
-Configuration:
- -h, --help display this help and exit
- --help=short display options specific to this package
- --help=recursive display the short help of all the included packages
- -V, --version display version information and exit
- -q, --quiet, --silent do not print \`checking...' messages
- --cache-file=FILE cache test results in FILE [disabled]
- -C, --config-cache alias for \`--cache-file=config.cache'
- -n, --no-create do not create output files
- --srcdir=DIR find the sources in DIR [configure dir or \`..']
-
-Installation directories:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [PREFIX]
-
-By default, \`make install' will install all the files in
-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
-an installation prefix other than \`$ac_default_prefix' using \`--prefix',
-for instance \`--prefix=\$HOME'.
-
-For better control, use the options below.
-
-Fine tuning of the installation directories:
- --bindir=DIR user executables [EPREFIX/bin]
- --sbindir=DIR system admin executables [EPREFIX/sbin]
- --libexecdir=DIR program executables [EPREFIX/libexec]
- --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data [PREFIX/var]
- --libdir=DIR object code libraries [EPREFIX/lib]
- --includedir=DIR C header files [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc [/usr/include]
- --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
- --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
- --infodir=DIR info documentation [DATAROOTDIR/info]
- --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
- --mandir=DIR man documentation [DATAROOTDIR/man]
- --docdir=DIR documentation root [DATAROOTDIR/doc/openssh]
- --htmldir=DIR html documentation [DOCDIR]
- --dvidir=DIR dvi documentation [DOCDIR]
- --pdfdir=DIR pdf documentation [DOCDIR]
- --psdir=DIR ps documentation [DOCDIR]
-_ACEOF
-
- cat <<\_ACEOF
-
-System types:
- --build=BUILD configure for building on BUILD [guessed]
- --host=HOST cross-compile to build programs to run on HOST [BUILD]
-_ACEOF
-fi
-
-if test -n "$ac_init_help"; then
- case $ac_init_help in
- short | recursive ) echo "Configuration of OpenSSH Portable:";;
- esac
- cat <<\_ACEOF
-
-Optional Features:
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --disable-largefile omit support for large files
- --disable-strip Disable calling strip(1) on install
- --disable-etc-default-login Disable using PATH from /etc/default/login no
- --disable-lastlog disable use of lastlog even if detected no
- --disable-utmp disable use of utmp even if detected no
- --disable-utmpx disable use of utmpx even if detected no
- --disable-wtmp disable use of wtmp even if detected no
- --disable-wtmpx disable use of wtmpx even if detected no
- --disable-libutil disable use of libutil (login() etc.) no
- --disable-pututline disable use of pututline() etc. (uwtmp) no
- --disable-pututxline disable use of pututxline() etc. (uwtmpx) no
-
-Optional Packages:
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL**
- --without-ssh1 Disable support for SSH protocol 1
- --without-stackprotect Don't use compiler's stack protection
- --without-hardening Don't use toolchain hardening flags
- --without-rpath Disable auto-added -R linker paths
- --with-cflags Specify additional flags to pass to compiler
- --with-cppflags Specify additional flags to pass to preprocessor
- --with-ldflags Specify additional flags to pass to linker
- --with-libs Specify additional libraries to link with
- --with-Werror Build main code with -Werror
- --with-solaris-contracts Enable Solaris process contracts (experimental)
- --with-solaris-projects Enable Solaris projects (experimental)
- --with-osfsia Enable Digital Unix SIA
- --with-zlib=PATH Use zlib in PATH
- --without-zlib-version-check Disable zlib version check
- --with-skey[=PATH] Enable S/Key support (optionally in PATH)
- --with-ldns[=PATH] Use ldns for DNSSEC support (optionally in PATH)
- --with-libedit[=PATH] Enable libedit support for sftp
- --with-audit=module Enable audit support (modules=debug,bsm,linux)
- --with-pie Build Position Independent Executables if possible
- --with-ssl-dir=PATH Specify path to OpenSSL installation
- --without-openssl-header-check Disable OpenSSL version consistency check
- --with-ssl-engine Enable OpenSSL (hardware) ENGINE support
- --with-prngd-port=PORT read entropy from PRNGD/EGD TCP localhost:PORT
- --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)
- --with-pam Enable PAM support
- --with-privsep-user=user Specify non-privileged user for privilege separation
- --with-sandbox=style Specify privilege separation sandbox (no, darwin, rlimit, systrace, seccomp_filter, capsicum)
- --with-selinux Enable SELinux support
- --with-kerberos5=PATH Enable Kerberos 5 support
- --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty)
- --with-xauth=PATH Specify path to xauth program
- --with-maildir=/path/to/mail Specify your system mail directory
- --with-mantype=man|cat|doc Set man page type
- --with-md5-passwords Enable use of MD5 passwords
- --without-shadow Disable shadow password support
- --with-ipaddr-display Use ip address instead of hostname in \$DISPLAY
- --with-default-path= Specify default \$PATH environment for server
- --with-superuser-path= Specify different path for super-user
- --with-4in6 Check for and convert IPv4 in IPv6 mapped addresses
- --with-bsd-auth Enable BSD auth support
- --with-pid-dir=PATH Specify location of ssh.pid file
- --with-lastlog=FILE|DIR specify lastlog location common locations
-
-Some influential environment variables:
- CC C compiler command
- CFLAGS C compiler flags
- LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
- nonstandard directory <lib dir>
- LIBS libraries to pass to the linker, e.g. -l<library>
- CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
- you have headers in a nonstandard directory <include dir>
- CPP C preprocessor
-
-Use these variables to override the choices made by `configure' or to help
-it to find libraries and programs with nonstandard names/locations.
-
-Report bugs to <openssh-unix-dev@mindrot.org>.
-_ACEOF
-ac_status=$?
-fi
-
-if test "$ac_init_help" = "recursive"; then
- # If there are subdirs, report their specific --help.
- for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
- test -d "$ac_dir" || continue
- ac_builddir=.
-
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
- ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
- # A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
- case $ac_top_builddir_sub in
- "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
- *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
- esac ;;
-esac
-ac_abs_top_builddir=$ac_pwd
-ac_abs_builddir=$ac_pwd$ac_dir_suffix
-# for backward compatibility:
-ac_top_builddir=$ac_top_build_prefix
-
-case $srcdir in
- .) # We are building in place.
- ac_srcdir=.
- ac_top_srcdir=$ac_top_builddir_sub
- ac_abs_top_srcdir=$ac_pwd ;;
- [\\/]* | ?:[\\/]* ) # Absolute name.
- ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir
- ac_abs_top_srcdir=$srcdir ;;
- *) # Relative name.
- ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_build_prefix$srcdir
- ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
-esac
-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
-
- cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
- if test -f "$ac_srcdir/configure.gnu"; then
- echo &&
- $SHELL "$ac_srcdir/configure.gnu" --help=recursive
- elif test -f "$ac_srcdir/configure"; then
- echo &&
- $SHELL "$ac_srcdir/configure" --help=recursive
- else
- echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
- fi || ac_status=$?
- cd "$ac_pwd" || { ac_status=$?; break; }
- done
-fi
-
-test -n "$ac_init_help" && exit $ac_status
-if $ac_init_version; then
- cat <<\_ACEOF
-OpenSSH configure Portable
-generated by GNU Autoconf 2.61
-
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-This configure script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it.
-_ACEOF
- exit
-fi
-cat >config.log <<_ACEOF
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by OpenSSH $as_me Portable, which was
-generated by GNU Autoconf 2.61. Invocation command line was
-
- $ $0 $@
-
-_ACEOF
-exec 5>>config.log
-{
-cat <<_ASUNAME
-## --------- ##
-## Platform. ##
-## --------- ##
-
-hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
-/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
-
-/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
-/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
-/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
-
-_ASUNAME
-
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- echo "PATH: $as_dir"
-done
-IFS=$as_save_IFS
-
-} >&5
-
-cat >&5 <<_ACEOF
-
-
-## ----------- ##
-## Core tests. ##
-## ----------- ##
-
-_ACEOF
-
-
-# Keep a trace of the command line.
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Strip out --silent because we don't want to record it for future runs.
-# Also quote any args containing shell meta-characters.
-# Make two passes to allow for proper duplicate-argument suppression.
-ac_configure_args=
-ac_configure_args0=
-ac_configure_args1=
-ac_must_keep_next=false
-for ac_pass in 1 2
-do
- for ac_arg
- do
- case $ac_arg in
- -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- continue ;;
- *\'*)
- ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
- esac
- case $ac_pass in
- 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
- 2)
- ac_configure_args1="$ac_configure_args1 '$ac_arg'"
- if test $ac_must_keep_next = true; then
- ac_must_keep_next=false # Got value, back to normal.
- else
- case $ac_arg in
- *=* | --config-cache | -C | -disable-* | --disable-* \
- | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
- | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
- | -with-* | --with-* | -without-* | --without-* | --x)
- case "$ac_configure_args0 " in
- "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
- esac
- ;;
- -* ) ac_must_keep_next=true ;;
- esac
- fi
- ac_configure_args="$ac_configure_args '$ac_arg'"
- ;;
- esac
- done
-done
-$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
-$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
-
-# When interrupted or exit'd, cleanup temporary files, and complete
-# config.log. We remove comments because anyway the quotes in there
-# would cause problems or look ugly.
-# WARNING: Use '\'' to represent an apostrophe within the trap.
-# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
-trap 'exit_status=$?
- # Save into config.log some information that might help in debugging.
- {
- echo
-
- cat <<\_ASBOX
-## ---------------- ##
-## Cache variables. ##
-## ---------------- ##
-_ASBOX
- echo
- # The following way of writing the cache mishandles newlines in values,
-(
- for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
- eval ac_val=\$$ac_var
- case $ac_val in #(
- *${as_nl}*)
- case $ac_var in #(
- *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
-echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
- esac
- case $ac_var in #(
- _ | IFS | as_nl) ;; #(
- *) $as_unset $ac_var ;;
- esac ;;
- esac
- done
- (set) 2>&1 |
- case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
- *${as_nl}ac_space=\ *)
- sed -n \
- "s/'\''/'\''\\\\'\'''\''/g;
- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
- ;; #(
- *)
- sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
- ;;
- esac |
- sort
-)
- echo
-
- cat <<\_ASBOX
-## ----------------- ##
-## Output variables. ##
-## ----------------- ##
-_ASBOX
- echo
- for ac_var in $ac_subst_vars
- do
- eval ac_val=\$$ac_var
- case $ac_val in
- *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
- esac
- echo "$ac_var='\''$ac_val'\''"
- done | sort
- echo
-
- if test -n "$ac_subst_files"; then
- cat <<\_ASBOX
-## ------------------- ##
-## File substitutions. ##
-## ------------------- ##
-_ASBOX
- echo
- for ac_var in $ac_subst_files
- do
- eval ac_val=\$$ac_var
- case $ac_val in
- *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
- esac
- echo "$ac_var='\''$ac_val'\''"
- done | sort
- echo
- fi
-
- if test -s confdefs.h; then
- cat <<\_ASBOX
-## ----------- ##
-## confdefs.h. ##
-## ----------- ##
-_ASBOX
- echo
- cat confdefs.h
- echo
- fi
- test "$ac_signal" != 0 &&
- echo "$as_me: caught signal $ac_signal"
- echo "$as_me: exit $exit_status"
- } >&5
- rm -f core *.core core.conftest.* &&
- rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
- exit $exit_status
-' 0
-for ac_signal in 1 2 13 15; do
- trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
-done
-ac_signal=0
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -f -r conftest* confdefs.h
-
-# Predefined preprocessor variables.
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
-
-
-# Let the site file select an alternate cache file if it wants to.
-# Prefer explicitly selected file to automatically selected ones.
-if test -n "$CONFIG_SITE"; then
- set x "$CONFIG_SITE"
-elif test "x$prefix" != xNONE; then
- set x "$prefix/share/config.site" "$prefix/etc/config.site"
-else
- set x "$ac_default_prefix/share/config.site" \
- "$ac_default_prefix/etc/config.site"
-fi
-shift
-for ac_site_file
-do
- if test -r "$ac_site_file"; then
- { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
-echo "$as_me: loading site script $ac_site_file" >&6;}
- sed 's/^/| /' "$ac_site_file" >&5
- . "$ac_site_file"
- fi
-done
-
-if test -r "$cache_file"; then
- # Some versions of bash will fail to source /dev/null (special
- # files actually), so we avoid doing that.
- if test -f "$cache_file"; then
- { echo "$as_me:$LINENO: loading cache $cache_file" >&5
-echo "$as_me: loading cache $cache_file" >&6;}
- case $cache_file in
- [\\/]* | ?:[\\/]* ) . "$cache_file";;
- *) . "./$cache_file";;
- esac
- fi
-else
- { echo "$as_me:$LINENO: creating cache $cache_file" >&5
-echo "$as_me: creating cache $cache_file" >&6;}
- >$cache_file
-fi
-
-# Check that the precious variables saved in the cache have kept the same
-# value.
-ac_cache_corrupted=false
-for ac_var in $ac_precious_vars; do
- eval ac_old_set=\$ac_cv_env_${ac_var}_set
- eval ac_new_set=\$ac_env_${ac_var}_set
- eval ac_old_val=\$ac_cv_env_${ac_var}_value
- eval ac_new_val=\$ac_env_${ac_var}_value
- case $ac_old_set,$ac_new_set in
- set,)
- { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
- ac_cache_corrupted=: ;;
- ,set)
- { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
- ac_cache_corrupted=: ;;
- ,);;
- *)
- if test "x$ac_old_val" != "x$ac_new_val"; then
- { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
-echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
- { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
-echo "$as_me: former value: $ac_old_val" >&2;}
- { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
-echo "$as_me: current value: $ac_new_val" >&2;}
- ac_cache_corrupted=:
- fi;;
- esac
- # Pass precious variables to config.status.
- if test "$ac_new_set" = set; then
- case $ac_new_val in
- *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
- *) ac_arg=$ac_var=$ac_new_val ;;
- esac
- case " $ac_configure_args " in
- *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
- *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
- esac
- fi
-done
-if $ac_cache_corrupted; then
- { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
-echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
-echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-ac_config_headers="$ac_config_headers config.h"
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_CC="${ac_tool_prefix}gcc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_CC"; then
- ac_ct_CC=$CC
- # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_ac_ct_CC="gcc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
- if test "x$ac_ct_CC" = x; then
- CC=""
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
- CC=$ac_ct_CC
- fi
-else
- CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_CC="${ac_tool_prefix}cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- fi
-fi
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# != 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
- fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-fi
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- for ac_prog in cl.exe
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- test -n "$CC" && break
- done
-fi
-if test -z "$CC"; then
- ac_ct_CC=$CC
- for ac_prog in cl.exe
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_ac_ct_CC="$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- test -n "$ac_ct_CC" && break
-done
-
- if test "x$ac_ct_CC" = x; then
- CC=""
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
- CC=$ac_ct_CC
- fi
-fi
-
-fi
-
-
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-
-# Provide some information about the compiler.
-echo "$as_me:$LINENO: checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (ac_try="$ac_compiler --version >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compiler --version >&5") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (ac_try="$ac_compiler -v >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compiler -v >&5") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (ac_try="$ac_compiler -V >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compiler -V >&5") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.exe b.out"
-# Try to create an executable without -o first, disregard a.out.
-# It will help us diagnose broken compilers, and finding out an intuition
-# of exeext.
-{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
-ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-#
-# List of possible output files, starting from the most likely.
-# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
-# only as a last resort. b.out is created by i960 compilers.
-ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
-#
-# The IRIX 6 linker writes into existing files which may not be
-# executable, retaining their permissions. Remove them first so a
-# subsequent execution test works.
-ac_rmfiles=
-for ac_file in $ac_files
-do
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
- * ) ac_rmfiles="$ac_rmfiles $ac_file";;
- esac
-done
-rm -f $ac_rmfiles
-
-if { (ac_try="$ac_link_default"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link_default") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
-# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
-# in a Makefile. We should not override ac_cv_exeext if it was cached,
-# so that the user can short-circuit this test for compilers unknown to
-# Autoconf.
-for ac_file in $ac_files ''
-do
- test -f "$ac_file" || continue
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
- ;;
- [ab].out )
- # We found the default executable, but exeext='' is most
- # certainly right.
- break;;
- *.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
- then :; else
- ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- fi
- # We set ac_cv_exeext here because the later test for it is not
- # safe: cross compilers may not add the suffix if given an `-o'
- # argument, so we may need to know it at that point already.
- # Even if this section looks crufty: it has the advantage of
- # actually working.
- break;;
- * )
- break;;
- esac
-done
-test "$ac_cv_exeext" = no && ac_cv_exeext=
-
-else
- ac_file=''
-fi
-
-{ echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6; }
-if test -z "$ac_file"; then
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
-See \`config.log' for more details." >&5
-echo "$as_me: error: C compiler cannot create executables
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
-fi
-
-ac_exeext=$ac_cv_exeext
-
-# Check that the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
-# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
- if { ac_try='./$ac_file'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- cross_compiling=no
- else
- if test "$cross_compiling" = maybe; then
- cross_compiling=yes
- else
- { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
- fi
- fi
-fi
-{ echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-rm -f a.out a.exe conftest$ac_cv_exeext b.out
-ac_clean_files=$ac_clean_files_save
-# Check that the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
-{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
-echo "${ECHO_T}$cross_compiling" >&6; }
-
-{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
-echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- # If both `conftest.exe' and `conftest' are `present' (well, observable)
-# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
-# work properly (i.e., refer to `conftest.exe'), while it won't with
-# `rm'.
-for ac_file in conftest.exe conftest conftest.*; do
- test -f "$ac_file" || continue
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
- *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- break;;
- * ) break;;
- esac
-done
-else
- { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest$ac_cv_exeext
-{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
-echo "${ECHO_T}$ac_cv_exeext" >&6; }
-
-rm -f conftest.$ac_ext
-EXEEXT=$ac_cv_exeext
-ac_exeext=$EXEEXT
-{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
-echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
-if test "${ac_cv_objext+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.o conftest.obj
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- for ac_file in conftest.o conftest.obj conftest.*; do
- test -f "$ac_file" || continue;
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
- *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
- break;;
- esac
-done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
-echo "${ECHO_T}$ac_cv_objext" >&6; }
-OBJEXT=$ac_cv_objext
-ac_objext=$OBJEXT
-{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-#ifndef __GNUC__
- choke me
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_compiler_gnu=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_compiler_gnu=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
-GCC=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_g+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_save_c_werror_flag=$ac_c_werror_flag
- ac_c_werror_flag=yes
- ac_cv_prog_cc_g=no
- CFLAGS="-g"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_prog_cc_g=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- CFLAGS=""
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_c_werror_flag=$ac_save_c_werror_flag
- CFLAGS="-g"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_prog_cc_g=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_c_werror_flag=$ac_save_c_werror_flag
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
- if test "$GCC" = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-g"
- fi
-else
- if test "$GCC" = yes; then
- CFLAGS="-O2"
- else
- CFLAGS=
- fi
-fi
-{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
-echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_prog_cc_c89=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
-
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
-
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
-_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
- CC="$ac_save_CC $ac_arg"
- rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_prog_cc_c89=$ac_arg
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext
- test "x$ac_cv_prog_cc_c89" != "xno" && break
-done
-rm -f conftest.$ac_ext
-CC=$ac_save_CC
-
-fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6; } ;;
- xno)
- { echo "$as_me:$LINENO: result: unsupported" >&5
-echo "${ECHO_T}unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-ac_aux_dir=
-for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
-echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-
-
-# Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
-echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
- { (exit 1); exit 1; }; }
-
-{ echo "$as_me:$LINENO: checking build system type" >&5
-echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
-if test "${ac_cv_build+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_build_alias=$build_alias
-test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
-test "x$ac_build_alias" = x &&
- { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
-echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
- { (exit 1); exit 1; }; }
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
-echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
- { (exit 1); exit 1; }; }
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
-echo "${ECHO_T}$ac_cv_build" >&6; }
-case $ac_cv_build in
-*-*-*) ;;
-*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
-echo "$as_me: error: invalid value of canonical build" >&2;}
- { (exit 1); exit 1; }; };;
-esac
-build=$ac_cv_build
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_build
-shift
-build_cpu=$1
-build_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-build_os=$*
-IFS=$ac_save_IFS
-case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-
-
-{ echo "$as_me:$LINENO: checking host system type" >&5
-echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
-if test "${ac_cv_host+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test "x$host_alias" = x; then
- ac_cv_host=$ac_cv_build
-else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
-echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
-echo "${ECHO_T}$ac_cv_host" >&6; }
-case $ac_cv_host in
-*-*-*) ;;
-*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
-echo "$as_me: error: invalid value of canonical host" >&2;}
- { (exit 1); exit 1; }; };;
-esac
-host=$ac_cv_host
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_host
-shift
-host_cpu=$1
-host_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-host_os=$*
-IFS=$ac_save_IFS
-case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if test "${ac_cv_prog_CPP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Broken: fails on valid input.
-continue
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- # Broken: success on invalid input.
-continue
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ echo "$as_me:$LINENO: result: $CPP" >&5
-echo "${ECHO_T}$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Broken: fails on valid input.
-continue
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- # Broken: success on invalid input.
-continue
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
- :
-else
- { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
-echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
-if test "${ac_cv_path_GREP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- # Extract the first word of "grep ggrep" to use in msg output
-if test -z "$GREP"; then
-set dummy grep ggrep; ac_prog_name=$2
-if test "${ac_cv_path_GREP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_path_GREP_found=false
-# Loop through the user's path and test for each of PROGNAME-LIST
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
- # Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- ac_count=`expr $ac_count + 1`
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
-
- $ac_path_GREP_found && break 3
- done
-done
-
-done
-IFS=$as_save_IFS
-
-
-fi
-
-GREP="$ac_cv_path_GREP"
-if test -z "$GREP"; then
- { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-else
- ac_cv_path_GREP=$GREP
-fi
-
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
-echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ echo "$as_me:$LINENO: checking for egrep" >&5
-echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
-if test "${ac_cv_path_EGREP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- # Extract the first word of "egrep" to use in msg output
-if test -z "$EGREP"; then
-set dummy egrep; ac_prog_name=$2
-if test "${ac_cv_path_EGREP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_path_EGREP_found=false
-# Loop through the user's path and test for each of PROGNAME-LIST
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
- # Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- ac_count=`expr $ac_count + 1`
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
-
- $ac_path_EGREP_found && break 3
- done
-done
-
-done
-IFS=$as_save_IFS
-
-
-fi
-
-EGREP="$ac_cv_path_EGREP"
-if test -z "$EGREP"; then
- { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
-
- fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
-echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_header_stdc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_header_stdc=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then
- :
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then
- :
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then
- :
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
-_ACEOF
-
-fi
-
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-
-
-
-
-
-
-
-
-
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- eval "$as_ac_Header=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_Header=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
-echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; }
-if test "${ac_cv_c_bigendian+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- # See if sys/param.h defines the BYTE_ORDER macro.
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/param.h>
-
-int
-main ()
-{
-#if ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \
- && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN)
- bogus endian macros
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- # It does; now see whether it defined to BIG_ENDIAN or not.
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/param.h>
-
-int
-main ()
-{
-#if BYTE_ORDER != BIG_ENDIAN
- not big endian
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_c_bigendian=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_c_bigendian=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # It does not; compile a test program.
-if test "$cross_compiling" = yes; then
- # try to guess the endianness by grepping values into an object file
- ac_cv_c_bigendian=unknown
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
-short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
-void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
-short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
-short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
-void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
-int
-main ()
-{
- _ascii (); _ebcdic ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
- ac_cv_c_bigendian=yes
-fi
-if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
- if test "$ac_cv_c_bigendian" = unknown; then
- ac_cv_c_bigendian=no
- else
- # finding both strings is unlikely to happen, but who knows?
- ac_cv_c_bigendian=unknown
- fi
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-
- /* Are we little or big endian? From Harbison&Steele. */
- union
- {
- long int l;
- char c[sizeof (long int)];
- } u;
- u.l = 1;
- return u.c[sizeof (long int) - 1] == 1;
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_c_bigendian=no
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_c_bigendian=yes
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
-echo "${ECHO_T}$ac_cv_c_bigendian" >&6; }
-case $ac_cv_c_bigendian in
- yes)
-
-cat >>confdefs.h <<\_ACEOF
-#define WORDS_BIGENDIAN 1
-_ACEOF
- ;;
- no)
- ;;
- *)
- { { echo "$as_me:$LINENO: error: unknown endianness
-presetting ac_cv_c_bigendian=no (or yes) will help" >&5
-echo "$as_me: error: unknown endianness
-presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
- { (exit 1); exit 1; }; } ;;
-esac
-
-
-# Checks for programs.
-for ac_prog in gawk mawk nawk awk
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_AWK+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$AWK"; then
- ac_cv_prog_AWK="$AWK" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_AWK="$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-AWK=$ac_cv_prog_AWK
-if test -n "$AWK"; then
- { echo "$as_me:$LINENO: result: $AWK" >&5
-echo "${ECHO_T}$AWK" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- test -n "$AWK" && break
-done
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if test "${ac_cv_prog_CPP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Broken: fails on valid input.
-continue
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- # Broken: success on invalid input.
-continue
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ echo "$as_me:$LINENO: result: $CPP" >&5
-echo "${ECHO_T}$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Broken: fails on valid input.
-continue
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- # Broken: success on invalid input.
-continue
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
- :
-else
- { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_RANLIB+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$RANLIB"; then
- ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-RANLIB=$ac_cv_prog_RANLIB
-if test -n "$RANLIB"; then
- { echo "$as_me:$LINENO: result: $RANLIB" >&5
-echo "${ECHO_T}$RANLIB" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_RANLIB"; then
- ac_ct_RANLIB=$RANLIB
- # Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_RANLIB"; then
- ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_ac_ct_RANLIB="ranlib"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
-if test -n "$ac_ct_RANLIB"; then
- { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
-echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
- if test "x$ac_ct_RANLIB" = x; then
- RANLIB=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
- RANLIB=$ac_ct_RANLIB
- fi
-else
- RANLIB="$ac_cv_prog_RANLIB"
-fi
-
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AmigaOS /C/install, which installs bootblocks on floppy discs
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# OS/2's system install, which has a completely different semantic
-# ./install, which can be erroneously created by make from ./install.sh.
-{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
-echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
-if test -z "$INSTALL"; then
-if test "${ac_cv_path_install+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in
- ./ | .// | /cC/* | \
- /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
- ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
- /usr/ucb/* ) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
- if test $ac_prog = install &&
- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- elif test $ac_prog = install &&
- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # program-specific install script used by HP pwplus--don't use.
- :
- else
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
- break 3
- fi
- fi
- done
- done
- ;;
-esac
-done
-IFS=$as_save_IFS
-
-
-fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL=$ac_cv_path_install
- else
- # As a last resort, use the slow shell script. Don't cache a
- # value for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the value is a relative name.
- INSTALL=$ac_install_sh
- fi
-fi
-{ echo "$as_me:$LINENO: result: $INSTALL" >&5
-echo "${ECHO_T}$INSTALL" >&6; }
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-{ echo "$as_me:$LINENO: checking for egrep" >&5
-echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
-if test "${ac_cv_path_EGREP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- # Extract the first word of "egrep" to use in msg output
-if test -z "$EGREP"; then
-set dummy egrep; ac_prog_name=$2
-if test "${ac_cv_path_EGREP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_path_EGREP_found=false
-# Loop through the user's path and test for each of PROGNAME-LIST
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
- # Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- ac_count=`expr $ac_count + 1`
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
-
- $ac_path_EGREP_found && break 3
- done
-done
-
-done
-IFS=$as_save_IFS
-
-
-fi
-
-EGREP="$ac_cv_path_EGREP"
-if test -z "$EGREP"; then
- { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
-
- fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
-echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-# Extract the first word of "ar", so it can be a program name with args.
-set dummy ar; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_AR+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $AR in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_AR="$AR" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-AR=$ac_cv_path_AR
-if test -n "$AR"; then
- { echo "$as_me:$LINENO: result: $AR" >&5
-echo "${ECHO_T}$AR" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-# Extract the first word of "cat", so it can be a program name with args.
-set dummy cat; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_CAT+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $CAT in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_CAT="$CAT" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_CAT="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-CAT=$ac_cv_path_CAT
-if test -n "$CAT"; then
- { echo "$as_me:$LINENO: result: $CAT" >&5
-echo "${ECHO_T}$CAT" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-# Extract the first word of "kill", so it can be a program name with args.
-set dummy kill; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_KILL+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $KILL in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_KILL="$KILL" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_KILL="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-KILL=$ac_cv_path_KILL
-if test -n "$KILL"; then
- { echo "$as_me:$LINENO: result: $KILL" >&5
-echo "${ECHO_T}$KILL" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-for ac_prog in perl5 perl
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_PERL+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $PERL in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-PERL=$ac_cv_path_PERL
-if test -n "$PERL"; then
- { echo "$as_me:$LINENO: result: $PERL" >&5
-echo "${ECHO_T}$PERL" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- test -n "$PERL" && break
-done
-
-# Extract the first word of "sed", so it can be a program name with args.
-set dummy sed; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_SED+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $SED in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_SED="$SED" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-SED=$ac_cv_path_SED
-if test -n "$SED"; then
- { echo "$as_me:$LINENO: result: $SED" >&5
-echo "${ECHO_T}$SED" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-
-# Extract the first word of "ent", so it can be a program name with args.
-set dummy ent; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_ENT+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $ENT in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_ENT="$ENT" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_ENT="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-ENT=$ac_cv_path_ENT
-if test -n "$ENT"; then
- { echo "$as_me:$LINENO: result: $ENT" >&5
-echo "${ECHO_T}$ENT" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-
-# Extract the first word of "bash", so it can be a program name with args.
-set dummy bash; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_TEST_MINUS_S_SH+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $TEST_MINUS_S_SH in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_TEST_MINUS_S_SH="$TEST_MINUS_S_SH" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_TEST_MINUS_S_SH="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-TEST_MINUS_S_SH=$ac_cv_path_TEST_MINUS_S_SH
-if test -n "$TEST_MINUS_S_SH"; then
- { echo "$as_me:$LINENO: result: $TEST_MINUS_S_SH" >&5
-echo "${ECHO_T}$TEST_MINUS_S_SH" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-# Extract the first word of "ksh", so it can be a program name with args.
-set dummy ksh; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_TEST_MINUS_S_SH+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $TEST_MINUS_S_SH in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_TEST_MINUS_S_SH="$TEST_MINUS_S_SH" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_TEST_MINUS_S_SH="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-TEST_MINUS_S_SH=$ac_cv_path_TEST_MINUS_S_SH
-if test -n "$TEST_MINUS_S_SH"; then
- { echo "$as_me:$LINENO: result: $TEST_MINUS_S_SH" >&5
-echo "${ECHO_T}$TEST_MINUS_S_SH" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-# Extract the first word of "sh", so it can be a program name with args.
-set dummy sh; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_TEST_MINUS_S_SH+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $TEST_MINUS_S_SH in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_TEST_MINUS_S_SH="$TEST_MINUS_S_SH" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_TEST_MINUS_S_SH="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-TEST_MINUS_S_SH=$ac_cv_path_TEST_MINUS_S_SH
-if test -n "$TEST_MINUS_S_SH"; then
- { echo "$as_me:$LINENO: result: $TEST_MINUS_S_SH" >&5
-echo "${ECHO_T}$TEST_MINUS_S_SH" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-# Extract the first word of "sh", so it can be a program name with args.
-set dummy sh; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_SH+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $SH in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_SH="$SH" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_SH="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-SH=$ac_cv_path_SH
-if test -n "$SH"; then
- { echo "$as_me:$LINENO: result: $SH" >&5
-echo "${ECHO_T}$SH" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-# Extract the first word of "groff", so it can be a program name with args.
-set dummy groff; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_GROFF+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $GROFF in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_GROFF="$GROFF" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_GROFF="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-GROFF=$ac_cv_path_GROFF
-if test -n "$GROFF"; then
- { echo "$as_me:$LINENO: result: $GROFF" >&5
-echo "${ECHO_T}$GROFF" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-# Extract the first word of "nroff", so it can be a program name with args.
-set dummy nroff; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_NROFF+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $NROFF in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_NROFF="$NROFF" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_NROFF="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-NROFF=$ac_cv_path_NROFF
-if test -n "$NROFF"; then
- { echo "$as_me:$LINENO: result: $NROFF" >&5
-echo "${ECHO_T}$NROFF" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-# Extract the first word of "mandoc", so it can be a program name with args.
-set dummy mandoc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_MANDOC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $MANDOC in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_MANDOC="$MANDOC" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_MANDOC="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-MANDOC=$ac_cv_path_MANDOC
-if test -n "$MANDOC"; then
- { echo "$as_me:$LINENO: result: $MANDOC" >&5
-echo "${ECHO_T}$MANDOC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-TEST_SHELL=sh
-
-
-if test "x$MANDOC" != "x" ; then
- MANFMT="$MANDOC"
-elif test "x$NROFF" != "x" ; then
- MANFMT="$NROFF -mandoc"
-elif test "x$GROFF" != "x" ; then
- MANFMT="$GROFF -mandoc -Tascii"
-else
- { echo "$as_me:$LINENO: WARNING: no manpage formatted found" >&5
-echo "$as_me: WARNING: no manpage formatted found" >&2;}
- MANFMT="false"
-fi
-
-
-# Extract the first word of "groupadd", so it can be a program name with args.
-set dummy groupadd; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_PATH_GROUPADD_PROG+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $PATH_GROUPADD_PROG in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_PATH_GROUPADD_PROG="$PATH_GROUPADD_PROG" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /usr/sbin${PATH_SEPARATOR}/etc
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_PATH_GROUPADD_PROG="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- test -z "$ac_cv_path_PATH_GROUPADD_PROG" && ac_cv_path_PATH_GROUPADD_PROG="groupadd"
- ;;
-esac
-fi
-PATH_GROUPADD_PROG=$ac_cv_path_PATH_GROUPADD_PROG
-if test -n "$PATH_GROUPADD_PROG"; then
- { echo "$as_me:$LINENO: result: $PATH_GROUPADD_PROG" >&5
-echo "${ECHO_T}$PATH_GROUPADD_PROG" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-# Extract the first word of "useradd", so it can be a program name with args.
-set dummy useradd; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_PATH_USERADD_PROG+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $PATH_USERADD_PROG in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_PATH_USERADD_PROG="$PATH_USERADD_PROG" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /usr/sbin${PATH_SEPARATOR}/etc
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_PATH_USERADD_PROG="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- test -z "$ac_cv_path_PATH_USERADD_PROG" && ac_cv_path_PATH_USERADD_PROG="useradd"
- ;;
-esac
-fi
-PATH_USERADD_PROG=$ac_cv_path_PATH_USERADD_PROG
-if test -n "$PATH_USERADD_PROG"; then
- { echo "$as_me:$LINENO: result: $PATH_USERADD_PROG" >&5
-echo "${ECHO_T}$PATH_USERADD_PROG" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-# Extract the first word of "pkgmk", so it can be a program name with args.
-set dummy pkgmk; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_MAKE_PACKAGE_SUPPORTED+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$MAKE_PACKAGE_SUPPORTED"; then
- ac_cv_prog_MAKE_PACKAGE_SUPPORTED="$MAKE_PACKAGE_SUPPORTED" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_MAKE_PACKAGE_SUPPORTED="yes"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- test -z "$ac_cv_prog_MAKE_PACKAGE_SUPPORTED" && ac_cv_prog_MAKE_PACKAGE_SUPPORTED="no"
-fi
-fi
-MAKE_PACKAGE_SUPPORTED=$ac_cv_prog_MAKE_PACKAGE_SUPPORTED
-if test -n "$MAKE_PACKAGE_SUPPORTED"; then
- { echo "$as_me:$LINENO: result: $MAKE_PACKAGE_SUPPORTED" >&5
-echo "${ECHO_T}$MAKE_PACKAGE_SUPPORTED" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-if test -x /sbin/sh; then
- STARTUP_SCRIPT_SHELL=/sbin/sh
-
-else
- STARTUP_SCRIPT_SHELL=/bin/sh
-
-fi
-
-# System features
-# Check whether --enable-largefile was given.
-if test "${enable_largefile+set}" = set; then
- enableval=$enable_largefile;
-fi
-
-if test "$enable_largefile" != no; then
-
- { echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
-echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6; }
-if test "${ac_cv_sys_largefile_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_sys_largefile_CC=no
- if test "$GCC" != yes; then
- ac_save_CC=$CC
- while :; do
- # IRIX 6.2 and later do not support large files by default,
- # so use the C compiler's -n32 option if that helps.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
- We can't simply define LARGE_OFF_T to be 9223372036854775807,
- since some C++ compilers masquerading as C compilers
- incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
- && LARGE_OFF_T % 2147483647 == 1)
- ? 1 : -1];
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
- rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext
- CC="$CC -n32"
- rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_sys_largefile_CC=' -n32'; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext
- break
- done
- CC=$ac_save_CC
- rm -f conftest.$ac_ext
- fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
-echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6; }
- if test "$ac_cv_sys_largefile_CC" != no; then
- CC=$CC$ac_cv_sys_largefile_CC
- fi
-
- { echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
-echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6; }
-if test "${ac_cv_sys_file_offset_bits+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- while :; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
- We can't simply define LARGE_OFF_T to be 9223372036854775807,
- since some C++ compilers masquerading as C compilers
- incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
- && LARGE_OFF_T % 2147483647 == 1)
- ? 1 : -1];
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_sys_file_offset_bits=no; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#define _FILE_OFFSET_BITS 64
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
- We can't simply define LARGE_OFF_T to be 9223372036854775807,
- since some C++ compilers masquerading as C compilers
- incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
- && LARGE_OFF_T % 2147483647 == 1)
- ? 1 : -1];
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_sys_file_offset_bits=64; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_cv_sys_file_offset_bits=unknown
- break
-done
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
-echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6; }
-case $ac_cv_sys_file_offset_bits in #(
- no | unknown) ;;
- *)
-cat >>confdefs.h <<_ACEOF
-#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
-_ACEOF
-;;
-esac
-rm -f conftest*
- if test $ac_cv_sys_file_offset_bits = unknown; then
- { echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
-echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6; }
-if test "${ac_cv_sys_large_files+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- while :; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
- We can't simply define LARGE_OFF_T to be 9223372036854775807,
- since some C++ compilers masquerading as C compilers
- incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
- && LARGE_OFF_T % 2147483647 == 1)
- ? 1 : -1];
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_sys_large_files=no; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#define _LARGE_FILES 1
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
- We can't simply define LARGE_OFF_T to be 9223372036854775807,
- since some C++ compilers masquerading as C compilers
- incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
- int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
- && LARGE_OFF_T % 2147483647 == 1)
- ? 1 : -1];
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_sys_large_files=1; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_cv_sys_large_files=unknown
- break
-done
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
-echo "${ECHO_T}$ac_cv_sys_large_files" >&6; }
-case $ac_cv_sys_large_files in #(
- no | unknown) ;;
- *)
-cat >>confdefs.h <<_ACEOF
-#define _LARGE_FILES $ac_cv_sys_large_files
-_ACEOF
-;;
-esac
-rm -f conftest*
- fi
-fi
-
-
-if test -z "$AR" ; then
- { { echo "$as_me:$LINENO: error: *** 'ar' missing, please install or fix your \$PATH ***" >&5
-echo "$as_me: error: *** 'ar' missing, please install or fix your \$PATH ***" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-# Use LOGIN_PROGRAM from environment if possible
-if test ! -z "$LOGIN_PROGRAM" ; then
-
-cat >>confdefs.h <<_ACEOF
-#define LOGIN_PROGRAM_FALLBACK "$LOGIN_PROGRAM"
-_ACEOF
-
-else
- # Search for login
- # Extract the first word of "login", so it can be a program name with args.
-set dummy login; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_LOGIN_PROGRAM_FALLBACK+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $LOGIN_PROGRAM_FALLBACK in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_LOGIN_PROGRAM_FALLBACK="$LOGIN_PROGRAM_FALLBACK" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_LOGIN_PROGRAM_FALLBACK="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-LOGIN_PROGRAM_FALLBACK=$ac_cv_path_LOGIN_PROGRAM_FALLBACK
-if test -n "$LOGIN_PROGRAM_FALLBACK"; then
- { echo "$as_me:$LINENO: result: $LOGIN_PROGRAM_FALLBACK" >&5
-echo "${ECHO_T}$LOGIN_PROGRAM_FALLBACK" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- if test ! -z "$LOGIN_PROGRAM_FALLBACK" ; then
- cat >>confdefs.h <<_ACEOF
-#define LOGIN_PROGRAM_FALLBACK "$LOGIN_PROGRAM_FALLBACK"
-_ACEOF
-
- fi
-fi
-
-# Extract the first word of "passwd", so it can be a program name with args.
-set dummy passwd; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_PATH_PASSWD_PROG+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $PATH_PASSWD_PROG in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_PATH_PASSWD_PROG="$PATH_PASSWD_PROG" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_PATH_PASSWD_PROG="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-PATH_PASSWD_PROG=$ac_cv_path_PATH_PASSWD_PROG
-if test -n "$PATH_PASSWD_PROG"; then
- { echo "$as_me:$LINENO: result: $PATH_PASSWD_PROG" >&5
-echo "${ECHO_T}$PATH_PASSWD_PROG" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-if test ! -z "$PATH_PASSWD_PROG" ; then
-
-cat >>confdefs.h <<_ACEOF
-#define _PATH_PASSWD_PROG "$PATH_PASSWD_PROG"
-_ACEOF
-
-fi
-
-if test -z "$LD" ; then
- LD=$CC
-fi
-
-
-{ echo "$as_me:$LINENO: checking for inline" >&5
-echo $ECHO_N "checking for inline... $ECHO_C" >&6; }
-if test "${ac_cv_c_inline+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_c_inline=no
-for ac_kw in inline __inline__ __inline; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#ifndef __cplusplus
-typedef int foo_t;
-static $ac_kw foo_t static_foo () {return 0; }
-$ac_kw foo_t foo () {return 0; }
-#endif
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_c_inline=$ac_kw
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- test "$ac_cv_c_inline" != no && break
-done
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
-echo "${ECHO_T}$ac_cv_c_inline" >&6; }
-
-
-case $ac_cv_c_inline in
- inline | yes) ;;
- *)
- case $ac_cv_c_inline in
- no) ac_val=;;
- *) ac_val=$ac_cv_c_inline;;
- esac
- cat >>confdefs.h <<_ACEOF
-#ifndef __cplusplus
-#define inline $ac_val
-#endif
-_ACEOF
- ;;
-esac
-
-
-{ echo "$as_me:$LINENO: checking whether LLONG_MAX is declared" >&5
-echo $ECHO_N "checking whether LLONG_MAX is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_LLONG_MAX+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <limits.h>
-
-int
-main ()
-{
-#ifndef LLONG_MAX
- (void) LLONG_MAX;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_LLONG_MAX=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_LLONG_MAX=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_LLONG_MAX" >&5
-echo "${ECHO_T}$ac_cv_have_decl_LLONG_MAX" >&6; }
-if test $ac_cv_have_decl_LLONG_MAX = yes; then
- have_llong_max=1
-fi
-
-{ echo "$as_me:$LINENO: checking whether SYSTR_POLICY_KILL is declared" >&5
-echo $ECHO_N "checking whether SYSTR_POLICY_KILL is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_SYSTR_POLICY_KILL+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <sys/types.h>
- #include <sys/param.h>
- #include <dev/systrace.h>
-
-
-int
-main ()
-{
-#ifndef SYSTR_POLICY_KILL
- (void) SYSTR_POLICY_KILL;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_SYSTR_POLICY_KILL=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_SYSTR_POLICY_KILL=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_SYSTR_POLICY_KILL" >&5
-echo "${ECHO_T}$ac_cv_have_decl_SYSTR_POLICY_KILL" >&6; }
-if test $ac_cv_have_decl_SYSTR_POLICY_KILL = yes; then
- have_systr_policy_kill=1
-fi
-
-{ echo "$as_me:$LINENO: checking whether RLIMIT_NPROC is declared" >&5
-echo $ECHO_N "checking whether RLIMIT_NPROC is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_RLIMIT_NPROC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <sys/types.h>
- #include <sys/resource.h>
-
-
-int
-main ()
-{
-#ifndef RLIMIT_NPROC
- (void) RLIMIT_NPROC;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_RLIMIT_NPROC=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_RLIMIT_NPROC=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_RLIMIT_NPROC" >&5
-echo "${ECHO_T}$ac_cv_have_decl_RLIMIT_NPROC" >&6; }
-if test $ac_cv_have_decl_RLIMIT_NPROC = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_RLIMIT_NPROC
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking whether PR_SET_NO_NEW_PRIVS is declared" >&5
-echo $ECHO_N "checking whether PR_SET_NO_NEW_PRIVS is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_PR_SET_NO_NEW_PRIVS+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <sys/types.h>
- #include <linux/prctl.h>
-
-
-int
-main ()
-{
-#ifndef PR_SET_NO_NEW_PRIVS
- (void) PR_SET_NO_NEW_PRIVS;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_PR_SET_NO_NEW_PRIVS=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_PR_SET_NO_NEW_PRIVS=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_PR_SET_NO_NEW_PRIVS" >&5
-echo "${ECHO_T}$ac_cv_have_decl_PR_SET_NO_NEW_PRIVS" >&6; }
-if test $ac_cv_have_decl_PR_SET_NO_NEW_PRIVS = yes; then
- have_linux_no_new_privs=1
-fi
-
-
-openssl=yes
-ssh1=yes
-
-# Check whether --with-openssl was given.
-if test "${with_openssl+set}" = set; then
- withval=$with_openssl; if test "x$withval" = "xno" ; then
- openssl=no
- ssh1=no
- fi
-
-
-fi
-
-{ echo "$as_me:$LINENO: checking whether OpenSSL will be used for cryptography" >&5
-echo $ECHO_N "checking whether OpenSSL will be used for cryptography... $ECHO_C" >&6; }
-if test "x$openssl" = "xyes" ; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<_ACEOF
-#define WITH_OPENSSL 1
-_ACEOF
-
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-# Check whether --with-ssh1 was given.
-if test "${with_ssh1+set}" = set; then
- withval=$with_ssh1;
- if test "x$withval" = "xno" ; then
- ssh1=no
- elif test "x$openssl" = "xno" ; then
- { { echo "$as_me:$LINENO: error: Cannot enable SSH protocol 1 with OpenSSL disabled" >&5
-echo "$as_me: error: Cannot enable SSH protocol 1 with OpenSSL disabled" >&2;}
- { (exit 1); exit 1; }; }
- fi
-
-
-fi
-
-{ echo "$as_me:$LINENO: checking whether SSH protocol 1 support is enabled" >&5
-echo $ECHO_N "checking whether SSH protocol 1 support is enabled... $ECHO_C" >&6; }
-if test "x$ssh1" = "xyes" ; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<_ACEOF
-#define WITH_SSH1 1
-_ACEOF
-
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-use_stack_protector=1
-use_toolchain_hardening=1
-
-# Check whether --with-stackprotect was given.
-if test "${with_stackprotect+set}" = set; then
- withval=$with_stackprotect;
- if test "x$withval" = "xno"; then
- use_stack_protector=0
- fi
-fi
-
-
-# Check whether --with-hardening was given.
-if test "${with_hardening+set}" = set; then
- withval=$with_hardening;
- if test "x$withval" = "xno"; then
- use_toolchain_hardening=0
- fi
-fi
-
-
-# We use -Werror for the tests only so that we catch warnings like "this is
-# on by default" for things like -fPIE.
-{ echo "$as_me:$LINENO: checking if $CC supports -Werror" >&5
-echo $ECHO_N "checking if $CC supports -Werror... $ECHO_C" >&6; }
-saved_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS -Werror"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-int main(void) { return 0; }
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- WERROR="-Werror"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- WERROR=""
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-CFLAGS="$saved_CFLAGS"
-
-if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -Qunused-arguments" >&5
-echo $ECHO_N "checking if $CC supports compile flag -Qunused-arguments... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -Qunused-arguments"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-Qunused-arguments"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -Wunknown-warning-option" >&5
-echo $ECHO_N "checking if $CC supports compile flag -Wunknown-warning-option... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -Wunknown-warning-option"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-Wunknown-warning-option"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -Wall" >&5
-echo $ECHO_N "checking if $CC supports compile flag -Wall... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -Wall"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-Wall"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -Wpointer-arith" >&5
-echo $ECHO_N "checking if $CC supports compile flag -Wpointer-arith... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -Wpointer-arith"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-Wpointer-arith"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -Wuninitialized" >&5
-echo $ECHO_N "checking if $CC supports compile flag -Wuninitialized... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -Wuninitialized"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-Wuninitialized"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -Wsign-compare" >&5
-echo $ECHO_N "checking if $CC supports compile flag -Wsign-compare... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -Wsign-compare"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-Wsign-compare"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -Wformat-security" >&5
-echo $ECHO_N "checking if $CC supports compile flag -Wformat-security... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -Wformat-security"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-Wformat-security"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -Wsizeof-pointer-memaccess" >&5
-echo $ECHO_N "checking if $CC supports compile flag -Wsizeof-pointer-memaccess... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -Wsizeof-pointer-memaccess"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-Wsizeof-pointer-memaccess"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -Wpointer-sign" >&5
-echo $ECHO_N "checking if $CC supports compile flag -Wpointer-sign... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -Wpointer-sign"
- _define_flag="-Wno-pointer-sign"
- test "x$_define_flag" = "x" && _define_flag="-Wpointer-sign"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -Wunused-result" >&5
-echo $ECHO_N "checking if $CC supports compile flag -Wunused-result... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -Wunused-result"
- _define_flag="-Wno-unused-result"
- test "x$_define_flag" = "x" && _define_flag="-Wunused-result"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -fno-strict-aliasing" >&5
-echo $ECHO_N "checking if $CC supports compile flag -fno-strict-aliasing... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -fno-strict-aliasing"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-fno-strict-aliasing"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -D_FORTIFY_SOURCE=2" >&5
-echo $ECHO_N "checking if $CC supports compile flag -D_FORTIFY_SOURCE=2... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -D_FORTIFY_SOURCE=2"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-D_FORTIFY_SOURCE=2"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- if test "x$use_toolchain_hardening" = "x1"; then
- {
- { echo "$as_me:$LINENO: checking if $LD supports link flag -Wl,-z,relro" >&5
-echo $ECHO_N "checking if $LD supports link flag -Wl,-z,relro... $ECHO_C" >&6; }
- saved_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $WERROR -Wl,-z,relro"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-Wl,-z,relro"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- LDFLAGS="$saved_LDFLAGS $_define_flag"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- LDFLAGS="$saved_LDFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $LD supports link flag -Wl,-z,now" >&5
-echo $ECHO_N "checking if $LD supports link flag -Wl,-z,now... $ECHO_C" >&6; }
- saved_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $WERROR -Wl,-z,now"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-Wl,-z,now"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- LDFLAGS="$saved_LDFLAGS $_define_flag"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- LDFLAGS="$saved_LDFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $LD supports link flag -Wl,-z,noexecstack" >&5
-echo $ECHO_N "checking if $LD supports link flag -Wl,-z,noexecstack... $ECHO_C" >&6; }
- saved_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $WERROR -Wl,-z,noexecstack"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-Wl,-z,noexecstack"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- LDFLAGS="$saved_LDFLAGS $_define_flag"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- LDFLAGS="$saved_LDFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-}
- # NB. -ftrapv expects certain support functions to be present in
- # the compiler library (libgcc or similar) to detect integer operations
- # that can overflow. We must check that the result of enabling it
- # actually links. The test program compiled/linked includes a number
- # of integer operations that should exercise this.
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -ftrapv and linking succeeds" >&5
-echo $ECHO_N "checking if $CC supports compile flag -ftrapv and linking succeeds... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -ftrapv"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-ftrapv"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-}
- fi
- { echo "$as_me:$LINENO: checking gcc version" >&5
-echo $ECHO_N "checking gcc version... $ECHO_C" >&6; }
- GCC_VER=`$CC -v 2>&1 | $AWK '/gcc version /{print $3}'`
- case $GCC_VER in
- 1.*) no_attrib_nonnull=1 ;;
- 2.8* | 2.9*)
- no_attrib_nonnull=1
- ;;
- 2.*) no_attrib_nonnull=1 ;;
- *) ;;
- esac
- { echo "$as_me:$LINENO: result: $GCC_VER" >&5
-echo "${ECHO_T}$GCC_VER" >&6; }
-
- { echo "$as_me:$LINENO: checking if $CC accepts -fno-builtin-memset" >&5
-echo $ECHO_N "checking if $CC accepts -fno-builtin-memset... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -fno-builtin-memset"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <string.h>
-int
-main ()
-{
- char b[10]; memset(b, 0, sizeof(b));
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
- # -fstack-protector-all doesn't always work for some GCC versions
- # and/or platforms, so we test if we can. If it's not supported
- # on a given platform gcc will emit a warning so we use -Werror.
- if test "x$use_stack_protector" = "x1"; then
- for t in -fstack-protector-strong -fstack-protector-all \
- -fstack-protector; do
- { echo "$as_me:$LINENO: checking if $CC supports $t" >&5
-echo $ECHO_N "checking if $CC supports $t... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- saved_LDFLAGS="$LDFLAGS"
- CFLAGS="$CFLAGS $t -Werror"
- LDFLAGS="$LDFLAGS $t -Werror"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <stdio.h>
-int
-main ()
-{
-
- char x[256];
- snprintf(x, sizeof(x), "XXX");
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $t"
- LDFLAGS="$saved_LDFLAGS $t"
- { echo "$as_me:$LINENO: checking if $t works" >&5
-echo $ECHO_N "checking if $t works... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: WARNING: cross compiling: cannot test" >&5
-echo "$as_me: WARNING: cross compiling: cannot test" >&2;}
- break
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <stdio.h>
-int
-main ()
-{
-
- char x[256];
- snprintf(x, sizeof(x), "XXX");
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- break
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
- CFLAGS="$saved_CFLAGS"
- LDFLAGS="$saved_LDFLAGS"
- done
- fi
-
- if test -z "$have_llong_max"; then
- # retry LLONG_MAX with -std=gnu99, needed on some Linuxes
- unset ac_cv_have_decl_LLONG_MAX
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -std=gnu99"
- { echo "$as_me:$LINENO: checking whether LLONG_MAX is declared" >&5
-echo $ECHO_N "checking whether LLONG_MAX is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_LLONG_MAX+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <limits.h>
-
-
-int
-main ()
-{
-#ifndef LLONG_MAX
- (void) LLONG_MAX;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_LLONG_MAX=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_LLONG_MAX=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_LLONG_MAX" >&5
-echo "${ECHO_T}$ac_cv_have_decl_LLONG_MAX" >&6; }
-if test $ac_cv_have_decl_LLONG_MAX = yes; then
- have_llong_max=1
-else
- CFLAGS="$saved_CFLAGS"
-fi
-
- fi
-fi
-
-{ echo "$as_me:$LINENO: checking if compiler allows __attribute__ on return types" >&5
-echo $ECHO_N "checking if compiler allows __attribute__ on return types... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-__attribute__((__unused__)) static void foo(void){return;}
-int
-main ()
-{
- exit(0);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define NO_ATTRIBUTE_ON_RETURN_TYPE 1
-_ACEOF
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test "x$no_attrib_nonnull" != "x1" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ATTRIBUTE__NONNULL__ 1
-_ACEOF
-
-fi
-
-
-# Check whether --with-rpath was given.
-if test "${with_rpath+set}" = set; then
- withval=$with_rpath;
- if test "x$withval" = "xno" ; then
- need_dash_r=""
- fi
- if test "x$withval" = "xyes" ; then
- need_dash_r=1
- fi
-
-
-fi
-
-
-# Allow user to specify flags
-
-# Check whether --with-cflags was given.
-if test "${with_cflags+set}" = set; then
- withval=$with_cflags;
- if test -n "$withval" && test "x$withval" != "xno" && \
- test "x${withval}" != "xyes"; then
- CFLAGS="$CFLAGS $withval"
- fi
-
-
-fi
-
-
-# Check whether --with-cppflags was given.
-if test "${with_cppflags+set}" = set; then
- withval=$with_cppflags;
- if test -n "$withval" && test "x$withval" != "xno" && \
- test "x${withval}" != "xyes"; then
- CPPFLAGS="$CPPFLAGS $withval"
- fi
-
-
-fi
-
-
-# Check whether --with-ldflags was given.
-if test "${with_ldflags+set}" = set; then
- withval=$with_ldflags;
- if test -n "$withval" && test "x$withval" != "xno" && \
- test "x${withval}" != "xyes"; then
- LDFLAGS="$LDFLAGS $withval"
- fi
-
-
-fi
-
-
-# Check whether --with-libs was given.
-if test "${with_libs+set}" = set; then
- withval=$with_libs;
- if test -n "$withval" && test "x$withval" != "xno" && \
- test "x${withval}" != "xyes"; then
- LIBS="$LIBS $withval"
- fi
-
-
-fi
-
-
-# Check whether --with-Werror was given.
-if test "${with_Werror+set}" = set; then
- withval=$with_Werror;
- if test -n "$withval" && test "x$withval" != "xno"; then
- werror_flags="-Werror"
- if test "x${withval}" != "xyes"; then
- werror_flags="$withval"
- fi
- fi
-
-
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-for ac_header in \
- blf.h \
- bstring.h \
- crypt.h \
- crypto/sha2.h \
- dirent.h \
- endian.h \
- elf.h \
- features.h \
- fcntl.h \
- floatingpoint.h \
- getopt.h \
- glob.h \
- ia.h \
- iaf.h \
- inttypes.h \
- limits.h \
- locale.h \
- login.h \
- maillock.h \
- ndir.h \
- net/if_tun.h \
- netdb.h \
- netgroup.h \
- pam/pam_appl.h \
- paths.h \
- poll.h \
- pty.h \
- readpassphrase.h \
- rpc/types.h \
- security/pam_appl.h \
- sha2.h \
- shadow.h \
- stddef.h \
- stdint.h \
- string.h \
- strings.h \
- sys/audit.h \
- sys/bitypes.h \
- sys/bsdtty.h \
- sys/capability.h \
- sys/cdefs.h \
- sys/dir.h \
- sys/mman.h \
- sys/ndir.h \
- sys/poll.h \
- sys/prctl.h \
- sys/pstat.h \
- sys/select.h \
- sys/stat.h \
- sys/stream.h \
- sys/stropts.h \
- sys/strtio.h \
- sys/statvfs.h \
- sys/sysmacros.h \
- sys/time.h \
- sys/timers.h \
- time.h \
- tmpdir.h \
- ttyent.h \
- ucred.h \
- unistd.h \
- usersec.h \
- util.h \
- utime.h \
- utmp.h \
- utmpx.h \
- vis.h \
-
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-# lastlog.h requires sys/time.h to be included first on Solaris
-
-for ac_header in lastlog.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- eval "$as_ac_Header=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_Header=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-# sys/ptms.h requires sys/stream.h to be included first on Solaris
-
-for ac_header in sys/ptms.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#ifdef HAVE_SYS_STREAM_H
-# include <sys/stream.h>
-#endif
-
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- eval "$as_ac_Header=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_Header=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-# login_cap.h requires sys/types.h on NetBSD
-
-for ac_header in login_cap.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- eval "$as_ac_Header=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_Header=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-# older BSDs need sys/param.h before sys/mount.h
-
-for ac_header in sys/mount.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/param.h>
-
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- eval "$as_ac_Header=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_Header=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-# Android requires sys/socket.h to be included before sys/un.h
-
-for ac_header in sys/un.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- eval "$as_ac_Header=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_Header=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-# Messages for features tested for in target-specific section
-SIA_MSG="no"
-SPC_MSG="no"
-SP_MSG="no"
-
-# Check for some target-specific stuff
-case "$host" in
-*-*-aix*)
- # Some versions of VAC won't allow macro redefinitions at
- # -qlanglevel=ansi, and autoconf 2.60 sometimes insists on using that
- # particularly with older versions of vac or xlc.
- # It also throws errors about null macro argments, but these are
- # not fatal.
- { echo "$as_me:$LINENO: checking if compiler allows macro redefinitions" >&5
-echo $ECHO_N "checking if compiler allows macro redefinitions... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#define testmacro foo
-#define testmacro bar
-int
-main ()
-{
- exit(0);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CC="`echo $CC | sed 's/-qlanglvl\=ansi//g'`"
- LD="`echo $LD | sed 's/-qlanglvl\=ansi//g'`"
- CFLAGS="`echo $CFLAGS | sed 's/-qlanglvl\=ansi//g'`"
- CPPFLAGS="`echo $CPPFLAGS | sed 's/-qlanglvl\=ansi//g'`"
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
- { echo "$as_me:$LINENO: checking how to specify blibpath for linker ($LD)" >&5
-echo $ECHO_N "checking how to specify blibpath for linker ($LD)... $ECHO_C" >&6; }
- if (test -z "$blibpath"); then
- blibpath="/usr/lib:/lib"
- fi
- saved_LDFLAGS="$LDFLAGS"
- if test "$GCC" = "yes"; then
- flags="-Wl,-blibpath: -Wl,-rpath, -blibpath:"
- else
- flags="-blibpath: -Wl,-blibpath: -Wl,-rpath,"
- fi
- for tryflags in $flags ;do
- if (test -z "$blibflags"); then
- LDFLAGS="$saved_LDFLAGS $tryflags$blibpath"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- blibflags=$tryflags
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
- fi
- done
- if (test -z "$blibflags"); then
- { echo "$as_me:$LINENO: result: not found" >&5
-echo "${ECHO_T}not found" >&6; }
- { { echo "$as_me:$LINENO: error: *** must be able to specify blibpath on AIX - check config.log" >&5
-echo "$as_me: error: *** must be able to specify blibpath on AIX - check config.log" >&2;}
- { (exit 1); exit 1; }; }
- else
- { echo "$as_me:$LINENO: result: $blibflags" >&5
-echo "${ECHO_T}$blibflags" >&6; }
- fi
- LDFLAGS="$saved_LDFLAGS"
- { echo "$as_me:$LINENO: checking for authenticate" >&5
-echo $ECHO_N "checking for authenticate... $ECHO_C" >&6; }
-if test "${ac_cv_func_authenticate+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define authenticate to an innocuous variant, in case <limits.h> declares authenticate.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define authenticate innocuous_authenticate
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char authenticate (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef authenticate
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char authenticate ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_authenticate || defined __stub___authenticate
-choke me
-#endif
-
-int
-main ()
-{
-return authenticate ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_func_authenticate=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_func_authenticate=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_authenticate" >&5
-echo "${ECHO_T}$ac_cv_func_authenticate" >&6; }
-if test $ac_cv_func_authenticate = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define WITH_AIXAUTHENTICATE 1
-_ACEOF
-
-else
- { echo "$as_me:$LINENO: checking for authenticate in -ls" >&5
-echo $ECHO_N "checking for authenticate in -ls... $ECHO_C" >&6; }
-if test "${ac_cv_lib_s_authenticate+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ls $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char authenticate ();
-int
-main ()
-{
-return authenticate ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_s_authenticate=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_s_authenticate=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_s_authenticate" >&5
-echo "${ECHO_T}$ac_cv_lib_s_authenticate" >&6; }
-if test $ac_cv_lib_s_authenticate = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define WITH_AIXAUTHENTICATE 1
-_ACEOF
-
- LIBS="$LIBS -ls"
-
-fi
-
-
-fi
-
- { echo "$as_me:$LINENO: checking whether authenticate is declared" >&5
-echo $ECHO_N "checking whether authenticate is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_authenticate+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <usersec.h>
-
-int
-main ()
-{
-#ifndef authenticate
- (void) authenticate;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_authenticate=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_authenticate=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_authenticate" >&5
-echo "${ECHO_T}$ac_cv_have_decl_authenticate" >&6; }
-if test $ac_cv_have_decl_authenticate = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_AUTHENTICATE 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_AUTHENTICATE 0
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking whether loginrestrictions is declared" >&5
-echo $ECHO_N "checking whether loginrestrictions is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_loginrestrictions+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <usersec.h>
-
-int
-main ()
-{
-#ifndef loginrestrictions
- (void) loginrestrictions;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_loginrestrictions=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_loginrestrictions=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_loginrestrictions" >&5
-echo "${ECHO_T}$ac_cv_have_decl_loginrestrictions" >&6; }
-if test $ac_cv_have_decl_loginrestrictions = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_LOGINRESTRICTIONS 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_LOGINRESTRICTIONS 0
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking whether loginsuccess is declared" >&5
-echo $ECHO_N "checking whether loginsuccess is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_loginsuccess+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <usersec.h>
-
-int
-main ()
-{
-#ifndef loginsuccess
- (void) loginsuccess;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_loginsuccess=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_loginsuccess=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_loginsuccess" >&5
-echo "${ECHO_T}$ac_cv_have_decl_loginsuccess" >&6; }
-if test $ac_cv_have_decl_loginsuccess = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_LOGINSUCCESS 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_LOGINSUCCESS 0
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking whether passwdexpired is declared" >&5
-echo $ECHO_N "checking whether passwdexpired is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_passwdexpired+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <usersec.h>
-
-int
-main ()
-{
-#ifndef passwdexpired
- (void) passwdexpired;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_passwdexpired=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_passwdexpired=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_passwdexpired" >&5
-echo "${ECHO_T}$ac_cv_have_decl_passwdexpired" >&6; }
-if test $ac_cv_have_decl_passwdexpired = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_PASSWDEXPIRED 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_PASSWDEXPIRED 0
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking whether setauthdb is declared" >&5
-echo $ECHO_N "checking whether setauthdb is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_setauthdb+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <usersec.h>
-
-int
-main ()
-{
-#ifndef setauthdb
- (void) setauthdb;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_setauthdb=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_setauthdb=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_setauthdb" >&5
-echo "${ECHO_T}$ac_cv_have_decl_setauthdb" >&6; }
-if test $ac_cv_have_decl_setauthdb = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SETAUTHDB 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SETAUTHDB 0
-_ACEOF
-
-
-fi
-
-
- { echo "$as_me:$LINENO: checking whether loginfailed is declared" >&5
-echo $ECHO_N "checking whether loginfailed is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_loginfailed+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <usersec.h>
-
-
-int
-main ()
-{
-#ifndef loginfailed
- (void) loginfailed;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_loginfailed=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_loginfailed=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_loginfailed" >&5
-echo "${ECHO_T}$ac_cv_have_decl_loginfailed" >&6; }
-if test $ac_cv_have_decl_loginfailed = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_LOGINFAILED 1
-_ACEOF
-
-{ echo "$as_me:$LINENO: checking if loginfailed takes 4 arguments" >&5
-echo $ECHO_N "checking if loginfailed takes 4 arguments... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <usersec.h>
-int
-main ()
-{
- (void)loginfailed("user","host","tty",0);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define AIX_LOGINFAILED_4ARG 1
-_ACEOF
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_LOGINFAILED 0
-_ACEOF
-
-
-fi
-
-
-
-
-for ac_func in getgrset setauthdb
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
- { echo "$as_me:$LINENO: checking whether F_CLOSEM is declared" >&5
-echo $ECHO_N "checking whether F_CLOSEM is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_F_CLOSEM+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <limits.h>
- #include <fcntl.h>
-
-
-int
-main ()
-{
-#ifndef F_CLOSEM
- (void) F_CLOSEM;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_F_CLOSEM=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_F_CLOSEM=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_F_CLOSEM" >&5
-echo "${ECHO_T}$ac_cv_have_decl_F_CLOSEM" >&6; }
-if test $ac_cv_have_decl_F_CLOSEM = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_FCNTL_CLOSEM 1
-_ACEOF
-
-fi
-
- check_for_aix_broken_getaddrinfo=1
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_REALPATH 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define DISABLE_LASTLOG 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define LOGIN_NEEDS_UTMPX 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SPT_TYPE SPT_REUSEARGV
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SSHPAM_CHAUTHTOK_NEEDS_RUID 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define PTY_ZEROREAD 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define PLATFORM_SYS_DIR_UID 2
-_ACEOF
-
- ;;
-*-*-android*)
-
-cat >>confdefs.h <<\_ACEOF
-#define DISABLE_UTMP 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define DISABLE_WTMP 1
-_ACEOF
-
- ;;
-*-*-cygwin*)
- check_for_libcrypt_later=1
- LIBS="$LIBS /usr/lib/textreadmode.o"
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_CYGWIN 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define DISABLE_SHADOW 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define NO_X11_UNIX_SOCKETS 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define NO_IPPORT_RESERVED_CONCEPT 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define DISABLE_FD_PASSING 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_IOBUFSZ 65535
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define FILESYSTEM_NO_BACKSLASH 1
-_ACEOF
-
- # Cygwin defines optargs, optargs as declspec(dllimport) for historical
- # reasons which cause compile warnings, so we disable those warnings.
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -Wno-attributes" >&5
-echo $ECHO_N "checking if $CC supports compile flag -Wno-attributes... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -Wno-attributes"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-Wno-attributes"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- ;;
-*-*-dgux*)
-
-cat >>confdefs.h <<\_ACEOF
-#define IP_TOS_IS_BROKEN 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
- ;;
-*-*-darwin*)
- use_pie=auto
- { echo "$as_me:$LINENO: checking if we have working getaddrinfo" >&5
-echo $ECHO_N "checking if we have working getaddrinfo... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: result: assume it is working" >&5
-echo "${ECHO_T}assume it is working" >&6; }
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <mach-o/dyld.h>
-main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
- exit(0);
- else
- exit(1);
-}
-
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: working" >&5
-echo "${ECHO_T}working" >&6; }
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-{ echo "$as_me:$LINENO: result: buggy" >&5
-echo "${ECHO_T}buggy" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_GETADDRINFO 1
-_ACEOF
-
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_GLOB 1
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define BIND_8_COMPAT 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_TUN_FREEBSD 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_TUN_COMPAT_AF 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_TUN_PREPEND_AF 1
-_ACEOF
-
-
- { echo "$as_me:$LINENO: checking whether AU_IPv4 is declared" >&5
-echo $ECHO_N "checking whether AU_IPv4 is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_AU_IPv4+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-#ifndef AU_IPv4
- (void) AU_IPv4;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_AU_IPv4=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_AU_IPv4=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_AU_IPv4" >&5
-echo "${ECHO_T}$ac_cv_have_decl_AU_IPv4" >&6; }
-if test $ac_cv_have_decl_AU_IPv4 = yes; then
- :
-else
-
-cat >>confdefs.h <<\_ACEOF
-#define AU_IPv4 0
-_ACEOF
-
- #include <bsm/audit.h>
-
-cat >>confdefs.h <<\_ACEOF
-#define LASTLOG_WRITE_PUTUTXLINE 1
-_ACEOF
-
-
-fi
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SPT_TYPE SPT_REUSEARGV
-_ACEOF
-
-
-for ac_func in sandbox_init
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-for ac_header in sandbox.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
- ;;
-*-*-dragonfly*)
- SSHDLIBS="$SSHDLIBS -lcrypt"
- TEST_MALLOC_OPTIONS="AFGJPRX"
- ;;
-*-*-haiku*)
- LIBS="$LIBS -lbsd "
-
-{ echo "$as_me:$LINENO: checking for socket in -lnetwork" >&5
-echo $ECHO_N "checking for socket in -lnetwork... $ECHO_C" >&6; }
-if test "${ac_cv_lib_network_socket+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnetwork $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char socket ();
-int
-main ()
-{
-return socket ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_network_socket=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_network_socket=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_network_socket" >&5
-echo "${ECHO_T}$ac_cv_lib_network_socket" >&6; }
-if test $ac_cv_lib_network_socket = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBNETWORK 1
-_ACEOF
-
- LIBS="-lnetwork $LIBS"
-
-fi
-
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_U_INT64_T 1
-_ACEOF
-
- MANTYPE=man
- ;;
-*-*-hpux*)
- # first we define all of the options common to all HP-UX releases
- CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1"
- IPADDR_IN_DISPLAY=yes
- cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define LOGIN_NO_ENDOPT 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define LOGIN_NEEDS_UTMPX 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define LOCKED_PASSWD_STRING "*"
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SPT_TYPE SPT_PSTAT
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define PLATFORM_SYS_DIR_UID 2
-_ACEOF
-
- maildir="/var/mail"
- LIBS="$LIBS -lsec"
-
-{ echo "$as_me:$LINENO: checking for t_error in -lxnet" >&5
-echo $ECHO_N "checking for t_error in -lxnet... $ECHO_C" >&6; }
-if test "${ac_cv_lib_xnet_t_error+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lxnet $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char t_error ();
-int
-main ()
-{
-return t_error ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_xnet_t_error=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_xnet_t_error=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_xnet_t_error" >&5
-echo "${ECHO_T}$ac_cv_lib_xnet_t_error" >&6; }
-if test $ac_cv_lib_xnet_t_error = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBXNET 1
-_ACEOF
-
- LIBS="-lxnet $LIBS"
-
-else
- { { echo "$as_me:$LINENO: error: *** -lxnet needed on HP-UX - check config.log ***" >&5
-echo "$as_me: error: *** -lxnet needed on HP-UX - check config.log ***" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-
- # next, we define all of the options specific to major releases
- case "$host" in
- *-*-hpux10*)
- if test -z "$GCC"; then
- CFLAGS="$CFLAGS -Ae"
- fi
- ;;
- *-*-hpux11*)
-
-cat >>confdefs.h <<\_ACEOF
-#define PAM_SUN_CODEBASE 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define DISABLE_UTMP 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_BTMP 1
-_ACEOF
-
- check_for_hpux_broken_getaddrinfo=1
- check_for_conflicting_getspnam=1
- ;;
- esac
-
- # lastly, we define options specific to minor releases
- case "$host" in
- *-*-hpux10.26)
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_SECUREWARE 1
-_ACEOF
-
- disable_ptmx_check=yes
- LIBS="$LIBS -lsecpw"
- ;;
- esac
- ;;
-*-*-irix5*)
- PATH="$PATH:/usr/etc"
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_INET_NTOA 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define WITH_ABBREV_NO_TTY 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define LOCKED_PASSWD_STRING "*LK*"
-_ACEOF
-
- ;;
-*-*-irix6*)
- PATH="$PATH:/usr/etc"
-
-cat >>confdefs.h <<\_ACEOF
-#define WITH_IRIX_ARRAY 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define WITH_IRIX_PROJECT 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define WITH_IRIX_AUDIT 1
-_ACEOF
-
- { echo "$as_me:$LINENO: checking for jlimit_startjob" >&5
-echo $ECHO_N "checking for jlimit_startjob... $ECHO_C" >&6; }
-if test "${ac_cv_func_jlimit_startjob+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define jlimit_startjob to an innocuous variant, in case <limits.h> declares jlimit_startjob.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define jlimit_startjob innocuous_jlimit_startjob
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char jlimit_startjob (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef jlimit_startjob
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char jlimit_startjob ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_jlimit_startjob || defined __stub___jlimit_startjob
-choke me
-#endif
-
-int
-main ()
-{
-return jlimit_startjob ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_func_jlimit_startjob=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_func_jlimit_startjob=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_jlimit_startjob" >&5
-echo "${ECHO_T}$ac_cv_func_jlimit_startjob" >&6; }
-if test $ac_cv_func_jlimit_startjob = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define WITH_IRIX_JOBS 1
-_ACEOF
-
-fi
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_INET_NTOA 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_UPDWTMPX 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define WITH_ABBREV_NO_TTY 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define LOCKED_PASSWD_STRING "*LK*"
-_ACEOF
-
- ;;
-*-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
- check_for_libcrypt_later=1
- cat >>confdefs.h <<\_ACEOF
-#define PAM_TTY_KLUDGE 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define LOCKED_PASSWD_PREFIX "!"
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SPT_TYPE SPT_REUSEARGV
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define _PATH_BTMP "/var/log/btmp"
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_BTMP 1
-_ACEOF
-
- ;;
-*-*-linux*)
- no_dev_ptmx=1
- use_pie=auto
- check_for_libcrypt_later=1
- check_for_openpty_ctty_bug=1
-
-cat >>confdefs.h <<\_ACEOF
-#define PAM_TTY_KLUDGE 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define LOCKED_PASSWD_PREFIX "!"
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SPT_TYPE SPT_REUSEARGV
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define LINK_OPNOTSUPP_ERRNO EPERM
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define _PATH_BTMP "/var/log/btmp"
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define USE_BTMP 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define LINUX_OOM_ADJUST 1
-_ACEOF
-
- inet6_default_4in6=yes
- case `uname -r` in
- 1.*|2.0.*)
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_CMSG_TYPE 1
-_ACEOF
-
- ;;
- esac
- # tun(4) forwarding compat code
-
-for ac_header in linux/if_tun.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
- if test "x$ac_cv_header_linux_if_tun_h" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_TUN_LINUX 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_TUN_COMPAT_AF 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_TUN_PREPEND_AF 1
-_ACEOF
-
- fi
-
-
-
-for ac_header in linux/seccomp.h linux/filter.h linux/audit.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <linux/types.h>
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- eval "$as_ac_Header=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_Header=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-for ac_func in prctl
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
- { echo "$as_me:$LINENO: checking for seccomp architecture" >&5
-echo $ECHO_N "checking for seccomp architecture... $ECHO_C" >&6; }
- seccomp_audit_arch=
- case "$host" in
- x86_64-*)
- seccomp_audit_arch=AUDIT_ARCH_X86_64
- ;;
- i*86-*)
- seccomp_audit_arch=AUDIT_ARCH_I386
- ;;
- arm*-*)
- seccomp_audit_arch=AUDIT_ARCH_ARM
- ;;
- esac
- if test "x$seccomp_audit_arch" != "x" ; then
- { echo "$as_me:$LINENO: result: \"$seccomp_audit_arch\"" >&5
-echo "${ECHO_T}\"$seccomp_audit_arch\"" >&6; }
-
-cat >>confdefs.h <<_ACEOF
-#define SECCOMP_AUDIT_ARCH $seccomp_audit_arch
-_ACEOF
-
- else
- { echo "$as_me:$LINENO: result: architecture not supported" >&5
-echo "${ECHO_T}architecture not supported" >&6; }
- fi
- ;;
-mips-sony-bsd|mips-sony-newsos4)
-
-cat >>confdefs.h <<\_ACEOF
-#define NEED_SETPGRP 1
-_ACEOF
-
- SONY=1
- ;;
-*-*-netbsd*)
- check_for_libcrypt_before=1
- if test "x$withval" != "xno" ; then
- need_dash_r=1
- fi
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_TUN_FREEBSD 1
-_ACEOF
-
- if test "${ac_cv_header_net_if_tap_h+set}" = set; then
- { echo "$as_me:$LINENO: checking for net/if_tap.h" >&5
-echo $ECHO_N "checking for net/if_tap.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_net_if_tap_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_net_if_tap_h" >&5
-echo "${ECHO_T}$ac_cv_header_net_if_tap_h" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking net/if_tap.h usability" >&5
-echo $ECHO_N "checking net/if_tap.h usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <net/if_tap.h>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking net/if_tap.h presence" >&5
-echo $ECHO_N "checking net/if_tap.h presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <net/if_tap.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: net/if_tap.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: net/if_tap.h: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: present but cannot be compiled" >&5
-echo "$as_me: WARNING: net/if_tap.h: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: net/if_tap.h: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: net/if_tap.h: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: net/if_tap.h: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: net/if_tap.h: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: net/if_tap.h: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for net/if_tap.h" >&5
-echo $ECHO_N "checking for net/if_tap.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_net_if_tap_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_header_net_if_tap_h=$ac_header_preproc
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_net_if_tap_h" >&5
-echo "${ECHO_T}$ac_cv_header_net_if_tap_h" >&6; }
-
-fi
-if test $ac_cv_header_net_if_tap_h = yes; then
- :
-else
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_TUN_NO_L2 1
-_ACEOF
-
-fi
-
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_TUN_PREPEND_AF 1
-_ACEOF
-
- TEST_MALLOC_OPTIONS="AJRX"
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_STRNVIS 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_READ_COMPARISON 1
-_ACEOF
-
- ;;
-*-*-freebsd*)
- check_for_libcrypt_later=1
-
-cat >>confdefs.h <<\_ACEOF
-#define LOCKED_PASSWD_PREFIX "*LOCKED*"
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_TUN_FREEBSD 1
-_ACEOF
-
- if test "${ac_cv_header_net_if_tap_h+set}" = set; then
- { echo "$as_me:$LINENO: checking for net/if_tap.h" >&5
-echo $ECHO_N "checking for net/if_tap.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_net_if_tap_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_net_if_tap_h" >&5
-echo "${ECHO_T}$ac_cv_header_net_if_tap_h" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking net/if_tap.h usability" >&5
-echo $ECHO_N "checking net/if_tap.h usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <net/if_tap.h>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking net/if_tap.h presence" >&5
-echo $ECHO_N "checking net/if_tap.h presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <net/if_tap.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: net/if_tap.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: net/if_tap.h: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: present but cannot be compiled" >&5
-echo "$as_me: WARNING: net/if_tap.h: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: net/if_tap.h: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: net/if_tap.h: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: net/if_tap.h: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: net/if_tap.h: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: net/if_tap.h: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: net/if_tap.h: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for net/if_tap.h" >&5
-echo $ECHO_N "checking for net/if_tap.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_net_if_tap_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_header_net_if_tap_h=$ac_header_preproc
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_net_if_tap_h" >&5
-echo "${ECHO_T}$ac_cv_header_net_if_tap_h" >&6; }
-
-fi
-if test $ac_cv_header_net_if_tap_h = yes; then
- :
-else
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_TUN_NO_L2 1
-_ACEOF
-
-fi
-
-
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_GLOB 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_STRNVIS 1
-_ACEOF
-
- TEST_MALLOC_OPTIONS="AJRX"
- # Preauth crypto occasionally uses file descriptors for crypto offload
- # and will crash if they cannot be opened.
-
-cat >>confdefs.h <<\_ACEOF
-#define SANDBOX_SKIP_RLIMIT_NOFILE 1
-_ACEOF
-
- ;;
-*-*-bsdi*)
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
- ;;
-*-next-*)
- conf_lastlog_location="/usr/adm/lastlog"
- conf_utmp_location=/etc/utmp
- conf_wtmp_location=/usr/adm/wtmp
- maildir=/usr/spool/mail
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_NEXT 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_REALPATH 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SAVED_UIDS 1
-_ACEOF
-
- ;;
-*-*-openbsd*)
- use_pie=auto
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ATTRIBUTE__SENTINEL__ 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ATTRIBUTE__BOUNDED__ 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_TUN_OPENBSD 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SYSLOG_R_SAFE_IN_SIGHAND 1
-_ACEOF
-
- TEST_MALLOC_OPTIONS="AFGJPRX"
- ;;
-*-*-solaris*)
- if test "x$withval" != "xno" ; then
- need_dash_r=1
- fi
- cat >>confdefs.h <<\_ACEOF
-#define PAM_SUN_CODEBASE 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define LOGIN_NEEDS_UTMPX 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define LOGIN_NEEDS_TERM 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define PAM_TTY_KLUDGE 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SSHPAM_CHAUTHTOK_NEEDS_RUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define LOCKED_PASSWD_STRING "*LK*"
-_ACEOF
-
- # Pushing STREAMS modules will cause sshd to acquire a controlling tty.
-
-cat >>confdefs.h <<\_ACEOF
-#define SSHD_ACQUIRES_CTTY 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define PASSWD_NEEDS_USERNAME 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_TCGETATTR_ICANON 1
-_ACEOF
-
- external_path_file=/etc/default/login
- # hardwire lastlog location (can't detect it on some versions)
- conf_lastlog_location="/var/adm/lastlog"
- { echo "$as_me:$LINENO: checking for obsolete utmp and wtmp in solaris2.x" >&5
-echo $ECHO_N "checking for obsolete utmp and wtmp in solaris2.x... $ECHO_C" >&6; }
- sol2ver=`echo "$host"| sed -e 's/.*[0-9]\.//'`
- if test "$sol2ver" -ge 8; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_UTMP 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define DISABLE_WTMP 1
-_ACEOF
-
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-# Check whether --with-solaris-contracts was given.
-if test "${with_solaris_contracts+set}" = set; then
- withval=$with_solaris_contracts;
- { echo "$as_me:$LINENO: checking for ct_tmpl_activate in -lcontract" >&5
-echo $ECHO_N "checking for ct_tmpl_activate in -lcontract... $ECHO_C" >&6; }
-if test "${ac_cv_lib_contract_ct_tmpl_activate+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcontract $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char ct_tmpl_activate ();
-int
-main ()
-{
-return ct_tmpl_activate ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_contract_ct_tmpl_activate=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_contract_ct_tmpl_activate=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_contract_ct_tmpl_activate" >&5
-echo "${ECHO_T}$ac_cv_lib_contract_ct_tmpl_activate" >&6; }
-if test $ac_cv_lib_contract_ct_tmpl_activate = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_SOLARIS_PROCESS_CONTRACTS 1
-_ACEOF
-
- SSHDLIBS="$SSHDLIBS -lcontract"
- SPC_MSG="yes"
-fi
-
-
-fi
-
-
-# Check whether --with-solaris-projects was given.
-if test "${with_solaris_projects+set}" = set; then
- withval=$with_solaris_projects;
- { echo "$as_me:$LINENO: checking for setproject in -lproject" >&5
-echo $ECHO_N "checking for setproject in -lproject... $ECHO_C" >&6; }
-if test "${ac_cv_lib_project_setproject+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lproject $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char setproject ();
-int
-main ()
-{
-return setproject ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_project_setproject=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_project_setproject=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_project_setproject" >&5
-echo "${ECHO_T}$ac_cv_lib_project_setproject" >&6; }
-if test $ac_cv_lib_project_setproject = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_SOLARIS_PROJECTS 1
-_ACEOF
-
- SSHDLIBS="$SSHDLIBS -lproject"
- SP_MSG="yes"
-fi
-
-
-fi
-
- TEST_SHELL=$SHELL # let configure find us a capable shell
- ;;
-*-*-sunos4*)
- CPPFLAGS="$CPPFLAGS -DSUNOS4"
-
-for ac_func in getpwanam
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
- cat >>confdefs.h <<\_ACEOF
-#define PAM_SUN_CODEBASE 1
-_ACEOF
-
- conf_utmp_location=/etc/utmp
- conf_wtmp_location=/var/adm/wtmp
- conf_lastlog_location=/var/adm/lastlog
- cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
- ;;
-*-ncr-sysv*)
- LIBS="$LIBS -lc89"
- cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SSHD_ACQUIRES_CTTY 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
- ;;
-*-sni-sysv*)
- # /usr/ucblib MUST NOT be searched on ReliantUNIX
-
-{ echo "$as_me:$LINENO: checking for dlsym in -ldl" >&5
-echo $ECHO_N "checking for dlsym in -ldl... $ECHO_C" >&6; }
-if test "${ac_cv_lib_dl_dlsym+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldl $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlsym ();
-int
-main ()
-{
-return dlsym ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_dl_dlsym=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_dl_dlsym=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlsym" >&5
-echo "${ECHO_T}$ac_cv_lib_dl_dlsym" >&6; }
-if test $ac_cv_lib_dl_dlsym = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBDL 1
-_ACEOF
-
- LIBS="-ldl $LIBS"
-
-fi
-
- # -lresolv needs to be at the end of LIBS or DNS lookups break
- { echo "$as_me:$LINENO: checking for res_query in -lresolv" >&5
-echo $ECHO_N "checking for res_query in -lresolv... $ECHO_C" >&6; }
-if test "${ac_cv_lib_resolv_res_query+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lresolv $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char res_query ();
-int
-main ()
-{
-return res_query ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_resolv_res_query=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_resolv_res_query=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_res_query" >&5
-echo "${ECHO_T}$ac_cv_lib_resolv_res_query" >&6; }
-if test $ac_cv_lib_resolv_res_query = yes; then
- LIBS="$LIBS -lresolv"
-fi
-
- IPADDR_IN_DISPLAY=yes
- cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define IP_TOS_IS_BROKEN 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SSHD_ACQUIRES_CTTY 1
-_ACEOF
-
- external_path_file=/etc/default/login
- # /usr/ucblib/libucb.a no longer needed on ReliantUNIX
- # Attention: always take care to bind libsocket and libnsl before libc,
- # otherwise you will find lots of "SIOCGPGRP errno 22" on syslog
- ;;
-# UnixWare 1.x, UnixWare 2.x, and others based on code from Univel.
-*-*-sysv4.2*)
- cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define PASSWD_NEEDS_USERNAME 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define LOCKED_PASSWD_STRING "*LK*"
-_ACEOF
-
- TEST_SHELL=$SHELL # let configure find us a capable shell
- ;;
-# UnixWare 7.x, OpenUNIX 8
-*-*-sysv5*)
- CPPFLAGS="$CPPFLAGS -Dvsnprintf=_xvsnprintf -Dsnprintf=_xsnprintf"
-
-cat >>confdefs.h <<\_ACEOF
-#define UNIXWARE_LONG_PASSWORDS 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_GETADDRINFO 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define PASSWD_NEEDS_USERNAME 1
-_ACEOF
-
- TEST_SHELL=$SHELL # let configure find us a capable shell
- case "$host" in
- *-*-sysv5SCO_SV*) # SCO OpenServer 6.x
- maildir=/var/spool/mail
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_LIBIAF 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_UPDWTMPX 1
-_ACEOF
-
- { echo "$as_me:$LINENO: checking for getluid in -lprot" >&5
-echo $ECHO_N "checking for getluid in -lprot... $ECHO_C" >&6; }
-if test "${ac_cv_lib_prot_getluid+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lprot $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getluid ();
-int
-main ()
-{
-return getluid ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_prot_getluid=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_prot_getluid=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_prot_getluid" >&5
-echo "${ECHO_T}$ac_cv_lib_prot_getluid" >&6; }
-if test $ac_cv_lib_prot_getluid = yes; then
- LIBS="$LIBS -lprot"
-
-
-for ac_func in getluid setluid
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_SECUREWARE 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_SHADOW 1
-_ACEOF
-
-
-fi
-
- ;;
- *) cat >>confdefs.h <<\_ACEOF
-#define LOCKED_PASSWD_STRING "*LK*"
-_ACEOF
-
- check_for_libcrypt_later=1
- ;;
- esac
- ;;
-*-*-sysv*)
- ;;
-# SCO UNIX and OEM versions of SCO UNIX
-*-*-sco3.2v4*)
- { { echo "$as_me:$LINENO: error: \"This Platform is no longer supported.\"" >&5
-echo "$as_me: error: \"This Platform is no longer supported.\"" >&2;}
- { (exit 1); exit 1; }; }
- ;;
-# SCO OpenServer 5.x
-*-*-sco3.2v5*)
- if test -z "$GCC"; then
- CFLAGS="$CFLAGS -belf"
- fi
- LIBS="$LIBS -lprot -lx -ltinfo -lm"
- no_dev_ptmx=1
- cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_SECUREWARE 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_SHADOW 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_FD_PASSING 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_GETADDRINFO 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define WITH_ABBREV_NO_TTY 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_UPDWTMPX 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define PASSWD_NEEDS_USERNAME 1
-_ACEOF
-
-
-
-for ac_func in getluid setluid
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
- MANTYPE=man
- TEST_SHELL=$SHELL # let configure find us a capable shell
- SKIP_DISABLE_LASTLOG_DEFINE=yes
- ;;
-*-*-unicosmk*)
-
-cat >>confdefs.h <<\_ACEOF
-#define NO_SSH_LASTLOG 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_FD_PASSING 1
-_ACEOF
-
- LDFLAGS="$LDFLAGS"
- LIBS="$LIBS -lgen -lrsc -lshare -luex -lacm"
- MANTYPE=cat
- ;;
-*-*-unicosmp*)
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define WITH_ABBREV_NO_TTY 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_FD_PASSING 1
-_ACEOF
-
- LDFLAGS="$LDFLAGS"
- LIBS="$LIBS -lgen -lacid -ldb"
- MANTYPE=cat
- ;;
-*-*-unicos*)
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_FD_PASSING 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define NO_SSH_LASTLOG 1
-_ACEOF
-
- LDFLAGS="$LDFLAGS -Wl,-Dmsglevel=334:fatal"
- LIBS="$LIBS -lgen -lrsc -lshare -luex -lacm"
- MANTYPE=cat
- ;;
-*-dec-osf*)
- { echo "$as_me:$LINENO: checking for Digital Unix SIA" >&5
-echo $ECHO_N "checking for Digital Unix SIA... $ECHO_C" >&6; }
- no_osfsia=""
-
-# Check whether --with-osfsia was given.
-if test "${with_osfsia+set}" = set; then
- withval=$with_osfsia;
- if test "x$withval" = "xno" ; then
- { echo "$as_me:$LINENO: result: disabled" >&5
-echo "${ECHO_T}disabled" >&6; }
- no_osfsia=1
- fi
-
-fi
-
- if test -z "$no_osfsia" ; then
- if test -f /etc/sia/matrix.conf; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_OSF_SIA 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define DISABLE_LOGIN 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_FD_PASSING 1
-_ACEOF
-
- LIBS="$LIBS -lsecurity -ldb -lm -laud"
- SIA_MSG="yes"
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define LOCKED_PASSWD_SUBSTR "Nologin"
-_ACEOF
-
- fi
- fi
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_GETADDRINFO 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_READV_COMPARISON 1
-_ACEOF
-
- ;;
-
-*-*-nto-qnx*)
- cat >>confdefs.h <<\_ACEOF
-#define USE_PIPES 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define NO_X11_UNIX_SOCKETS 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_LASTLOG 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define SSHD_ACQUIRES_CTTY 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SHADOW_EXPIRE 1
-_ACEOF
-
- enable_etc_default_login=no # has incompatible /etc/default/login
- case "$host" in
- *-*-nto-qnx6*)
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_FD_PASSING 1
-_ACEOF
-
- ;;
- esac
- ;;
-
-*-*-ultrix*)
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_GETGROUPS 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_MMAP 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define NEED_SETPGRP 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_SYS_SYSLOG_H 1
-_ACEOF
-
- ;;
-
-*-*-lynxos)
- CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__"
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETVBUF 1
-_ACEOF
-
- ;;
-esac
-
-{ echo "$as_me:$LINENO: checking compiler and flags for sanity" >&5
-echo $ECHO_N "checking compiler and flags for sanity... $ECHO_C" >&6; }
-if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: WARNING: cross compiling: not checking compiler sanity" >&5
-echo "$as_me: WARNING: cross compiling: not checking compiler sanity" >&2;}
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <stdio.h>
-int
-main ()
-{
- exit(0);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- { { echo "$as_me:$LINENO: error: *** compiler cannot create working executables, check config.log ***" >&5
-echo "$as_me: error: *** compiler cannot create working executables, check config.log ***" >&2;}
- { (exit 1); exit 1; }; }
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
-# Checks for libraries.
-{ echo "$as_me:$LINENO: checking for yp_match" >&5
-echo $ECHO_N "checking for yp_match... $ECHO_C" >&6; }
-if test "${ac_cv_func_yp_match+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define yp_match to an innocuous variant, in case <limits.h> declares yp_match.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define yp_match innocuous_yp_match
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char yp_match (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef yp_match
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char yp_match ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_yp_match || defined __stub___yp_match
-choke me
-#endif
-
-int
-main ()
-{
-return yp_match ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_func_yp_match=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_func_yp_match=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_yp_match" >&5
-echo "${ECHO_T}$ac_cv_func_yp_match" >&6; }
-if test $ac_cv_func_yp_match = yes; then
- :
-else
-
-{ echo "$as_me:$LINENO: checking for yp_match in -lnsl" >&5
-echo $ECHO_N "checking for yp_match in -lnsl... $ECHO_C" >&6; }
-if test "${ac_cv_lib_nsl_yp_match+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnsl $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char yp_match ();
-int
-main ()
-{
-return yp_match ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_nsl_yp_match=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_nsl_yp_match=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_yp_match" >&5
-echo "${ECHO_T}$ac_cv_lib_nsl_yp_match" >&6; }
-if test $ac_cv_lib_nsl_yp_match = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBNSL 1
-_ACEOF
-
- LIBS="-lnsl $LIBS"
-
-fi
-
-fi
-
-{ echo "$as_me:$LINENO: checking for setsockopt" >&5
-echo $ECHO_N "checking for setsockopt... $ECHO_C" >&6; }
-if test "${ac_cv_func_setsockopt+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define setsockopt to an innocuous variant, in case <limits.h> declares setsockopt.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define setsockopt innocuous_setsockopt
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char setsockopt (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef setsockopt
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char setsockopt ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_setsockopt || defined __stub___setsockopt
-choke me
-#endif
-
-int
-main ()
-{
-return setsockopt ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_func_setsockopt=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_func_setsockopt=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_setsockopt" >&5
-echo "${ECHO_T}$ac_cv_func_setsockopt" >&6; }
-if test $ac_cv_func_setsockopt = yes; then
- :
-else
-
-{ echo "$as_me:$LINENO: checking for setsockopt in -lsocket" >&5
-echo $ECHO_N "checking for setsockopt in -lsocket... $ECHO_C" >&6; }
-if test "${ac_cv_lib_socket_setsockopt+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char setsockopt ();
-int
-main ()
-{
-return setsockopt ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_socket_setsockopt=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_socket_setsockopt=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_setsockopt" >&5
-echo "${ECHO_T}$ac_cv_lib_socket_setsockopt" >&6; }
-if test $ac_cv_lib_socket_setsockopt = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBSOCKET 1
-_ACEOF
-
- LIBS="-lsocket $LIBS"
-
-fi
-
-fi
-
-
-
-for ac_func in dirname
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-for ac_header in libgen.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-else
-
- { echo "$as_me:$LINENO: checking for dirname in -lgen" >&5
-echo $ECHO_N "checking for dirname in -lgen... $ECHO_C" >&6; }
-if test "${ac_cv_lib_gen_dirname+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lgen $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dirname ();
-int
-main ()
-{
-return dirname ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_gen_dirname=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_gen_dirname=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_gen_dirname" >&5
-echo "${ECHO_T}$ac_cv_lib_gen_dirname" >&6; }
-if test $ac_cv_lib_gen_dirname = yes; then
-
- { echo "$as_me:$LINENO: checking for broken dirname" >&5
-echo $ECHO_N "checking for broken dirname... $ECHO_C" >&6; }
-if test "${ac_cv_have_broken_dirname+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- save_LIBS="$LIBS"
- LIBS="$LIBS -lgen"
- if test "$cross_compiling" = yes; then
- ac_cv_have_broken_dirname="no"
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <libgen.h>
-#include <string.h>
-
-int main(int argc, char **argv) {
- char *s, buf[32];
-
- strncpy(buf,"/etc", 32);
- s = dirname(buf);
- if (!s || strncmp(s, "/", 32) != 0) {
- exit(1);
- } else {
- exit(0);
- }
-}
-
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_have_broken_dirname="no"
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
- ac_cv_have_broken_dirname="yes"
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
- LIBS="$save_LIBS"
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_broken_dirname" >&5
-echo "${ECHO_T}$ac_cv_have_broken_dirname" >&6; }
- if test "x$ac_cv_have_broken_dirname" = "xno" ; then
- LIBS="$LIBS -lgen"
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_DIRNAME 1
-_ACEOF
-
-
-for ac_header in libgen.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
- fi
-
-fi
-
-
-fi
-done
-
-
-{ echo "$as_me:$LINENO: checking for getspnam" >&5
-echo $ECHO_N "checking for getspnam... $ECHO_C" >&6; }
-if test "${ac_cv_func_getspnam+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define getspnam to an innocuous variant, in case <limits.h> declares getspnam.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define getspnam innocuous_getspnam
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char getspnam (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef getspnam
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getspnam ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_getspnam || defined __stub___getspnam
-choke me
-#endif
-
-int
-main ()
-{
-return getspnam ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_func_getspnam=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_func_getspnam=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_getspnam" >&5
-echo "${ECHO_T}$ac_cv_func_getspnam" >&6; }
-if test $ac_cv_func_getspnam = yes; then
- :
-else
- { echo "$as_me:$LINENO: checking for getspnam in -lgen" >&5
-echo $ECHO_N "checking for getspnam in -lgen... $ECHO_C" >&6; }
-if test "${ac_cv_lib_gen_getspnam+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lgen $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getspnam ();
-int
-main ()
-{
-return getspnam ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_gen_getspnam=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_gen_getspnam=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_gen_getspnam" >&5
-echo "${ECHO_T}$ac_cv_lib_gen_getspnam" >&6; }
-if test $ac_cv_lib_gen_getspnam = yes; then
- LIBS="$LIBS -lgen"
-fi
-
-fi
-
-{ echo "$as_me:$LINENO: checking for library containing basename" >&5
-echo $ECHO_N "checking for library containing basename... $ECHO_C" >&6; }
-if test "${ac_cv_search_basename+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char basename ();
-int
-main ()
-{
-return basename ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' gen; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_basename=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_basename+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_basename+set}" = set; then
- :
-else
- ac_cv_search_basename=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_basename" >&5
-echo "${ECHO_T}$ac_cv_search_basename" >&6; }
-ac_res=$ac_cv_search_basename
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_BASENAME 1
-_ACEOF
-
-fi
-
-
-
-# Check whether --with-zlib was given.
-if test "${with_zlib+set}" = set; then
- withval=$with_zlib; if test "x$withval" = "xno" ; then
- { { echo "$as_me:$LINENO: error: *** zlib is required ***" >&5
-echo "$as_me: error: *** zlib is required ***" >&2;}
- { (exit 1); exit 1; }; }
- elif test "x$withval" != "xyes"; then
- if test -d "$withval/lib"; then
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
- else
- LDFLAGS="-L${withval}/lib ${LDFLAGS}"
- fi
- else
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
- else
- LDFLAGS="-L${withval} ${LDFLAGS}"
- fi
- fi
- if test -d "$withval/include"; then
- CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
- else
- CPPFLAGS="-I${withval} ${CPPFLAGS}"
- fi
- fi
-
-fi
-
-
-if test "${ac_cv_header_zlib_h+set}" = set; then
- { echo "$as_me:$LINENO: checking for zlib.h" >&5
-echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_zlib_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
-echo "${ECHO_T}$ac_cv_header_zlib_h" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking zlib.h usability" >&5
-echo $ECHO_N "checking zlib.h usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <zlib.h>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking zlib.h presence" >&5
-echo $ECHO_N "checking zlib.h presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <zlib.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: zlib.h: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: zlib.h: present but cannot be compiled" >&5
-echo "$as_me: WARNING: zlib.h: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: zlib.h: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: zlib.h: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: zlib.h: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: zlib.h: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: zlib.h: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: zlib.h: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: zlib.h: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: zlib.h: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: zlib.h: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for zlib.h" >&5
-echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_zlib_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_header_zlib_h=$ac_header_preproc
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
-echo "${ECHO_T}$ac_cv_header_zlib_h" >&6; }
-
-fi
-if test $ac_cv_header_zlib_h = yes; then
- :
-else
- { { echo "$as_me:$LINENO: error: *** zlib.h missing - please install first or check config.log ***" >&5
-echo "$as_me: error: *** zlib.h missing - please install first or check config.log ***" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking for deflate in -lz" >&5
-echo $ECHO_N "checking for deflate in -lz... $ECHO_C" >&6; }
-if test "${ac_cv_lib_z_deflate+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lz $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char deflate ();
-int
-main ()
-{
-return deflate ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_z_deflate=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_z_deflate=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_z_deflate" >&5
-echo "${ECHO_T}$ac_cv_lib_z_deflate" >&6; }
-if test $ac_cv_lib_z_deflate = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBZ 1
-_ACEOF
-
- LIBS="-lz $LIBS"
-
-else
-
- saved_CPPFLAGS="$CPPFLAGS"
- saved_LDFLAGS="$LDFLAGS"
- save_LIBS="$LIBS"
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L/usr/local/lib -R/usr/local/lib ${saved_LDFLAGS}"
- else
- LDFLAGS="-L/usr/local/lib ${saved_LDFLAGS}"
- fi
- CPPFLAGS="-I/usr/local/include ${saved_CPPFLAGS}"
- LIBS="$LIBS -lz"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char deflate ();
-int
-main ()
-{
-return deflate ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_LIBZ 1
-_ACEOF
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { { echo "$as_me:$LINENO: error: *** zlib missing - please install first or check config.log ***" >&5
-echo "$as_me: error: *** zlib missing - please install first or check config.log ***" >&2;}
- { (exit 1); exit 1; }; }
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-
-fi
-
-
-
-# Check whether --with-zlib-version-check was given.
-if test "${with_zlib_version_check+set}" = set; then
- withval=$with_zlib_version_check; if test "x$withval" = "xno" ; then
- zlib_check_nonfatal=1
- fi
-
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking for possibly buggy zlib" >&5
-echo $ECHO_N "checking for possibly buggy zlib... $ECHO_C" >&6; }
-if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: WARNING: cross compiling: not checking zlib version" >&5
-echo "$as_me: WARNING: cross compiling: not checking zlib version" >&2;}
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <zlib.h>
-
-int
-main ()
-{
-
- int a=0, b=0, c=0, d=0, n, v;
- n = sscanf(ZLIB_VERSION, "%d.%d.%d.%d", &a, &b, &c, &d);
- if (n != 3 && n != 4)
- exit(1);
- v = a*1000000 + b*10000 + c*100 + d;
- fprintf(stderr, "found zlib version %s (%d)\n", ZLIB_VERSION, v);
-
- /* 1.1.4 is OK */
- if (a == 1 && b == 1 && c >= 4)
- exit(0);
-
- /* 1.2.3 and up are OK */
- if (v >= 1020300)
- exit(0);
-
- exit(2);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- if test -z "$zlib_check_nonfatal" ; then
- { { echo "$as_me:$LINENO: error: *** zlib too old - check config.log ***
-Your reported zlib version has known security problems. It's possible your
-vendor has fixed these problems without changing the version number. If you
-are sure this is the case, you can disable the check by running
-\"./configure --without-zlib-version-check\".
-If you are in doubt, upgrade zlib to version 1.2.3 or greater.
-See http://www.gzip.org/zlib/ for details." >&5
-echo "$as_me: error: *** zlib too old - check config.log ***
-Your reported zlib version has known security problems. It's possible your
-vendor has fixed these problems without changing the version number. If you
-are sure this is the case, you can disable the check by running
-\"./configure --without-zlib-version-check\".
-If you are in doubt, upgrade zlib to version 1.2.3 or greater.
-See http://www.gzip.org/zlib/ for details." >&2;}
- { (exit 1); exit 1; }; }
- else
- { echo "$as_me:$LINENO: WARNING: zlib version may have security problems" >&5
-echo "$as_me: WARNING: zlib version may have security problems" >&2;}
- fi
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking for strcasecmp" >&5
-echo $ECHO_N "checking for strcasecmp... $ECHO_C" >&6; }
-if test "${ac_cv_func_strcasecmp+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define strcasecmp to an innocuous variant, in case <limits.h> declares strcasecmp.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define strcasecmp innocuous_strcasecmp
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char strcasecmp (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef strcasecmp
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char strcasecmp ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_strcasecmp || defined __stub___strcasecmp
-choke me
-#endif
-
-int
-main ()
-{
-return strcasecmp ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_func_strcasecmp=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_func_strcasecmp=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_strcasecmp" >&5
-echo "${ECHO_T}$ac_cv_func_strcasecmp" >&6; }
-if test $ac_cv_func_strcasecmp = yes; then
- :
-else
- { echo "$as_me:$LINENO: checking for strcasecmp in -lresolv" >&5
-echo $ECHO_N "checking for strcasecmp in -lresolv... $ECHO_C" >&6; }
-if test "${ac_cv_lib_resolv_strcasecmp+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lresolv $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char strcasecmp ();
-int
-main ()
-{
-return strcasecmp ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_resolv_strcasecmp=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_resolv_strcasecmp=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_strcasecmp" >&5
-echo "${ECHO_T}$ac_cv_lib_resolv_strcasecmp" >&6; }
-if test $ac_cv_lib_resolv_strcasecmp = yes; then
- LIBS="$LIBS -lresolv"
-fi
-
-
-fi
-
-
-for ac_func in utimes
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-else
- { echo "$as_me:$LINENO: checking for utimes in -lc89" >&5
-echo $ECHO_N "checking for utimes in -lc89... $ECHO_C" >&6; }
-if test "${ac_cv_lib_c89_utimes+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lc89 $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char utimes ();
-int
-main ()
-{
-return utimes ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_c89_utimes=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_c89_utimes=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_c89_utimes" >&5
-echo "${ECHO_T}$ac_cv_lib_c89_utimes" >&6; }
-if test $ac_cv_lib_c89_utimes = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_UTIMES 1
-_ACEOF
-
- LIBS="$LIBS -lc89"
-fi
-
-
-fi
-done
-
-
-
-
-for ac_header in bsd/libutil.h libutil.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-{ echo "$as_me:$LINENO: checking for library containing fmt_scaled" >&5
-echo $ECHO_N "checking for library containing fmt_scaled... $ECHO_C" >&6; }
-if test "${ac_cv_search_fmt_scaled+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char fmt_scaled ();
-int
-main ()
-{
-return fmt_scaled ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' util bsd; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_fmt_scaled=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_fmt_scaled+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_fmt_scaled+set}" = set; then
- :
-else
- ac_cv_search_fmt_scaled=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_fmt_scaled" >&5
-echo "${ECHO_T}$ac_cv_search_fmt_scaled" >&6; }
-ac_res=$ac_cv_search_fmt_scaled
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-{ echo "$as_me:$LINENO: checking for library containing scan_scaled" >&5
-echo $ECHO_N "checking for library containing scan_scaled... $ECHO_C" >&6; }
-if test "${ac_cv_search_scan_scaled+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char scan_scaled ();
-int
-main ()
-{
-return scan_scaled ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' util bsd; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_scan_scaled=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_scan_scaled+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_scan_scaled+set}" = set; then
- :
-else
- ac_cv_search_scan_scaled=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_scan_scaled" >&5
-echo "${ECHO_T}$ac_cv_search_scan_scaled" >&6; }
-ac_res=$ac_cv_search_scan_scaled
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-{ echo "$as_me:$LINENO: checking for library containing login" >&5
-echo $ECHO_N "checking for library containing login... $ECHO_C" >&6; }
-if test "${ac_cv_search_login+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char login ();
-int
-main ()
-{
-return login ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' util bsd; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_login=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_login+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_login+set}" = set; then
- :
-else
- ac_cv_search_login=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_login" >&5
-echo "${ECHO_T}$ac_cv_search_login" >&6; }
-ac_res=$ac_cv_search_login
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-{ echo "$as_me:$LINENO: checking for library containing logout" >&5
-echo $ECHO_N "checking for library containing logout... $ECHO_C" >&6; }
-if test "${ac_cv_search_logout+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char logout ();
-int
-main ()
-{
-return logout ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' util bsd; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_logout=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_logout+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_logout+set}" = set; then
- :
-else
- ac_cv_search_logout=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_logout" >&5
-echo "${ECHO_T}$ac_cv_search_logout" >&6; }
-ac_res=$ac_cv_search_logout
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-{ echo "$as_me:$LINENO: checking for library containing logwtmp" >&5
-echo $ECHO_N "checking for library containing logwtmp... $ECHO_C" >&6; }
-if test "${ac_cv_search_logwtmp+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char logwtmp ();
-int
-main ()
-{
-return logwtmp ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' util bsd; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_logwtmp=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_logwtmp+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_logwtmp+set}" = set; then
- :
-else
- ac_cv_search_logwtmp=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_logwtmp" >&5
-echo "${ECHO_T}$ac_cv_search_logwtmp" >&6; }
-ac_res=$ac_cv_search_logwtmp
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-{ echo "$as_me:$LINENO: checking for library containing openpty" >&5
-echo $ECHO_N "checking for library containing openpty... $ECHO_C" >&6; }
-if test "${ac_cv_search_openpty+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char openpty ();
-int
-main ()
-{
-return openpty ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' util bsd; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_openpty=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_openpty+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_openpty+set}" = set; then
- :
-else
- ac_cv_search_openpty=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_openpty" >&5
-echo "${ECHO_T}$ac_cv_search_openpty" >&6; }
-ac_res=$ac_cv_search_openpty
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-{ echo "$as_me:$LINENO: checking for library containing updwtmp" >&5
-echo $ECHO_N "checking for library containing updwtmp... $ECHO_C" >&6; }
-if test "${ac_cv_search_updwtmp+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char updwtmp ();
-int
-main ()
-{
-return updwtmp ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' util bsd; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_updwtmp=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_updwtmp+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_updwtmp+set}" = set; then
- :
-else
- ac_cv_search_updwtmp=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_updwtmp" >&5
-echo "${ECHO_T}$ac_cv_search_updwtmp" >&6; }
-ac_res=$ac_cv_search_updwtmp
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-
-
-
-
-
-
-
-for ac_func in fmt_scaled scan_scaled login logout openpty updwtmp logwtmp
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-# On some platforms, inet_ntop may be found in libresolv or libnsl.
-{ echo "$as_me:$LINENO: checking for library containing inet_ntop" >&5
-echo $ECHO_N "checking for library containing inet_ntop... $ECHO_C" >&6; }
-if test "${ac_cv_search_inet_ntop+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char inet_ntop ();
-int
-main ()
-{
-return inet_ntop ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' resolv nsl; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_inet_ntop=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_inet_ntop+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_inet_ntop+set}" = set; then
- :
-else
- ac_cv_search_inet_ntop=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_inet_ntop" >&5
-echo "${ECHO_T}$ac_cv_search_inet_ntop" >&6; }
-ac_res=$ac_cv_search_inet_ntop
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-
-
-for ac_func in strftime
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-else
- # strftime is in -lintl on SCO UNIX.
-{ echo "$as_me:$LINENO: checking for strftime in -lintl" >&5
-echo $ECHO_N "checking for strftime in -lintl... $ECHO_C" >&6; }
-if test "${ac_cv_lib_intl_strftime+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lintl $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char strftime ();
-int
-main ()
-{
-return strftime ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_intl_strftime=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_intl_strftime=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_intl_strftime" >&5
-echo "${ECHO_T}$ac_cv_lib_intl_strftime" >&6; }
-if test $ac_cv_lib_intl_strftime = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_STRFTIME 1
-_ACEOF
-
-LIBS="-lintl $LIBS"
-fi
-
-fi
-done
-
-
-# Check for ALTDIRFUNC glob() extension
-{ echo "$as_me:$LINENO: checking for GLOB_ALTDIRFUNC support" >&5
-echo $ECHO_N "checking for GLOB_ALTDIRFUNC support... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <glob.h>
- #ifdef GLOB_ALTDIRFUNC
- FOUNDIT
- #endif
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "FOUNDIT" >/dev/null 2>&1; then
-
-
-cat >>confdefs.h <<\_ACEOF
-#define GLOB_HAS_ALTDIRFUNC 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-
-fi
-rm -f conftest*
-
-
-# Check for g.gl_matchc glob() extension
-{ echo "$as_me:$LINENO: checking for gl_matchc field in glob_t" >&5
-echo $ECHO_N "checking for gl_matchc field in glob_t... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <glob.h>
-int
-main ()
-{
- glob_t g; g.gl_matchc = 1;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-
-cat >>confdefs.h <<\_ACEOF
-#define GLOB_HAS_GL_MATCHC 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-# Check for g.gl_statv glob() extension
-{ echo "$as_me:$LINENO: checking for gl_statv and GLOB_KEEPSTAT extensions for glob" >&5
-echo $ECHO_N "checking for gl_statv and GLOB_KEEPSTAT extensions for glob... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <glob.h>
-int
-main ()
-{
-
-#ifndef GLOB_KEEPSTAT
-#error "glob does not support GLOB_KEEPSTAT extension"
-#endif
-glob_t g;
-g.gl_statv = NULL;
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-
-cat >>confdefs.h <<\_ACEOF
-#define GLOB_HAS_GL_STATV 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-{ echo "$as_me:$LINENO: checking whether GLOB_NOMATCH is declared" >&5
-echo $ECHO_N "checking whether GLOB_NOMATCH is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_GLOB_NOMATCH+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <glob.h>
-
-int
-main ()
-{
-#ifndef GLOB_NOMATCH
- (void) GLOB_NOMATCH;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_GLOB_NOMATCH=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_GLOB_NOMATCH=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_GLOB_NOMATCH" >&5
-echo "${ECHO_T}$ac_cv_have_decl_GLOB_NOMATCH" >&6; }
-if test $ac_cv_have_decl_GLOB_NOMATCH = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_GLOB_NOMATCH 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_GLOB_NOMATCH 0
-_ACEOF
-
-
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking whether struct dirent allocates space for d_name" >&5
-echo $ECHO_N "checking whether struct dirent allocates space for d_name... $ECHO_C" >&6; }
-if test "$cross_compiling" = yes; then
-
- { echo "$as_me:$LINENO: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&5
-echo "$as_me: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&2;}
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1
-_ACEOF
-
-
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <dirent.h>
-int
-main ()
-{
-
- struct dirent d;
- exit(sizeof(d.d_name)<=sizeof(char));
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1
-_ACEOF
-
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking for /proc/pid/fd directory" >&5
-echo $ECHO_N "checking for /proc/pid/fd directory... $ECHO_C" >&6; }
-if test -d "/proc/$$/fd" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_PROC_PID 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-# Check whether user wants S/Key support
-SKEY_MSG="no"
-
-# Check whether --with-skey was given.
-if test "${with_skey+set}" = set; then
- withval=$with_skey;
- if test "x$withval" != "xno" ; then
-
- if test "x$withval" != "xyes" ; then
- CPPFLAGS="$CPPFLAGS -I${withval}/include"
- LDFLAGS="$LDFLAGS -L${withval}/lib"
- fi
-
-
-cat >>confdefs.h <<\_ACEOF
-#define SKEY 1
-_ACEOF
-
- LIBS="-lskey $LIBS"
- SKEY_MSG="yes"
-
- { echo "$as_me:$LINENO: checking for s/key support" >&5
-echo $ECHO_N "checking for s/key support... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-#include <skey.h>
-
-int
-main ()
-{
-
- char *ff = skey_keyinfo(""); ff="";
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- { { echo "$as_me:$LINENO: error: ** Incomplete or missing s/key libraries." >&5
-echo "$as_me: error: ** Incomplete or missing s/key libraries." >&2;}
- { (exit 1); exit 1; }; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
- { echo "$as_me:$LINENO: checking if skeychallenge takes 4 arguments" >&5
-echo $ECHO_N "checking if skeychallenge takes 4 arguments... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-#include <skey.h>
-
-int
-main ()
-{
-
- (void)skeychallenge(NULL,"name","",0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define SKEYCHALLENGE_4ARG 1
-_ACEOF
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- fi
-
-
-fi
-
-
-# Check whether user wants to use ldns
-LDNS_MSG="no"
-
-# Check whether --with-ldns was given.
-if test "${with_ldns+set}" = set; then
- withval=$with_ldns;
- if test "x$withval" != "xno" ; then
-
- if test "x$withval" != "xyes" ; then
- CPPFLAGS="$CPPFLAGS -I${withval}/include"
- LDFLAGS="$LDFLAGS -L${withval}/lib"
- fi
-
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_LDNS 1
-_ACEOF
-
- LIBS="-lldns $LIBS"
- LDNS_MSG="yes"
-
- { echo "$as_me:$LINENO: checking for ldns support" >&5
-echo $ECHO_N "checking for ldns support... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <ldns/ldns.h>
-int main() { ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); status=LDNS_STATUS_OK; exit(0); }
-
-
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- { { echo "$as_me:$LINENO: error: ** Incomplete or missing ldns libraries." >&5
-echo "$as_me: error: ** Incomplete or missing ldns libraries." >&2;}
- { (exit 1); exit 1; }; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
- fi
-
-
-fi
-
-
-# Check whether user wants libedit support
-LIBEDIT_MSG="no"
-
-# Check whether --with-libedit was given.
-if test "${with_libedit+set}" = set; then
- withval=$with_libedit; if test "x$withval" != "xno" ; then
- if test "x$withval" = "xyes" ; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
-set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_PKGCONFIG+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $PKGCONFIG in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_PKGCONFIG="$PKGCONFIG" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_PKGCONFIG="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-PKGCONFIG=$ac_cv_path_PKGCONFIG
-if test -n "$PKGCONFIG"; then
- { echo "$as_me:$LINENO: result: $PKGCONFIG" >&5
-echo "${ECHO_T}$PKGCONFIG" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_path_PKGCONFIG"; then
- ac_pt_PKGCONFIG=$PKGCONFIG
- # Extract the first word of "pkg-config", so it can be a program name with args.
-set dummy pkg-config; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_ac_pt_PKGCONFIG+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $ac_pt_PKGCONFIG in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_ac_pt_PKGCONFIG="$ac_pt_PKGCONFIG" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_ac_pt_PKGCONFIG="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-ac_pt_PKGCONFIG=$ac_cv_path_ac_pt_PKGCONFIG
-if test -n "$ac_pt_PKGCONFIG"; then
- { echo "$as_me:$LINENO: result: $ac_pt_PKGCONFIG" >&5
-echo "${ECHO_T}$ac_pt_PKGCONFIG" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
- if test "x$ac_pt_PKGCONFIG" = x; then
- PKGCONFIG="no"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
- PKGCONFIG=$ac_pt_PKGCONFIG
- fi
-else
- PKGCONFIG="$ac_cv_path_PKGCONFIG"
-fi
-
- if test "x$PKGCONFIG" != "xno"; then
- { echo "$as_me:$LINENO: checking if $PKGCONFIG knows about libedit" >&5
-echo $ECHO_N "checking if $PKGCONFIG knows about libedit... $ECHO_C" >&6; }
- if "$PKGCONFIG" libedit; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- use_pkgconfig_for_libedit=yes
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
- fi
- else
- CPPFLAGS="$CPPFLAGS -I${withval}/include"
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
- else
- LDFLAGS="-L${withval}/lib ${LDFLAGS}"
- fi
- fi
- if test "x$use_pkgconfig_for_libedit" = "xyes"; then
- LIBEDIT=`$PKGCONFIG --libs libedit`
- CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libedit`"
- else
- LIBEDIT="-ledit -lcurses"
- fi
- OTHERLIBS=`echo $LIBEDIT | sed 's/-ledit//'`
- { echo "$as_me:$LINENO: checking for el_init in -ledit" >&5
-echo $ECHO_N "checking for el_init in -ledit... $ECHO_C" >&6; }
-if test "${ac_cv_lib_edit_el_init+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ledit $OTHERLIBS
- $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char el_init ();
-int
-main ()
-{
-return el_init ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_edit_el_init=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_edit_el_init=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_edit_el_init" >&5
-echo "${ECHO_T}$ac_cv_lib_edit_el_init" >&6; }
-if test $ac_cv_lib_edit_el_init = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_LIBEDIT 1
-_ACEOF
-
- LIBEDIT_MSG="yes"
-
-
-else
- { { echo "$as_me:$LINENO: error: libedit not found" >&5
-echo "$as_me: error: libedit not found" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
- { echo "$as_me:$LINENO: checking if libedit version is compatible" >&5
-echo $ECHO_N "checking if libedit version is compatible... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <histedit.h>
-int
-main ()
-{
-
- int i = H_SETSIZE;
- el_init("", NULL, NULL, NULL);
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- { { echo "$as_me:$LINENO: error: libedit version is not compatible" >&5
-echo "$as_me: error: libedit version is not compatible" >&2;}
- { (exit 1); exit 1; }; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- fi
-
-fi
-
-
-AUDIT_MODULE=none
-
-# Check whether --with-audit was given.
-if test "${with_audit+set}" = set; then
- withval=$with_audit;
- { echo "$as_me:$LINENO: checking for supported audit module" >&5
-echo $ECHO_N "checking for supported audit module... $ECHO_C" >&6; }
- case "$withval" in
- bsm)
- { echo "$as_me:$LINENO: result: bsm" >&5
-echo "${ECHO_T}bsm" >&6; }
- AUDIT_MODULE=bsm
-
-for ac_header in bsm/audit.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#ifdef HAVE_TIME_H
-# include <time.h>
-#endif
-
-
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- eval "$as_ac_Header=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_Header=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-else
- { { echo "$as_me:$LINENO: error: BSM enabled and bsm/audit.h not found" >&5
-echo "$as_me: error: BSM enabled and bsm/audit.h not found" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-done
-
-
-{ echo "$as_me:$LINENO: checking for getaudit in -lbsm" >&5
-echo $ECHO_N "checking for getaudit in -lbsm... $ECHO_C" >&6; }
-if test "${ac_cv_lib_bsm_getaudit+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lbsm $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getaudit ();
-int
-main ()
-{
-return getaudit ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_bsm_getaudit=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_bsm_getaudit=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_bsm_getaudit" >&5
-echo "${ECHO_T}$ac_cv_lib_bsm_getaudit" >&6; }
-if test $ac_cv_lib_bsm_getaudit = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBBSM 1
-_ACEOF
-
- LIBS="-lbsm $LIBS"
-
-else
- { { echo "$as_me:$LINENO: error: BSM enabled and required library not found" >&5
-echo "$as_me: error: BSM enabled and required library not found" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-
-for ac_func in getaudit
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-else
- { { echo "$as_me:$LINENO: error: BSM enabled and required function not found" >&5
-echo "$as_me: error: BSM enabled and required function not found" >&2;}
- { (exit 1); exit 1; }; }
-fi
-done
-
- # These are optional
-
-
-for ac_func in getaudit_addr aug_get_machine
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_BSM_AUDIT 1
-_ACEOF
-
- if test "$sol2ver" -ge 11; then
- SSHDLIBS="$SSHDLIBS -lscf"
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_BSM_API 1
-_ACEOF
-
- fi
- ;;
- linux)
- { echo "$as_me:$LINENO: result: linux" >&5
-echo "${ECHO_T}linux" >&6; }
- AUDIT_MODULE=linux
-
-for ac_header in libaudit.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
- SSHDLIBS="$SSHDLIBS -laudit"
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_LINUX_AUDIT 1
-_ACEOF
-
- ;;
- debug)
- AUDIT_MODULE=debug
- { echo "$as_me:$LINENO: result: debug" >&5
-echo "${ECHO_T}debug" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define SSH_AUDIT_EVENTS 1
-_ACEOF
-
- ;;
- no)
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- ;;
- *)
- { { echo "$as_me:$LINENO: error: Unknown audit module $withval" >&5
-echo "$as_me: error: Unknown audit module $withval" >&2;}
- { (exit 1); exit 1; }; }
- ;;
- esac
-
-fi
-
-
-
-# Check whether --with-pie was given.
-if test "${with_pie+set}" = set; then
- withval=$with_pie;
- if test "x$withval" = "xno"; then
- use_pie=no
- fi
- if test "x$withval" = "xyes"; then
- use_pie=yes
- fi
-
-
-fi
-
-if test "x$use_pie" = "x"; then
- use_pie=no
-fi
-if test "x$use_toolchain_hardening" != "x1" && test "x$use_pie" = "xauto"; then
- # Turn off automatic PIE when toolchain hardening is off.
- use_pie=no
-fi
-if test "x$use_pie" = "xauto"; then
- # Automatic PIE requires gcc >= 4.x
- { echo "$as_me:$LINENO: checking for gcc >= 4.x" >&5
-echo $ECHO_N "checking for gcc >= 4.x... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#if !defined(__GNUC__) || __GNUC__ < 4
-#error gcc is too old
-#endif
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- use_pie=no
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-if test "x$use_pie" != "xno"; then
- SAVED_CFLAGS="$CFLAGS"
- SAVED_LDFLAGS="$LDFLAGS"
- {
- { echo "$as_me:$LINENO: checking if $CC supports compile flag -fPIE" >&5
-echo $ECHO_N "checking if $CC supports compile flag -fPIE... $ECHO_C" >&6; }
- saved_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $WERROR -fPIE"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-fPIE"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-if `grep -i "unrecognized option" conftest.err >/dev/null`
-then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-else
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- CFLAGS="$saved_CFLAGS $_define_flag"
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$saved_CFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-}
- {
- { echo "$as_me:$LINENO: checking if $LD supports link flag -pie" >&5
-echo $ECHO_N "checking if $LD supports link flag -pie... $ECHO_C" >&6; }
- saved_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $WERROR -pie"
- _define_flag=""
- test "x$_define_flag" = "x" && _define_flag="-pie"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char **argv) {
- /* Some math to catch -ftrapv problems in the toolchain */
- int i = 123 * argc, j = 456 + argc, k = 789 - argc;
- float l = i * 2.1;
- double m = l / 0.5;
- long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
- printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
- exit(0);
-}
-
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- LDFLAGS="$saved_LDFLAGS $_define_flag"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- LDFLAGS="$saved_LDFLAGS"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-}
- # We use both -fPIE and -pie or neither.
- { echo "$as_me:$LINENO: checking whether both -fPIE and -pie are supported" >&5
-echo $ECHO_N "checking whether both -fPIE and -pie are supported... $ECHO_C" >&6; }
- if echo "x $CFLAGS" | grep ' -fPIE' >/dev/null 2>&1 && \
- echo "x $LDFLAGS" | grep ' -pie' >/dev/null 2>&1 ; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- CFLAGS="$SAVED_CFLAGS"
- LDFLAGS="$SAVED_LDFLAGS"
- fi
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-for ac_func in \
- Blowfish_initstate \
- Blowfish_expandstate \
- Blowfish_expand0state \
- Blowfish_stream2word \
- asprintf \
- b64_ntop \
- __b64_ntop \
- b64_pton \
- __b64_pton \
- bcopy \
- bcrypt_pbkdf \
- bindresvport_sa \
- blf_enc \
- cap_rights_limit \
- clock \
- closefrom \
- dirfd \
- endgrent \
- explicit_bzero \
- fchmod \
- fchown \
- freeaddrinfo \
- fstatfs \
- fstatvfs \
- futimes \
- getaddrinfo \
- getcwd \
- getgrouplist \
- getnameinfo \
- getopt \
- getpeereid \
- getpeerucred \
- getpgid \
- getpgrp \
- _getpty \
- getrlimit \
- getttyent \
- glob \
- group_from_gid \
- inet_aton \
- inet_ntoa \
- inet_ntop \
- innetgr \
- login_getcapbool \
- mblen \
- md5_crypt \
- memmove \
- memset_s \
- mkdtemp \
- mmap \
- ngetaddrinfo \
- nsleep \
- ogetaddrinfo \
- openlog_r \
- poll \
- prctl \
- pstat \
- readpassphrase \
- reallocarray \
- realpath \
- recvmsg \
- rresvport_af \
- sendmsg \
- setdtablesize \
- setegid \
- setenv \
- seteuid \
- setgroupent \
- setgroups \
- setlinebuf \
- setlogin \
- setpassent\
- setpcred \
- setproctitle \
- setregid \
- setreuid \
- setrlimit \
- setsid \
- setvbuf \
- sigaction \
- sigvec \
- snprintf \
- socketpair \
- statfs \
- statvfs \
- strdup \
- strerror \
- strlcat \
- strlcpy \
- strmode \
- strnlen \
- strnvis \
- strptime \
- strtonum \
- strtoll \
- strtoul \
- strtoull \
- swap32 \
- sysconf \
- tcgetpgrp \
- timingsafe_bcmp \
- truncate \
- unsetenv \
- updwtmpx \
- user_from_uid \
- usleep \
- vasprintf \
- vsnprintf \
- waitpid \
-
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <ctype.h>
-int
-main ()
-{
- return (isblank('a'));
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ISBLANK 1
-_ACEOF
-
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-# PKCS11 depends on OpenSSL.
-if test "x$openssl" = "xyes" ; then
- # PKCS#11 support requires dlopen() and co
- { echo "$as_me:$LINENO: checking for library containing dlopen" >&5
-echo $ECHO_N "checking for library containing dlopen... $ECHO_C" >&6; }
-if test "${ac_cv_search_dlopen+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen ();
-int
-main ()
-{
-return dlopen ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' dl; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_dlopen=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_dlopen+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_dlopen+set}" = set; then
- :
-else
- ac_cv_search_dlopen=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_dlopen" >&5
-echo "${ECHO_T}$ac_cv_search_dlopen" >&6; }
-ac_res=$ac_cv_search_dlopen
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_PKCS11
-_ACEOF
-
-
-fi
-
-fi
-
-# IRIX has a const char return value for gai_strerror()
-
-for ac_func in gai_strerror
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_GAI_STRERROR 1
-_ACEOF
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-const char *gai_strerror(int);
-
-int
-main ()
-{
-
- char *str;
- str = gai_strerror(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_CONST_GAI_STRERROR_PROTO 1
-_ACEOF
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-done
-
-
-{ echo "$as_me:$LINENO: checking for library containing nanosleep" >&5
-echo $ECHO_N "checking for library containing nanosleep... $ECHO_C" >&6; }
-if test "${ac_cv_search_nanosleep+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char nanosleep ();
-int
-main ()
-{
-return nanosleep ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' rt posix4; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_nanosleep=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_nanosleep+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_nanosleep+set}" = set; then
- :
-else
- ac_cv_search_nanosleep=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_nanosleep" >&5
-echo "${ECHO_T}$ac_cv_search_nanosleep" >&6; }
-ac_res=$ac_cv_search_nanosleep
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_NANOSLEEP 1
-_ACEOF
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking for library containing clock_gettime" >&5
-echo $ECHO_N "checking for library containing clock_gettime... $ECHO_C" >&6; }
-if test "${ac_cv_search_clock_gettime+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char clock_gettime ();
-int
-main ()
-{
-return clock_gettime ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' rt; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_clock_gettime=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_clock_gettime+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_clock_gettime+set}" = set; then
- :
-else
- ac_cv_search_clock_gettime=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_clock_gettime" >&5
-echo "${ECHO_T}$ac_cv_search_clock_gettime" >&6; }
-ac_res=$ac_cv_search_clock_gettime
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_CLOCK_GETTIME 1
-_ACEOF
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking whether getrusage is declared" >&5
-echo $ECHO_N "checking whether getrusage is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_getrusage+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-#ifndef getrusage
- (void) getrusage;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_getrusage=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_getrusage=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_getrusage" >&5
-echo "${ECHO_T}$ac_cv_have_decl_getrusage" >&6; }
-if test $ac_cv_have_decl_getrusage = yes; then
-
-for ac_func in getrusage
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-fi
-
-{ echo "$as_me:$LINENO: checking whether strsep is declared" >&5
-echo $ECHO_N "checking whether strsep is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_strsep+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif
-
-
-int
-main ()
-{
-#ifndef strsep
- (void) strsep;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_strsep=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_strsep=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_strsep" >&5
-echo "${ECHO_T}$ac_cv_have_decl_strsep" >&6; }
-if test $ac_cv_have_decl_strsep = yes; then
-
-for ac_func in strsep
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking whether tcsendbreak is declared" >&5
-echo $ECHO_N "checking whether tcsendbreak is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_tcsendbreak+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <termios.h>
-
-
-int
-main ()
-{
-#ifndef tcsendbreak
- (void) tcsendbreak;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_tcsendbreak=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_tcsendbreak=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_tcsendbreak" >&5
-echo "${ECHO_T}$ac_cv_have_decl_tcsendbreak" >&6; }
-if test $ac_cv_have_decl_tcsendbreak = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_TCSENDBREAK 1
-_ACEOF
-
-else
-
-for ac_func in tcsendbreak
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking whether h_errno is declared" >&5
-echo $ECHO_N "checking whether h_errno is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_h_errno+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <netdb.h>
-
-int
-main ()
-{
-#ifndef h_errno
- (void) h_errno;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_h_errno=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_h_errno=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_h_errno" >&5
-echo "${ECHO_T}$ac_cv_have_decl_h_errno" >&6; }
-if test $ac_cv_have_decl_h_errno = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_H_ERRNO 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_H_ERRNO 0
-_ACEOF
-
-
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking whether SHUT_RD is declared" >&5
-echo $ECHO_N "checking whether SHUT_RD is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_SHUT_RD+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-
-int
-main ()
-{
-#ifndef SHUT_RD
- (void) SHUT_RD;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_SHUT_RD=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_SHUT_RD=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_SHUT_RD" >&5
-echo "${ECHO_T}$ac_cv_have_decl_SHUT_RD" >&6; }
-if test $ac_cv_have_decl_SHUT_RD = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SHUT_RD 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SHUT_RD 0
-_ACEOF
-
-
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking whether O_NONBLOCK is declared" >&5
-echo $ECHO_N "checking whether O_NONBLOCK is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_O_NONBLOCK+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-
-
-int
-main ()
-{
-#ifndef O_NONBLOCK
- (void) O_NONBLOCK;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_O_NONBLOCK=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_O_NONBLOCK=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_O_NONBLOCK" >&5
-echo "${ECHO_T}$ac_cv_have_decl_O_NONBLOCK" >&6; }
-if test $ac_cv_have_decl_O_NONBLOCK = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_O_NONBLOCK 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_O_NONBLOCK 0
-_ACEOF
-
-
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking whether writev is declared" >&5
-echo $ECHO_N "checking whether writev is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_writev+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-
-
-int
-main ()
-{
-#ifndef writev
- (void) writev;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_writev=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_writev=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_writev" >&5
-echo "${ECHO_T}$ac_cv_have_decl_writev" >&6; }
-if test $ac_cv_have_decl_writev = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_WRITEV 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_WRITEV 0
-_ACEOF
-
-
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking whether MAXSYMLINKS is declared" >&5
-echo $ECHO_N "checking whether MAXSYMLINKS is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_MAXSYMLINKS+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/param.h>
-
-
-int
-main ()
-{
-#ifndef MAXSYMLINKS
- (void) MAXSYMLINKS;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_MAXSYMLINKS=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_MAXSYMLINKS=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_MAXSYMLINKS" >&5
-echo "${ECHO_T}$ac_cv_have_decl_MAXSYMLINKS" >&6; }
-if test $ac_cv_have_decl_MAXSYMLINKS = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_MAXSYMLINKS 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_MAXSYMLINKS 0
-_ACEOF
-
-
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking whether offsetof is declared" >&5
-echo $ECHO_N "checking whether offsetof is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_offsetof+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stddef.h>
-
-
-int
-main ()
-{
-#ifndef offsetof
- (void) offsetof;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_offsetof=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_offsetof=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_offsetof" >&5
-echo "${ECHO_T}$ac_cv_have_decl_offsetof" >&6; }
-if test $ac_cv_have_decl_offsetof = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_OFFSETOF 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_OFFSETOF 0
-_ACEOF
-
-
-fi
-
-
-
-# extra bits for select(2)
-{ echo "$as_me:$LINENO: checking whether howmany is declared" >&5
-echo $ECHO_N "checking whether howmany is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_howmany+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_SYSMACROS_H
-#include <sys/sysmacros.h>
-#endif
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-
-int
-main ()
-{
-#ifndef howmany
- (void) howmany;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_howmany=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_howmany=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_howmany" >&5
-echo "${ECHO_T}$ac_cv_have_decl_howmany" >&6; }
-if test $ac_cv_have_decl_howmany = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_HOWMANY 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_HOWMANY 0
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking whether NFDBITS is declared" >&5
-echo $ECHO_N "checking whether NFDBITS is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_NFDBITS+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_SYSMACROS_H
-#include <sys/sysmacros.h>
-#endif
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-
-int
-main ()
-{
-#ifndef NFDBITS
- (void) NFDBITS;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_NFDBITS=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_NFDBITS=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_NFDBITS" >&5
-echo "${ECHO_T}$ac_cv_have_decl_NFDBITS" >&6; }
-if test $ac_cv_have_decl_NFDBITS = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_NFDBITS 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_NFDBITS 0
-_ACEOF
-
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking for fd_mask" >&5
-echo $ECHO_N "checking for fd_mask... $ECHO_C" >&6; }
-if test "${ac_cv_type_fd_mask+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-
-typedef fd_mask ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_fd_mask=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_fd_mask=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_fd_mask" >&5
-echo "${ECHO_T}$ac_cv_type_fd_mask" >&6; }
-if test $ac_cv_type_fd_mask = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_FD_MASK 1
-_ACEOF
-
-
-fi
-
-
-
-for ac_func in setresuid
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
- { echo "$as_me:$LINENO: checking if setresuid seems to work" >&5
-echo $ECHO_N "checking if setresuid seems to work... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: WARNING: cross compiling: not checking setresuid" >&5
-echo "$as_me: WARNING: cross compiling: not checking setresuid" >&2;}
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <errno.h>
-
-int
-main ()
-{
-
- errno=0;
- setresuid(0,0,0);
- if (errno==ENOSYS)
- exit(1);
- else
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETRESUID 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: not implemented" >&5
-echo "${ECHO_T}not implemented" >&6; }
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
-fi
-done
-
-
-
-for ac_func in setresgid
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
- { echo "$as_me:$LINENO: checking if setresgid seems to work" >&5
-echo $ECHO_N "checking if setresgid seems to work... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: WARNING: cross compiling: not checking setresuid" >&5
-echo "$as_me: WARNING: cross compiling: not checking setresuid" >&2;}
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#include <errno.h>
-
-int
-main ()
-{
-
- errno=0;
- setresgid(0,0,0);
- if (errno==ENOSYS)
- exit(1);
- else
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETRESGID 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: not implemented" >&5
-echo "${ECHO_T}not implemented" >&6; }
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
-fi
-done
-
-
-
-
-for ac_func in gettimeofday time
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-
-
-
-
-
-for ac_func in endutent getutent getutid getutline pututline setutent
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-for ac_func in utmpname
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-
-
-
-
-
-for ac_func in endutxent getutxent getutxid getutxline getutxuser pututxline
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-
-
-for ac_func in setutxdb setutxent utmpxname
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-for ac_func in getlastlogxbyname
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-{ echo "$as_me:$LINENO: checking for daemon" >&5
-echo $ECHO_N "checking for daemon... $ECHO_C" >&6; }
-if test "${ac_cv_func_daemon+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define daemon to an innocuous variant, in case <limits.h> declares daemon.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define daemon innocuous_daemon
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char daemon (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef daemon
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char daemon ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_daemon || defined __stub___daemon
-choke me
-#endif
-
-int
-main ()
-{
-return daemon ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_func_daemon=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_func_daemon=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_daemon" >&5
-echo "${ECHO_T}$ac_cv_func_daemon" >&6; }
-if test $ac_cv_func_daemon = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DAEMON 1
-_ACEOF
-
-else
- { echo "$as_me:$LINENO: checking for daemon in -lbsd" >&5
-echo $ECHO_N "checking for daemon in -lbsd... $ECHO_C" >&6; }
-if test "${ac_cv_lib_bsd_daemon+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lbsd $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char daemon ();
-int
-main ()
-{
-return daemon ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_bsd_daemon=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_bsd_daemon=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_daemon" >&5
-echo "${ECHO_T}$ac_cv_lib_bsd_daemon" >&6; }
-if test $ac_cv_lib_bsd_daemon = yes; then
- LIBS="$LIBS -lbsd"; cat >>confdefs.h <<\_ACEOF
-#define HAVE_DAEMON 1
-_ACEOF
-
-fi
-
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking for getpagesize" >&5
-echo $ECHO_N "checking for getpagesize... $ECHO_C" >&6; }
-if test "${ac_cv_func_getpagesize+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define getpagesize to an innocuous variant, in case <limits.h> declares getpagesize.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define getpagesize innocuous_getpagesize
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char getpagesize (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef getpagesize
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getpagesize ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_getpagesize || defined __stub___getpagesize
-choke me
-#endif
-
-int
-main ()
-{
-return getpagesize ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_func_getpagesize=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_func_getpagesize=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_getpagesize" >&5
-echo "${ECHO_T}$ac_cv_func_getpagesize" >&6; }
-if test $ac_cv_func_getpagesize = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_GETPAGESIZE 1
-_ACEOF
-
-else
- { echo "$as_me:$LINENO: checking for getpagesize in -lucb" >&5
-echo $ECHO_N "checking for getpagesize in -lucb... $ECHO_C" >&6; }
-if test "${ac_cv_lib_ucb_getpagesize+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lucb $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getpagesize ();
-int
-main ()
-{
-return getpagesize ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_ucb_getpagesize=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_ucb_getpagesize=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_ucb_getpagesize" >&5
-echo "${ECHO_T}$ac_cv_lib_ucb_getpagesize" >&6; }
-if test $ac_cv_lib_ucb_getpagesize = yes; then
- LIBS="$LIBS -lucb"; cat >>confdefs.h <<\_ACEOF
-#define HAVE_GETPAGESIZE 1
-_ACEOF
-
-fi
-
-
-fi
-
-
-# Check for broken snprintf
-if test "x$ac_cv_func_snprintf" = "xyes" ; then
- { echo "$as_me:$LINENO: checking whether snprintf correctly terminates long strings" >&5
-echo $ECHO_N "checking whether snprintf correctly terminates long strings... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: WARNING: cross compiling: Assuming working snprintf()" >&5
-echo "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;}
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <stdio.h>
-int
-main ()
-{
-
- char b[5];
- snprintf(b,5,"123456789");
- exit(b[4]!='\0');
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SNPRINTF 1
-_ACEOF
-
- { echo "$as_me:$LINENO: WARNING: ****** Your snprintf() function is broken, complain to your vendor" >&5
-echo "$as_me: WARNING: ****** Your snprintf() function is broken, complain to your vendor" >&2;}
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-
-# We depend on vsnprintf returning the right thing on overflow: the
-# number of characters it tried to create (as per SUSv3)
-if test "x$ac_cv_func_vsnprintf" = "xyes" ; then
- { echo "$as_me:$LINENO: checking whether vsnprintf returns correct values on overflow" >&5
-echo $ECHO_N "checking whether vsnprintf returns correct values on overflow... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: WARNING: cross compiling: Assuming working vsnprintf()" >&5
-echo "$as_me: WARNING: cross compiling: Assuming working vsnprintf()" >&2;}
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-int x_snprintf(char *str, size_t count, const char *fmt, ...)
-{
- size_t ret;
- va_list ap;
-
- va_start(ap, fmt);
- ret = vsnprintf(str, count, fmt, ap);
- va_end(ap);
- return ret;
-}
-
-int
-main ()
-{
-
-char x[1];
-if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11)
- return 1;
-if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11)
- return 1;
-return 0;
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SNPRINTF 1
-_ACEOF
-
- { echo "$as_me:$LINENO: WARNING: ****** Your vsnprintf() function is broken, complain to your vendor" >&5
-echo "$as_me: WARNING: ****** Your vsnprintf() function is broken, complain to your vendor" >&2;}
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-
-# On systems where [v]snprintf is broken, but is declared in stdio,
-# check that the fmt argument is const char * or just char *.
-# This is only useful for when BROKEN_SNPRINTF
-{ echo "$as_me:$LINENO: checking whether snprintf can declare const char *fmt" >&5
-echo $ECHO_N "checking whether snprintf can declare const char *fmt... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-int snprintf(char *a, size_t b, const char *c, ...) { return 0; }
-
-int
-main ()
-{
-
- snprintf(0, 0, 0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define SNPRINTF_CONST const
-_ACEOF
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- cat >>confdefs.h <<\_ACEOF
-#define SNPRINTF_CONST /* not const */
-_ACEOF
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-# Check for missing getpeereid (or equiv) support
-NO_PEERCHECK=""
-if test "x$ac_cv_func_getpeereid" != "xyes" -a "x$ac_cv_func_getpeerucred" != "xyes"; then
- { echo "$as_me:$LINENO: checking whether system supports SO_PEERCRED getsockopt" >&5
-echo $ECHO_N "checking whether system supports SO_PEERCRED getsockopt... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-int
-main ()
-{
-int i = SO_PEERCRED;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_SO_PEERCRED 1
-_ACEOF
-
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- NO_PEERCHECK=1
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-if test "x$ac_cv_func_mkdtemp" = "xyes" ; then
-{ echo "$as_me:$LINENO: checking for (overly) strict mkstemp" >&5
-echo $ECHO_N "checking for (overly) strict mkstemp... $ECHO_C" >&6; }
-if test "$cross_compiling" = yes; then
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_STRICT_MKSTEMP 1
-_ACEOF
-
-
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-
-int
-main ()
-{
-
- char template[]="conftest.mkstemp-test";
- if (mkstemp(template) == -1)
- exit(1);
- unlink(template);
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_STRICT_MKSTEMP 1
-_ACEOF
-
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-
-if test ! -z "$check_for_openpty_ctty_bug"; then
- { echo "$as_me:$LINENO: checking if openpty correctly handles controlling tty" >&5
-echo $ECHO_N "checking if openpty correctly handles controlling tty... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
-
- { echo "$as_me:$LINENO: result: cross-compiling, assuming yes" >&5
-echo "${ECHO_T}cross-compiling, assuming yes" >&6; }
-
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-#include <sys/fcntl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-int
-main ()
-{
-
- pid_t pid;
- int fd, ptyfd, ttyfd, status;
-
- pid = fork();
- if (pid < 0) { /* failed */
- exit(1);
- } else if (pid > 0) { /* parent */
- waitpid(pid, &status, 0);
- if (WIFEXITED(status))
- exit(WEXITSTATUS(status));
- else
- exit(2);
- } else { /* child */
- close(0); close(1); close(2);
- setsid();
- openpty(&ptyfd, &ttyfd, NULL, NULL, NULL);
- fd = open("/dev/tty", O_RDWR | O_NOCTTY);
- if (fd >= 0)
- exit(3); /* Acquired ctty: broken */
- else
- exit(0); /* Did not acquire ctty: OK */
- }
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- cat >>confdefs.h <<\_ACEOF
-#define SSHD_ACQUIRES_CTTY 1
-_ACEOF
-
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-
-if test "x$ac_cv_func_getaddrinfo" = "xyes" && \
- test "x$check_for_hpux_broken_getaddrinfo" = "x1"; then
- { echo "$as_me:$LINENO: checking if getaddrinfo seems to work" >&5
-echo $ECHO_N "checking if getaddrinfo seems to work... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
-
- { echo "$as_me:$LINENO: result: cross-compiling, assuming yes" >&5
-echo "${ECHO_T}cross-compiling, assuming yes" >&6; }
-
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <errno.h>
-#include <netinet/in.h>
-
-#define TEST_PORT "2222"
-
-int
-main ()
-{
-
- int err, sock;
- struct addrinfo *gai_ai, *ai, hints;
- char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_PASSIVE;
-
- err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai);
- if (err != 0) {
- fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err));
- exit(1);
- }
-
- for (ai = gai_ai; ai != NULL; ai = ai->ai_next) {
- if (ai->ai_family != AF_INET6)
- continue;
-
- err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop,
- sizeof(ntop), strport, sizeof(strport),
- NI_NUMERICHOST|NI_NUMERICSERV);
-
- if (err != 0) {
- if (err == EAI_SYSTEM)
- perror("getnameinfo EAI_SYSTEM");
- else
- fprintf(stderr, "getnameinfo failed: %s\n",
- gai_strerror(err));
- exit(2);
- }
-
- sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (sock < 0)
- perror("socket");
- if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
- if (errno == EBADF)
- exit(3);
- }
- }
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_GETADDRINFO 1
-_ACEOF
-
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-
-if test "x$ac_cv_func_getaddrinfo" = "xyes" && \
- test "x$check_for_aix_broken_getaddrinfo" = "x1"; then
- { echo "$as_me:$LINENO: checking if getaddrinfo seems to work" >&5
-echo $ECHO_N "checking if getaddrinfo seems to work... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
-
- { echo "$as_me:$LINENO: result: cross-compiling, assuming no" >&5
-echo "${ECHO_T}cross-compiling, assuming no" >&6; }
-
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <errno.h>
-#include <netinet/in.h>
-
-#define TEST_PORT "2222"
-
-int
-main ()
-{
-
- int err, sock;
- struct addrinfo *gai_ai, *ai, hints;
- char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_PASSIVE;
-
- err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai);
- if (err != 0) {
- fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err));
- exit(1);
- }
-
- for (ai = gai_ai; ai != NULL; ai = ai->ai_next) {
- if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
- continue;
-
- err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop,
- sizeof(ntop), strport, sizeof(strport),
- NI_NUMERICHOST|NI_NUMERICSERV);
-
- if (ai->ai_family == AF_INET && err != 0) {
- perror("getnameinfo");
- exit(2);
- }
- }
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define AIX_GETNAMEINFO_HACK 1
-_ACEOF
-
-
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_GETADDRINFO 1
-_ACEOF
-
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-
-if test "x$ac_cv_func_getaddrinfo" = "xyes"; then
- { echo "$as_me:$LINENO: checking whether AI_NUMERICSERV is declared" >&5
-echo $ECHO_N "checking whether AI_NUMERICSERV is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_AI_NUMERICSERV+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
- #include <sys/socket.h>
- #include <netdb.h>
-
-int
-main ()
-{
-#ifndef AI_NUMERICSERV
- (void) AI_NUMERICSERV;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_AI_NUMERICSERV=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_AI_NUMERICSERV=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_AI_NUMERICSERV" >&5
-echo "${ECHO_T}$ac_cv_have_decl_AI_NUMERICSERV" >&6; }
-if test $ac_cv_have_decl_AI_NUMERICSERV = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_AI_NUMERICSERV 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_AI_NUMERICSERV 0
-_ACEOF
-
-
-fi
-
-
-fi
-
-if test "x$check_for_conflicting_getspnam" = "x1"; then
- { echo "$as_me:$LINENO: checking for conflicting getspnam in shadow.h" >&5
-echo $ECHO_N "checking for conflicting getspnam in shadow.h... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <shadow.h>
-int
-main ()
-{
- exit(0);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define GETSPNAM_CONFLICTING_DEFS 1
-_ACEOF
-
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-{ echo "$as_me:$LINENO: checking whether getpgrp requires zero arguments" >&5
-echo $ECHO_N "checking whether getpgrp requires zero arguments... $ECHO_C" >&6; }
-if test "${ac_cv_func_getpgrp_void+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- # Use it with a single arg.
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-getpgrp (0);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_func_getpgrp_void=no
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_func_getpgrp_void=yes
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_getpgrp_void" >&5
-echo "${ECHO_T}$ac_cv_func_getpgrp_void" >&6; }
-if test $ac_cv_func_getpgrp_void = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define GETPGRP_VOID 1
-_ACEOF
-
-fi
-
-
-# Search for OpenSSL
-saved_CPPFLAGS="$CPPFLAGS"
-saved_LDFLAGS="$LDFLAGS"
-
-# Check whether --with-ssl-dir was given.
-if test "${with_ssl_dir+set}" = set; then
- withval=$with_ssl_dir;
- if test "x$openssl" = "xno" ; then
- { { echo "$as_me:$LINENO: error: cannot use --with-ssl-dir when OpenSSL disabled" >&5
-echo "$as_me: error: cannot use --with-ssl-dir when OpenSSL disabled" >&2;}
- { (exit 1); exit 1; }; }
- fi
- if test "x$withval" != "xno" ; then
- case "$withval" in
- # Relative paths
- ./*|../*) withval="`pwd`/$withval"
- esac
- if test -d "$withval/lib"; then
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
- else
- LDFLAGS="-L${withval}/lib ${LDFLAGS}"
- fi
- elif test -d "$withval/lib64"; then
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib64 -R${withval}/lib64 ${LDFLAGS}"
- else
- LDFLAGS="-L${withval}/lib64 ${LDFLAGS}"
- fi
- else
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
- else
- LDFLAGS="-L${withval} ${LDFLAGS}"
- fi
- fi
- if test -d "$withval/include"; then
- CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
- else
- CPPFLAGS="-I${withval} ${CPPFLAGS}"
- fi
- fi
-
-
-fi
-
-
-
-# Check whether --with-openssl-header-check was given.
-if test "${with_openssl_header_check+set}" = set; then
- withval=$with_openssl_header_check;
- if test "x$withval" = "xno" ; then
- openssl_check_nonfatal=1
- fi
-
-
-fi
-
-
-openssl_engine=no
-
-# Check whether --with-ssl-engine was given.
-if test "${with_ssl_engine+set}" = set; then
- withval=$with_ssl_engine;
- if test "x$openssl" = "xno" ; then
- { { echo "$as_me:$LINENO: error: cannot use --with-ssl-engine when OpenSSL disabled" >&5
-echo "$as_me: error: cannot use --with-ssl-engine when OpenSSL disabled" >&2;}
- { (exit 1); exit 1; }; }
- fi
- if test "x$withval" != "xno" ; then
- openssl_engine=yes
- fi
-
-
-fi
-
-
-if test "x$openssl" = "xyes" ; then
- LIBS="-lcrypto $LIBS"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RAND_add ();
-int
-main ()
-{
-return RAND_add ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_OPENSSL 1
-_ACEOF
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib ${saved_LDFLAGS}"
- else
- LDFLAGS="-L/usr/local/ssl/lib ${saved_LDFLAGS}"
- fi
- CPPFLAGS="-I/usr/local/ssl/include ${saved_CPPFLAGS}"
- if test "${ac_cv_header_openssl_opensslv_h+set}" = set; then
- { echo "$as_me:$LINENO: checking for openssl/opensslv.h" >&5
-echo $ECHO_N "checking for openssl/opensslv.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_openssl_opensslv_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_openssl_opensslv_h" >&5
-echo "${ECHO_T}$ac_cv_header_openssl_opensslv_h" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking openssl/opensslv.h usability" >&5
-echo $ECHO_N "checking openssl/opensslv.h usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <openssl/opensslv.h>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking openssl/opensslv.h presence" >&5
-echo $ECHO_N "checking openssl/opensslv.h presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <openssl/opensslv.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: openssl/opensslv.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: openssl/opensslv.h: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: present but cannot be compiled" >&5
-echo "$as_me: WARNING: openssl/opensslv.h: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: openssl/opensslv.h: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: openssl/opensslv.h: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: openssl/opensslv.h: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: openssl/opensslv.h: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: openssl/opensslv.h: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for openssl/opensslv.h" >&5
-echo $ECHO_N "checking for openssl/opensslv.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_openssl_opensslv_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_header_openssl_opensslv_h=$ac_header_preproc
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_openssl_opensslv_h" >&5
-echo "${ECHO_T}$ac_cv_header_openssl_opensslv_h" >&6; }
-
-fi
-if test $ac_cv_header_openssl_opensslv_h = yes; then
- :
-else
- { { echo "$as_me:$LINENO: error: *** OpenSSL headers missing - please install first or check config.log ***" >&5
-echo "$as_me: error: *** OpenSSL headers missing - please install first or check config.log ***" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RAND_add ();
-int
-main ()
-{
-return RAND_add ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_OPENSSL 1
-_ACEOF
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { { echo "$as_me:$LINENO: error: *** Can't find recent OpenSSL libcrypto (see config.log for details) ***" >&5
-echo "$as_me: error: *** Can't find recent OpenSSL libcrypto (see config.log for details) ***" >&2;}
- { (exit 1); exit 1; }; }
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
- # Determine OpenSSL header version
- { echo "$as_me:$LINENO: checking OpenSSL header version" >&5
-echo $ECHO_N "checking OpenSSL header version... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
-
- { echo "$as_me:$LINENO: WARNING: cross compiling: not checking" >&5
-echo "$as_me: WARNING: cross compiling: not checking" >&2;}
-
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <stdio.h>
- #include <string.h>
- #include <openssl/opensslv.h>
- #define DATA "conftest.sslincver"
-
-int
-main ()
-{
-
- FILE *fd;
- int rc;
-
- fd = fopen(DATA,"w");
- if(fd == NULL)
- exit(1);
-
- if ((rc = fprintf(fd ,"%08x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0)
- exit(1);
-
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
- ssl_header_ver=`cat conftest.sslincver`
- { echo "$as_me:$LINENO: result: $ssl_header_ver" >&5
-echo "${ECHO_T}$ssl_header_ver" >&6; }
-
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: not found" >&5
-echo "${ECHO_T}not found" >&6; }
- { { echo "$as_me:$LINENO: error: OpenSSL version header not found." >&5
-echo "$as_me: error: OpenSSL version header not found." >&2;}
- { (exit 1); exit 1; }; }
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
- # Determine OpenSSL library version
- { echo "$as_me:$LINENO: checking OpenSSL library version" >&5
-echo $ECHO_N "checking OpenSSL library version... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
-
- { echo "$as_me:$LINENO: WARNING: cross compiling: not checking" >&5
-echo "$as_me: WARNING: cross compiling: not checking" >&2;}
-
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <stdio.h>
- #include <string.h>
- #include <openssl/opensslv.h>
- #include <openssl/crypto.h>
- #define DATA "conftest.ssllibver"
-
-int
-main ()
-{
-
- FILE *fd;
- int rc;
-
- fd = fopen(DATA,"w");
- if(fd == NULL)
- exit(1);
-
- if ((rc = fprintf(fd ,"%08x (%s)\n", SSLeay(),
- SSLeay_version(SSLEAY_VERSION))) <0)
- exit(1);
-
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
- ssl_library_ver=`cat conftest.ssllibver`
- # Check version is supported.
- case "$ssl_library_ver" in
- 0090[0-7]*|009080[0-5]*)
- { { echo "$as_me:$LINENO: error: OpenSSL >= 0.9.8f required (have \"$ssl_library_ver\")" >&5
-echo "$as_me: error: OpenSSL >= 0.9.8f required (have \"$ssl_library_ver\")" >&2;}
- { (exit 1); exit 1; }; }
- ;;
- *) ;;
- esac
- { echo "$as_me:$LINENO: result: $ssl_library_ver" >&5
-echo "${ECHO_T}$ssl_library_ver" >&6; }
-
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: not found" >&5
-echo "${ECHO_T}not found" >&6; }
- { { echo "$as_me:$LINENO: error: OpenSSL library not found." >&5
-echo "$as_me: error: OpenSSL library not found." >&2;}
- { (exit 1); exit 1; }; }
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
- # Sanity check OpenSSL headers
- { echo "$as_me:$LINENO: checking whether OpenSSL's headers match the library" >&5
-echo $ECHO_N "checking whether OpenSSL's headers match the library... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
-
- { echo "$as_me:$LINENO: WARNING: cross compiling: not checking" >&5
-echo "$as_me: WARNING: cross compiling: not checking" >&2;}
-
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <string.h>
- #include <openssl/opensslv.h>
-
-int
-main ()
-{
-
- exit(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- if test "x$openssl_check_nonfatal" = "x"; then
- { { echo "$as_me:$LINENO: error: Your OpenSSL headers do not match your
- library. Check config.log for details.
- If you are sure your installation is consistent, you can disable the check
- by running \"./configure --without-openssl-header-check\".
- Also see contrib/findssl.sh for help identifying header/library mismatches.
- " >&5
-echo "$as_me: error: Your OpenSSL headers do not match your
- library. Check config.log for details.
- If you are sure your installation is consistent, you can disable the check
- by running \"./configure --without-openssl-header-check\".
- Also see contrib/findssl.sh for help identifying header/library mismatches.
- " >&2;}
- { (exit 1); exit 1; }; }
- else
- { echo "$as_me:$LINENO: WARNING: Your OpenSSL headers do not match your
- library. Check config.log for details.
- Also see contrib/findssl.sh for help identifying header/library mismatches." >&5
-echo "$as_me: WARNING: Your OpenSSL headers do not match your
- library. Check config.log for details.
- Also see contrib/findssl.sh for help identifying header/library mismatches." >&2;}
- fi
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
- { echo "$as_me:$LINENO: checking if programs using OpenSSL functions will link" >&5
-echo $ECHO_N "checking if programs using OpenSSL functions will link... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <openssl/evp.h>
-int
-main ()
-{
- SSLeay_add_all_algorithms();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- saved_LIBS="$LIBS"
- LIBS="$LIBS -ldl"
- { echo "$as_me:$LINENO: checking if programs using OpenSSL need -ldl" >&5
-echo $ECHO_N "checking if programs using OpenSSL need -ldl... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <openssl/evp.h>
-int
-main ()
-{
- SSLeay_add_all_algorithms();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- LIBS="$saved_LIBS"
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-
-
-
-
-
-
-
-
-
-
-for ac_func in \
- BN_is_prime_ex \
- DSA_generate_parameters_ex \
- EVP_DigestInit_ex \
- EVP_DigestFinal_ex \
- EVP_MD_CTX_init \
- EVP_MD_CTX_cleanup \
- EVP_MD_CTX_copy_ex \
- HMAC_CTX_init \
- RSA_generate_key_ex \
- RSA_get_default_method \
-
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
- if test "x$openssl_engine" = "xyes" ; then
- { echo "$as_me:$LINENO: checking for OpenSSL ENGINE support" >&5
-echo $ECHO_N "checking for OpenSSL ENGINE support... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <openssl/engine.h>
-
-int
-main ()
-{
-
- ENGINE_load_builtin_engines();
- ENGINE_register_all_complete();
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_OPENSSL_ENGINE 1
-_ACEOF
-
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { { echo "$as_me:$LINENO: error: OpenSSL ENGINE support not found" >&5
-echo "$as_me: error: OpenSSL ENGINE support not found" >&2;}
- { (exit 1); exit 1; }; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- fi
-
- # Check for OpenSSL without EVP_aes_{192,256}_cbc
- { echo "$as_me:$LINENO: checking whether OpenSSL has crippled AES support" >&5
-echo $ECHO_N "checking whether OpenSSL has crippled AES support... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <string.h>
- #include <openssl/evp.h>
-
-int
-main ()
-{
-
- exit(EVP_aes_192_cbc() == NULL || EVP_aes_256_cbc() == NULL);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define OPENSSL_LOBOTOMISED_AES 1
-_ACEOF
-
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
- # Check for OpenSSL with EVP_aes_*ctr
- { echo "$as_me:$LINENO: checking whether OpenSSL has AES CTR via EVP" >&5
-echo $ECHO_N "checking whether OpenSSL has AES CTR via EVP... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <string.h>
- #include <openssl/evp.h>
-
-int
-main ()
-{
-
- exit(EVP_aes_128_ctr() == NULL ||
- EVP_aes_192_cbc() == NULL ||
- EVP_aes_256_cbc() == NULL);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define OPENSSL_HAVE_EVPCTR 1
-_ACEOF
-
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
- # Check for OpenSSL with EVP_aes_*gcm
- { echo "$as_me:$LINENO: checking whether OpenSSL has AES GCM via EVP" >&5
-echo $ECHO_N "checking whether OpenSSL has AES GCM via EVP... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <string.h>
- #include <openssl/evp.h>
-
-int
-main ()
-{
-
- exit(EVP_aes_128_gcm() == NULL ||
- EVP_aes_256_gcm() == NULL ||
- EVP_CTRL_GCM_SET_IV_FIXED == 0 ||
- EVP_CTRL_GCM_IV_GEN == 0 ||
- EVP_CTRL_GCM_SET_TAG == 0 ||
- EVP_CTRL_GCM_GET_TAG == 0 ||
- EVP_CIPHER_CTX_ctrl(NULL, 0, 0, NULL) == 0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define OPENSSL_HAVE_EVPGCM 1
-_ACEOF
-
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- unsupported_algorithms="$unsupported_cipers \
- aes128-gcm@openssh.com aes256-gcm@openssh.com"
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
- { echo "$as_me:$LINENO: checking for library containing EVP_CIPHER_CTX_ctrl" >&5
-echo $ECHO_N "checking for library containing EVP_CIPHER_CTX_ctrl... $ECHO_C" >&6; }
-if test "${ac_cv_search_EVP_CIPHER_CTX_ctrl+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char EVP_CIPHER_CTX_ctrl ();
-int
-main ()
-{
-return EVP_CIPHER_CTX_ctrl ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_EVP_CIPHER_CTX_ctrl=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_EVP_CIPHER_CTX_ctrl+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_EVP_CIPHER_CTX_ctrl+set}" = set; then
- :
-else
- ac_cv_search_EVP_CIPHER_CTX_ctrl=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_EVP_CIPHER_CTX_ctrl" >&5
-echo "${ECHO_T}$ac_cv_search_EVP_CIPHER_CTX_ctrl" >&6; }
-ac_res=$ac_cv_search_EVP_CIPHER_CTX_ctrl
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_EVP_CIPHER_CTX_CTRL 1
-_ACEOF
-
-fi
-
-
- { echo "$as_me:$LINENO: checking if EVP_DigestUpdate returns an int" >&5
-echo $ECHO_N "checking if EVP_DigestUpdate returns an int... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <string.h>
- #include <openssl/evp.h>
-
-int
-main ()
-{
-
- if(EVP_DigestUpdate(NULL, NULL,0))
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define OPENSSL_EVP_DIGESTUPDATE_VOID 1
-_ACEOF
-
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
- # Some systems want crypt() from libcrypt, *not* the version in OpenSSL,
- # because the system crypt() is more featureful.
- if test "x$check_for_libcrypt_before" = "x1"; then
-
-{ echo "$as_me:$LINENO: checking for crypt in -lcrypt" >&5
-echo $ECHO_N "checking for crypt in -lcrypt... $ECHO_C" >&6; }
-if test "${ac_cv_lib_crypt_crypt+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcrypt $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char crypt ();
-int
-main ()
-{
-return crypt ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_crypt_crypt=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_crypt_crypt=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_crypt" >&5
-echo "${ECHO_T}$ac_cv_lib_crypt_crypt" >&6; }
-if test $ac_cv_lib_crypt_crypt = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBCRYPT 1
-_ACEOF
-
- LIBS="-lcrypt $LIBS"
-
-fi
-
- fi
-
- # Some Linux systems (Slackware) need crypt() from libcrypt, *not* the
- # version in OpenSSL.
- if test "x$check_for_libcrypt_later" = "x1"; then
- { echo "$as_me:$LINENO: checking for crypt in -lcrypt" >&5
-echo $ECHO_N "checking for crypt in -lcrypt... $ECHO_C" >&6; }
-if test "${ac_cv_lib_crypt_crypt+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcrypt $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char crypt ();
-int
-main ()
-{
-return crypt ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_crypt_crypt=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_crypt_crypt=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_crypt" >&5
-echo "${ECHO_T}$ac_cv_lib_crypt_crypt" >&6; }
-if test $ac_cv_lib_crypt_crypt = yes; then
- LIBS="$LIBS -lcrypt"
-fi
-
- fi
-
-
-for ac_func in crypt DES_crypt
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
- # Search for SHA256 support in libc and/or OpenSSL
-
-
-for ac_func in SHA256_Update EVP_sha256
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-else
- unsupported_algorithms="$unsupported_algorithms \
- hmac-sha2-256 hmac-sha2-512 \
- diffie-hellman-group-exchange-sha256 \
- hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com"
-
-
-fi
-done
-
- # Search for RIPE-MD support in OpenSSL
-
-for ac_func in EVP_ripemd160
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-else
- unsupported_algorithms="$unsupported_algorithms \
- hmac-ripemd160
- hmac-ripemd160@openssh.com
- hmac-ripemd160-etm@openssh.com"
-
-
-fi
-done
-
-
- # Check complete ECC support in OpenSSL
- { echo "$as_me:$LINENO: checking whether OpenSSL has NID_X9_62_prime256v1" >&5
-echo $ECHO_N "checking whether OpenSSL has NID_X9_62_prime256v1... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <openssl/ec.h>
- #include <openssl/ecdh.h>
- #include <openssl/ecdsa.h>
- #include <openssl/evp.h>
- #include <openssl/objects.h>
- #include <openssl/opensslv.h>
- #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */
- # error "OpenSSL < 0.9.8g has unreliable ECC code"
- #endif
-
-int
-main ()
-{
-
- EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
- const EVP_MD *m = EVP_sha256(); /* We need this too */
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- enable_nistp256=1
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
- { echo "$as_me:$LINENO: checking whether OpenSSL has NID_secp384r1" >&5
-echo $ECHO_N "checking whether OpenSSL has NID_secp384r1... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <openssl/ec.h>
- #include <openssl/ecdh.h>
- #include <openssl/ecdsa.h>
- #include <openssl/evp.h>
- #include <openssl/objects.h>
- #include <openssl/opensslv.h>
- #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */
- # error "OpenSSL < 0.9.8g has unreliable ECC code"
- #endif
-
-int
-main ()
-{
-
- EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1);
- const EVP_MD *m = EVP_sha384(); /* We need this too */
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- enable_nistp384=1
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
- { echo "$as_me:$LINENO: checking whether OpenSSL has NID_secp521r1" >&5
-echo $ECHO_N "checking whether OpenSSL has NID_secp521r1... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <openssl/ec.h>
- #include <openssl/ecdh.h>
- #include <openssl/ecdsa.h>
- #include <openssl/evp.h>
- #include <openssl/objects.h>
- #include <openssl/opensslv.h>
- #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */
- # error "OpenSSL < 0.9.8g has unreliable ECC code"
- #endif
-
-int
-main ()
-{
-
- EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1);
- const EVP_MD *m = EVP_sha512(); /* We need this too */
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- { echo "$as_me:$LINENO: checking if OpenSSL's NID_secp521r1 is functional" >&5
-echo $ECHO_N "checking if OpenSSL's NID_secp521r1 is functional... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: WARNING: cross-compiling: assuming yes" >&5
-echo "$as_me: WARNING: cross-compiling: assuming yes" >&2;}
- enable_nistp521=1
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <openssl/ec.h>
- #include <openssl/ecdh.h>
- #include <openssl/ecdsa.h>
- #include <openssl/evp.h>
- #include <openssl/objects.h>
- #include <openssl/opensslv.h>
-
-int
-main ()
-{
-
- EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1);
- const EVP_MD *m = EVP_sha512(); /* We need this too */
- exit(e == NULL || m == NULL);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- enable_nistp521=1
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
- COMMENT_OUT_ECC="#no ecc#"
- TEST_SSH_ECC=no
-
- if test x$enable_nistp256 = x1 || test x$enable_nistp384 = x1 || \
- test x$enable_nistp521 = x1; then
-
-cat >>confdefs.h <<\_ACEOF
-#define OPENSSL_HAS_ECC 1
-_ACEOF
-
- fi
- if test x$enable_nistp256 = x1; then
-
-cat >>confdefs.h <<\_ACEOF
-#define OPENSSL_HAS_NISTP256 1
-_ACEOF
-
- TEST_SSH_ECC=yes
- COMMENT_OUT_ECC=""
- else
- unsupported_algorithms="$unsupported_algorithms ecdsa-sha2-nistp256 \
- ecdh-sha2-nistp256 ecdsa-sha2-nistp256-cert-v01@openssh.com"
- fi
- if test x$enable_nistp384 = x1; then
-
-cat >>confdefs.h <<\_ACEOF
-#define OPENSSL_HAS_NISTP384 1
-_ACEOF
-
- TEST_SSH_ECC=yes
- COMMENT_OUT_ECC=""
- else
- unsupported_algorithms="$unsupported_algorithms ecdsa-sha2-nistp384 \
- ecdh-sha2-nistp384 ecdsa-sha2-nistp384-cert-v01@openssh.com"
- fi
- if test x$enable_nistp521 = x1; then
-
-cat >>confdefs.h <<\_ACEOF
-#define OPENSSL_HAS_NISTP521 1
-_ACEOF
-
- TEST_SSH_ECC=yes
- COMMENT_OUT_ECC=""
- else
- unsupported_algorithms="$unsupported_algorithms ecdh-sha2-nistp521 \
- ecdsa-sha2-nistp521 ecdsa-sha2-nistp521-cert-v01@openssh.com"
- fi
-
-
-
-else
- { echo "$as_me:$LINENO: checking for crypt in -lcrypt" >&5
-echo $ECHO_N "checking for crypt in -lcrypt... $ECHO_C" >&6; }
-if test "${ac_cv_lib_crypt_crypt+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcrypt $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char crypt ();
-int
-main ()
-{
-return crypt ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_crypt_crypt=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_crypt_crypt=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_crypt" >&5
-echo "${ECHO_T}$ac_cv_lib_crypt_crypt" >&6; }
-if test $ac_cv_lib_crypt_crypt = yes; then
- LIBS="$LIBS -lcrypt"
-fi
-
-
-for ac_func in crypt
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-fi
-
-
-
-
-
-for ac_func in \
- arc4random \
- arc4random_buf \
- arc4random_stir \
- arc4random_uniform \
-
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-saved_LIBS="$LIBS"
-{ echo "$as_me:$LINENO: checking for ia_openinfo in -liaf" >&5
-echo $ECHO_N "checking for ia_openinfo in -liaf... $ECHO_C" >&6; }
-if test "${ac_cv_lib_iaf_ia_openinfo+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-liaf $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char ia_openinfo ();
-int
-main ()
-{
-return ia_openinfo ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_iaf_ia_openinfo=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_iaf_ia_openinfo=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_iaf_ia_openinfo" >&5
-echo "${ECHO_T}$ac_cv_lib_iaf_ia_openinfo" >&6; }
-if test $ac_cv_lib_iaf_ia_openinfo = yes; then
-
- LIBS="$LIBS -liaf"
-
-for ac_func in set_id
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
- SSHDLIBS="$SSHDLIBS -liaf"
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_LIBIAF 1
-_ACEOF
-
-
-fi
-done
-
-
-fi
-
-LIBS="$saved_LIBS"
-
-### Configure cryptographic random number support
-
-# Check wheter OpenSSL seeds itself
-if test "x$openssl" = "xyes" ; then
- { echo "$as_me:$LINENO: checking whether OpenSSL's PRNG is internally seeded" >&5
-echo $ECHO_N "checking whether OpenSSL's PRNG is internally seeded... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
-
- { echo "$as_me:$LINENO: WARNING: cross compiling: assuming yes" >&5
-echo "$as_me: WARNING: cross compiling: assuming yes" >&2;}
- # This is safe, since we will fatal() at runtime if
- # OpenSSL is not seeded correctly.
- OPENSSL_SEEDS_ITSELF=yes
-
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <string.h>
- #include <openssl/rand.h>
-
-int
-main ()
-{
-
- exit(RAND_status() == 1 ? 0 : 1);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
- OPENSSL_SEEDS_ITSELF=yes
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-
-# PRNGD TCP socket
-
-# Check whether --with-prngd-port was given.
-if test "${with_prngd_port+set}" = set; then
- withval=$with_prngd_port;
- case "$withval" in
- no)
- withval=""
- ;;
- [0-9]*)
- ;;
- *)
- { { echo "$as_me:$LINENO: error: You must specify a numeric port number for --with-prngd-port" >&5
-echo "$as_me: error: You must specify a numeric port number for --with-prngd-port" >&2;}
- { (exit 1); exit 1; }; }
- ;;
- esac
- if test ! -z "$withval" ; then
- PRNGD_PORT="$withval"
-
-cat >>confdefs.h <<_ACEOF
-#define PRNGD_PORT $PRNGD_PORT
-_ACEOF
-
- fi
-
-
-fi
-
-
-# PRNGD Unix domain socket
-
-# Check whether --with-prngd-socket was given.
-if test "${with_prngd_socket+set}" = set; then
- withval=$with_prngd_socket;
- case "$withval" in
- yes)
- withval="/var/run/egd-pool"
- ;;
- no)
- withval=""
- ;;
- /*)
- ;;
- *)
- { { echo "$as_me:$LINENO: error: You must specify an absolute path to the entropy socket" >&5
-echo "$as_me: error: You must specify an absolute path to the entropy socket" >&2;}
- { (exit 1); exit 1; }; }
- ;;
- esac
-
- if test ! -z "$withval" ; then
- if test ! -z "$PRNGD_PORT" ; then
- { { echo "$as_me:$LINENO: error: You may not specify both a PRNGD/EGD port and socket" >&5
-echo "$as_me: error: You may not specify both a PRNGD/EGD port and socket" >&2;}
- { (exit 1); exit 1; }; }
- fi
- if test ! -r "$withval" ; then
- { echo "$as_me:$LINENO: WARNING: Entropy socket is not readable" >&5
-echo "$as_me: WARNING: Entropy socket is not readable" >&2;}
- fi
- PRNGD_SOCKET="$withval"
-
-cat >>confdefs.h <<_ACEOF
-#define PRNGD_SOCKET "$PRNGD_SOCKET"
-_ACEOF
-
- fi
-
-else
-
- # Check for existing socket only if we don't have a random device already
- if test "x$OPENSSL_SEEDS_ITSELF" != "xyes" ; then
- { echo "$as_me:$LINENO: checking for PRNGD/EGD socket" >&5
-echo $ECHO_N "checking for PRNGD/EGD socket... $ECHO_C" >&6; }
- # Insert other locations here
- for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do
- if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then
- PRNGD_SOCKET="$sock"
- cat >>confdefs.h <<_ACEOF
-#define PRNGD_SOCKET "$PRNGD_SOCKET"
-_ACEOF
-
- break;
- fi
- done
- if test ! -z "$PRNGD_SOCKET" ; then
- { echo "$as_me:$LINENO: result: $PRNGD_SOCKET" >&5
-echo "${ECHO_T}$PRNGD_SOCKET" >&6; }
- else
- { echo "$as_me:$LINENO: result: not found" >&5
-echo "${ECHO_T}not found" >&6; }
- fi
- fi
-
-
-fi
-
-
-# Which randomness source do we use?
-if test ! -z "$PRNGD_PORT" ; then
- RAND_MSG="PRNGd port $PRNGD_PORT"
-elif test ! -z "$PRNGD_SOCKET" ; then
- RAND_MSG="PRNGd socket $PRNGD_SOCKET"
-elif test ! -z "$OPENSSL_SEEDS_ITSELF" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define OPENSSL_PRNG_ONLY 1
-_ACEOF
-
- RAND_MSG="OpenSSL internal ONLY"
-elif test "x$openssl" = "xno" ; then
- { echo "$as_me:$LINENO: WARNING: OpenSSH will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible" >&5
-echo "$as_me: WARNING: OpenSSH will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible" >&2;}
-else
- { { echo "$as_me:$LINENO: error: OpenSSH has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options" >&5
-echo "$as_me: error: OpenSSH has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-# Check for PAM libs
-PAM_MSG="no"
-
-# Check whether --with-pam was given.
-if test "${with_pam+set}" = set; then
- withval=$with_pam;
- if test "x$withval" != "xno" ; then
- if test "x$ac_cv_header_security_pam_appl_h" != "xyes" && \
- test "x$ac_cv_header_pam_pam_appl_h" != "xyes" ; then
- { { echo "$as_me:$LINENO: error: PAM headers not found" >&5
-echo "$as_me: error: PAM headers not found" >&2;}
- { (exit 1); exit 1; }; }
- fi
-
- saved_LIBS="$LIBS"
-
-{ echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
-echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
-if test "${ac_cv_lib_dl_dlopen+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldl $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen ();
-int
-main ()
-{
-return dlopen ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_dl_dlopen=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_dl_dlopen=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
-echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
-if test $ac_cv_lib_dl_dlopen = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBDL 1
-_ACEOF
-
- LIBS="-ldl $LIBS"
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking for pam_set_item in -lpam" >&5
-echo $ECHO_N "checking for pam_set_item in -lpam... $ECHO_C" >&6; }
-if test "${ac_cv_lib_pam_pam_set_item+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpam $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char pam_set_item ();
-int
-main ()
-{
-return pam_set_item ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_pam_pam_set_item=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_pam_pam_set_item=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_pam_pam_set_item" >&5
-echo "${ECHO_T}$ac_cv_lib_pam_pam_set_item" >&6; }
-if test $ac_cv_lib_pam_pam_set_item = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBPAM 1
-_ACEOF
-
- LIBS="-lpam $LIBS"
-
-else
- { { echo "$as_me:$LINENO: error: *** libpam missing" >&5
-echo "$as_me: error: *** libpam missing" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-
-for ac_func in pam_getenvlist
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-for ac_func in pam_putenv
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
- LIBS="$saved_LIBS"
-
- PAM_MSG="yes"
-
- SSHDLIBS="$SSHDLIBS -lpam"
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_PAM 1
-_ACEOF
-
-
- if test $ac_cv_lib_dl_dlopen = yes; then
- case "$LIBS" in
- *-ldl*)
- # libdl already in LIBS
- ;;
- *)
- SSHDLIBS="$SSHDLIBS -ldl"
- ;;
- esac
- fi
- fi
-
-
-fi
-
-
-# Check for older PAM
-if test "x$PAM_MSG" = "xyes" ; then
- # Check PAM strerror arguments (old PAM)
- { echo "$as_me:$LINENO: checking whether pam_strerror takes only one argument" >&5
-echo $ECHO_N "checking whether pam_strerror takes only one argument... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdlib.h>
-#if defined(HAVE_SECURITY_PAM_APPL_H)
-#include <security/pam_appl.h>
-#elif defined (HAVE_PAM_PAM_APPL_H)
-#include <pam/pam_appl.h>
-#endif
-
-int
-main ()
-{
-
-(void)pam_strerror((pam_handle_t *)NULL, -1);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_OLD_PAM 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- PAM_MSG="yes (old library)"
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-case "$host" in
-*-*-cygwin*)
- SSH_PRIVSEP_USER=CYGWIN_SSH_PRIVSEP_USER
- ;;
-*)
- SSH_PRIVSEP_USER=sshd
- ;;
-esac
-
-# Check whether --with-privsep-user was given.
-if test "${with_privsep_user+set}" = set; then
- withval=$with_privsep_user;
- if test -n "$withval" && test "x$withval" != "xno" && \
- test "x${withval}" != "xyes"; then
- SSH_PRIVSEP_USER=$withval
- fi
-
-
-fi
-
-if test "x$SSH_PRIVSEP_USER" = "xCYGWIN_SSH_PRIVSEP_USER" ; then
-
-cat >>confdefs.h <<_ACEOF
-#define SSH_PRIVSEP_USER CYGWIN_SSH_PRIVSEP_USER
-_ACEOF
-
-else
-
-cat >>confdefs.h <<_ACEOF
-#define SSH_PRIVSEP_USER "$SSH_PRIVSEP_USER"
-_ACEOF
-
-fi
-
-
-if test "x$have_linux_no_new_privs" = "x1" ; then
-{ echo "$as_me:$LINENO: checking whether SECCOMP_MODE_FILTER is declared" >&5
-echo $ECHO_N "checking whether SECCOMP_MODE_FILTER is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_SECCOMP_MODE_FILTER+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <sys/types.h>
- #include <linux/seccomp.h>
-
-
-int
-main ()
-{
-#ifndef SECCOMP_MODE_FILTER
- (void) SECCOMP_MODE_FILTER;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_SECCOMP_MODE_FILTER=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_SECCOMP_MODE_FILTER=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_SECCOMP_MODE_FILTER" >&5
-echo "${ECHO_T}$ac_cv_have_decl_SECCOMP_MODE_FILTER" >&6; }
-if test $ac_cv_have_decl_SECCOMP_MODE_FILTER = yes; then
- have_seccomp_filter=1
-fi
-
-fi
-if test "x$have_seccomp_filter" = "x1" ; then
-{ echo "$as_me:$LINENO: checking kernel for seccomp_filter support" >&5
-echo $ECHO_N "checking kernel for seccomp_filter support... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <errno.h>
- #include <elf.h>
- #include <linux/audit.h>
- #include <linux/seccomp.h>
- #include <stdlib.h>
- #include <sys/prctl.h>
-
-int
-main ()
-{
- int i = $seccomp_audit_arch;
- errno = 0;
- prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, 0, 0);
- exit(errno == EFAULT ? 0 : 1);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- # Disable seccomp filter as a target
- have_seccomp_filter=0
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-
-# Decide which sandbox style to use
-sandbox_arg=""
-
-# Check whether --with-sandbox was given.
-if test "${with_sandbox+set}" = set; then
- withval=$with_sandbox;
- if test "x$withval" = "xyes" ; then
- sandbox_arg=""
- else
- sandbox_arg="$withval"
- fi
-
-
-fi
-
-
-# Some platforms (seems to be the ones that have a kernel poll(2)-type
-# function with which they implement select(2)) use an extra file descriptor
-# when calling select(2), which means we can't use the rlimit sandbox.
-{ echo "$as_me:$LINENO: checking if select works with descriptor rlimit" >&5
-echo $ECHO_N "checking if select works with descriptor rlimit... $ECHO_C" >&6; }
-if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: WARNING: cross compiling: assuming yes" >&5
-echo "$as_me: WARNING: cross compiling: assuming yes" >&2;}
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-#include <sys/resource.h>
-#ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-
-int
-main ()
-{
-
- struct rlimit rl_zero;
- int fd, r;
- fd_set fds;
- struct timeval tv;
-
- fd = open("/dev/null", O_RDONLY);
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- rl_zero.rlim_cur = rl_zero.rlim_max = 0;
- setrlimit(RLIMIT_FSIZE, &rl_zero);
- setrlimit(RLIMIT_NOFILE, &rl_zero);
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- r = select(fd+1, &fds, NULL, NULL, &tv);
- exit (r == -1 ? 1 : 0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- select_works_with_rlimit=yes
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-{ echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- select_works_with_rlimit=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking if setrlimit(RLIMIT_NOFILE,{0,0}) works" >&5
-echo $ECHO_N "checking if setrlimit(RLIMIT_NOFILE,{0,0}) works... $ECHO_C" >&6; }
-if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: WARNING: cross compiling: assuming yes" >&5
-echo "$as_me: WARNING: cross compiling: assuming yes" >&2;}
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-#include <sys/resource.h>
-#include <errno.h>
-#include <stdlib.h>
-
-int
-main ()
-{
-
- struct rlimit rl_zero;
- int fd, r;
- fd_set fds;
-
- rl_zero.rlim_cur = rl_zero.rlim_max = 0;
- r = setrlimit(RLIMIT_NOFILE, &rl_zero);
- exit (r == -1 ? 1 : 0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- rlimit_nofile_zero_works=yes
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-{ echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- rlimit_nofile_zero_works=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking if setrlimit RLIMIT_FSIZE works" >&5
-echo $ECHO_N "checking if setrlimit RLIMIT_FSIZE works... $ECHO_C" >&6; }
-if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: WARNING: cross compiling: assuming yes" >&5
-echo "$as_me: WARNING: cross compiling: assuming yes" >&2;}
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/resource.h>
-#include <stdlib.h>
-
-int
-main ()
-{
-
- struct rlimit rl_zero;
-
- rl_zero.rlim_cur = rl_zero.rlim_max = 0;
- exit(setrlimit(RLIMIT_FSIZE, &rl_zero) != 0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-{ echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define SANDBOX_SKIP_RLIMIT_FSIZE 1
-_ACEOF
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
-if test "x$sandbox_arg" = "xsystrace" || \
- ( test -z "$sandbox_arg" && test "x$have_systr_policy_kill" = "x1" ) ; then
- test "x$have_systr_policy_kill" != "x1" && \
- { { echo "$as_me:$LINENO: error: systrace sandbox requires systrace headers and SYSTR_POLICY_KILL support" >&5
-echo "$as_me: error: systrace sandbox requires systrace headers and SYSTR_POLICY_KILL support" >&2;}
- { (exit 1); exit 1; }; }
- SANDBOX_STYLE="systrace"
-
-cat >>confdefs.h <<\_ACEOF
-#define SANDBOX_SYSTRACE 1
-_ACEOF
-
-elif test "x$sandbox_arg" = "xdarwin" || \
- ( test -z "$sandbox_arg" && test "x$ac_cv_func_sandbox_init" = "xyes" && \
- test "x$ac_cv_header_sandbox_h" = "xyes") ; then
- test "x$ac_cv_func_sandbox_init" != "xyes" -o \
- "x$ac_cv_header_sandbox_h" != "xyes" && \
- { { echo "$as_me:$LINENO: error: Darwin seatbelt sandbox requires sandbox.h and sandbox_init function" >&5
-echo "$as_me: error: Darwin seatbelt sandbox requires sandbox.h and sandbox_init function" >&2;}
- { (exit 1); exit 1; }; }
- SANDBOX_STYLE="darwin"
-
-cat >>confdefs.h <<\_ACEOF
-#define SANDBOX_DARWIN 1
-_ACEOF
-
-elif test "x$sandbox_arg" = "xseccomp_filter" || \
- ( test -z "$sandbox_arg" && \
- test "x$have_seccomp_filter" = "x1" && \
- test "x$ac_cv_header_elf_h" = "xyes" && \
- test "x$ac_cv_header_linux_audit_h" = "xyes" && \
- test "x$ac_cv_header_linux_filter_h" = "xyes" && \
- test "x$seccomp_audit_arch" != "x" && \
- test "x$have_linux_no_new_privs" = "x1" && \
- test "x$ac_cv_func_prctl" = "xyes" ) ; then
- test "x$seccomp_audit_arch" = "x" && \
- { { echo "$as_me:$LINENO: error: seccomp_filter sandbox not supported on $host" >&5
-echo "$as_me: error: seccomp_filter sandbox not supported on $host" >&2;}
- { (exit 1); exit 1; }; }
- test "x$have_linux_no_new_privs" != "x1" && \
- { { echo "$as_me:$LINENO: error: seccomp_filter sandbox requires PR_SET_NO_NEW_PRIVS" >&5
-echo "$as_me: error: seccomp_filter sandbox requires PR_SET_NO_NEW_PRIVS" >&2;}
- { (exit 1); exit 1; }; }
- test "x$have_seccomp_filter" != "x1" && \
- { { echo "$as_me:$LINENO: error: seccomp_filter sandbox requires seccomp headers" >&5
-echo "$as_me: error: seccomp_filter sandbox requires seccomp headers" >&2;}
- { (exit 1); exit 1; }; }
- test "x$ac_cv_func_prctl" != "xyes" && \
- { { echo "$as_me:$LINENO: error: seccomp_filter sandbox requires prctl function" >&5
-echo "$as_me: error: seccomp_filter sandbox requires prctl function" >&2;}
- { (exit 1); exit 1; }; }
- SANDBOX_STYLE="seccomp_filter"
-
-cat >>confdefs.h <<\_ACEOF
-#define SANDBOX_SECCOMP_FILTER 1
-_ACEOF
-
-elif test "x$sandbox_arg" = "xcapsicum" || \
- ( test -z "$sandbox_arg" && \
- test "x$ac_cv_header_sys_capability_h" = "xyes" && \
- test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then
- test "x$ac_cv_header_sys_capability_h" != "xyes" && \
- { { echo "$as_me:$LINENO: error: capsicum sandbox requires sys/capability.h header" >&5
-echo "$as_me: error: capsicum sandbox requires sys/capability.h header" >&2;}
- { (exit 1); exit 1; }; }
- test "x$ac_cv_func_cap_rights_limit" != "xyes" && \
- { { echo "$as_me:$LINENO: error: capsicum sandbox requires cap_rights_limit function" >&5
-echo "$as_me: error: capsicum sandbox requires cap_rights_limit function" >&2;}
- { (exit 1); exit 1; }; }
- SANDBOX_STYLE="capsicum"
-
-cat >>confdefs.h <<\_ACEOF
-#define SANDBOX_CAPSICUM 1
-_ACEOF
-
-elif test "x$sandbox_arg" = "xrlimit" || \
- ( test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" && \
- test "x$select_works_with_rlimit" = "xyes" && \
- test "x$rlimit_nofile_zero_works" = "xyes" ) ; then
- test "x$ac_cv_func_setrlimit" != "xyes" && \
- { { echo "$as_me:$LINENO: error: rlimit sandbox requires setrlimit function" >&5
-echo "$as_me: error: rlimit sandbox requires setrlimit function" >&2;}
- { (exit 1); exit 1; }; }
- test "x$select_works_with_rlimit" != "xyes" && \
- { { echo "$as_me:$LINENO: error: rlimit sandbox requires select to work with rlimit" >&5
-echo "$as_me: error: rlimit sandbox requires select to work with rlimit" >&2;}
- { (exit 1); exit 1; }; }
- SANDBOX_STYLE="rlimit"
-
-cat >>confdefs.h <<\_ACEOF
-#define SANDBOX_RLIMIT 1
-_ACEOF
-
-elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \
- test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then
- SANDBOX_STYLE="none"
-
-cat >>confdefs.h <<\_ACEOF
-#define SANDBOX_NULL 1
-_ACEOF
-
-else
- { { echo "$as_me:$LINENO: error: unsupported --with-sandbox" >&5
-echo "$as_me: error: unsupported --with-sandbox" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-# Cheap hack to ensure NEWS-OS libraries are arranged right.
-if test ! -z "$SONY" ; then
- LIBS="$LIBS -liberty";
-fi
-
-# Check for long long datatypes
-{ echo "$as_me:$LINENO: checking for long long" >&5
-echo $ECHO_N "checking for long long... $ECHO_C" >&6; }
-if test "${ac_cv_type_long_long+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-typedef long long ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_long_long=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_long_long=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_long_long" >&5
-echo "${ECHO_T}$ac_cv_type_long_long" >&6; }
-if test $ac_cv_type_long_long = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_LONG_LONG 1
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking for unsigned long long" >&5
-echo $ECHO_N "checking for unsigned long long... $ECHO_C" >&6; }
-if test "${ac_cv_type_unsigned_long_long+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-typedef unsigned long long ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_unsigned_long_long=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_unsigned_long_long=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_unsigned_long_long" >&5
-echo "${ECHO_T}$ac_cv_type_unsigned_long_long" >&6; }
-if test $ac_cv_type_unsigned_long_long = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UNSIGNED_LONG_LONG 1
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking for long double" >&5
-echo $ECHO_N "checking for long double... $ECHO_C" >&6; }
-if test "${ac_cv_type_long_double+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-typedef long double ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_long_double=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_long_double=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_long_double" >&5
-echo "${ECHO_T}$ac_cv_type_long_double" >&6; }
-if test $ac_cv_type_long_double = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_LONG_DOUBLE 1
-_ACEOF
-
-
-fi
-
-
-# Check datatype sizes
-{ echo "$as_me:$LINENO: checking for short int" >&5
-echo $ECHO_N "checking for short int... $ECHO_C" >&6; }
-if test "${ac_cv_type_short_int+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-typedef short int ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_short_int=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_short_int=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_short_int" >&5
-echo "${ECHO_T}$ac_cv_type_short_int" >&6; }
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ echo "$as_me:$LINENO: checking size of short int" >&5
-echo $ECHO_N "checking size of short int... $ECHO_C" >&6; }
-if test "${ac_cv_sizeof_short_int+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test "$cross_compiling" = yes; then
- # Depending upon the size, compute the lo and hi bounds.
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef short int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_lo=0 ac_mid=0
- while :; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef short int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_hi=$ac_mid; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_lo=`expr $ac_mid + 1`
- if test $ac_lo -le $ac_mid; then
- ac_lo= ac_hi=
- break
- fi
- ac_mid=`expr 2 '*' $ac_mid + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef short int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_hi=-1 ac_mid=-1
- while :; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef short int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_lo=$ac_mid; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_hi=`expr '(' $ac_mid ')' - 1`
- if test $ac_mid -le $ac_hi; then
- ac_lo= ac_hi=
- break
- fi
- ac_mid=`expr 2 '*' $ac_mid`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_lo= ac_hi=
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-# Binary search between lo and hi bounds.
-while test "x$ac_lo" != "x$ac_hi"; do
- ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef short int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_hi=$ac_mid
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_lo=`expr '(' $ac_mid ')' + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-case $ac_lo in
-?*) ac_cv_sizeof_short_int=$ac_lo;;
-'') if test "$ac_cv_type_short_int" = yes; then
- { { echo "$as_me:$LINENO: error: cannot compute sizeof (short int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (short int)
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
- else
- ac_cv_sizeof_short_int=0
- fi ;;
-esac
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef short int ac__type_sizeof_;
-static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
-static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
-#include <stdio.h>
-#include <stdlib.h>
-int
-main ()
-{
-
- FILE *f = fopen ("conftest.val", "w");
- if (! f)
- return 1;
- if (((long int) (sizeof (ac__type_sizeof_))) < 0)
- {
- long int i = longval ();
- if (i != ((long int) (sizeof (ac__type_sizeof_))))
- return 1;
- fprintf (f, "%ld\n", i);
- }
- else
- {
- unsigned long int i = ulongval ();
- if (i != ((long int) (sizeof (ac__type_sizeof_))))
- return 1;
- fprintf (f, "%lu\n", i);
- }
- return ferror (f) || fclose (f) != 0;
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_sizeof_short_int=`cat conftest.val`
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-if test "$ac_cv_type_short_int" = yes; then
- { { echo "$as_me:$LINENO: error: cannot compute sizeof (short int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (short int)
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
- else
- ac_cv_sizeof_short_int=0
- fi
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.val
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_short_int" >&5
-echo "${ECHO_T}$ac_cv_sizeof_short_int" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_SHORT_INT $ac_cv_sizeof_short_int
-_ACEOF
-
-
-{ echo "$as_me:$LINENO: checking for int" >&5
-echo $ECHO_N "checking for int... $ECHO_C" >&6; }
-if test "${ac_cv_type_int+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-typedef int ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_int=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_int=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5
-echo "${ECHO_T}$ac_cv_type_int" >&6; }
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ echo "$as_me:$LINENO: checking size of int" >&5
-echo $ECHO_N "checking size of int... $ECHO_C" >&6; }
-if test "${ac_cv_sizeof_int+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test "$cross_compiling" = yes; then
- # Depending upon the size, compute the lo and hi bounds.
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_lo=0 ac_mid=0
- while :; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_hi=$ac_mid; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_lo=`expr $ac_mid + 1`
- if test $ac_lo -le $ac_mid; then
- ac_lo= ac_hi=
- break
- fi
- ac_mid=`expr 2 '*' $ac_mid + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_hi=-1 ac_mid=-1
- while :; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_lo=$ac_mid; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_hi=`expr '(' $ac_mid ')' - 1`
- if test $ac_mid -le $ac_hi; then
- ac_lo= ac_hi=
- break
- fi
- ac_mid=`expr 2 '*' $ac_mid`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_lo= ac_hi=
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-# Binary search between lo and hi bounds.
-while test "x$ac_lo" != "x$ac_hi"; do
- ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_hi=$ac_mid
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_lo=`expr '(' $ac_mid ')' + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-case $ac_lo in
-?*) ac_cv_sizeof_int=$ac_lo;;
-'') if test "$ac_cv_type_int" = yes; then
- { { echo "$as_me:$LINENO: error: cannot compute sizeof (int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (int)
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
- else
- ac_cv_sizeof_int=0
- fi ;;
-esac
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef int ac__type_sizeof_;
-static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
-static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
-#include <stdio.h>
-#include <stdlib.h>
-int
-main ()
-{
-
- FILE *f = fopen ("conftest.val", "w");
- if (! f)
- return 1;
- if (((long int) (sizeof (ac__type_sizeof_))) < 0)
- {
- long int i = longval ();
- if (i != ((long int) (sizeof (ac__type_sizeof_))))
- return 1;
- fprintf (f, "%ld\n", i);
- }
- else
- {
- unsigned long int i = ulongval ();
- if (i != ((long int) (sizeof (ac__type_sizeof_))))
- return 1;
- fprintf (f, "%lu\n", i);
- }
- return ferror (f) || fclose (f) != 0;
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_sizeof_int=`cat conftest.val`
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-if test "$ac_cv_type_int" = yes; then
- { { echo "$as_me:$LINENO: error: cannot compute sizeof (int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (int)
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
- else
- ac_cv_sizeof_int=0
- fi
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.val
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5
-echo "${ECHO_T}$ac_cv_sizeof_int" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_INT $ac_cv_sizeof_int
-_ACEOF
-
-
-{ echo "$as_me:$LINENO: checking for long int" >&5
-echo $ECHO_N "checking for long int... $ECHO_C" >&6; }
-if test "${ac_cv_type_long_int+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-typedef long int ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_long_int=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_long_int=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_long_int" >&5
-echo "${ECHO_T}$ac_cv_type_long_int" >&6; }
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ echo "$as_me:$LINENO: checking size of long int" >&5
-echo $ECHO_N "checking size of long int... $ECHO_C" >&6; }
-if test "${ac_cv_sizeof_long_int+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test "$cross_compiling" = yes; then
- # Depending upon the size, compute the lo and hi bounds.
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_lo=0 ac_mid=0
- while :; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_hi=$ac_mid; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_lo=`expr $ac_mid + 1`
- if test $ac_lo -le $ac_mid; then
- ac_lo= ac_hi=
- break
- fi
- ac_mid=`expr 2 '*' $ac_mid + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_hi=-1 ac_mid=-1
- while :; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_lo=$ac_mid; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_hi=`expr '(' $ac_mid ')' - 1`
- if test $ac_mid -le $ac_hi; then
- ac_lo= ac_hi=
- break
- fi
- ac_mid=`expr 2 '*' $ac_mid`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_lo= ac_hi=
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-# Binary search between lo and hi bounds.
-while test "x$ac_lo" != "x$ac_hi"; do
- ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_hi=$ac_mid
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_lo=`expr '(' $ac_mid ')' + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-case $ac_lo in
-?*) ac_cv_sizeof_long_int=$ac_lo;;
-'') if test "$ac_cv_type_long_int" = yes; then
- { { echo "$as_me:$LINENO: error: cannot compute sizeof (long int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (long int)
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
- else
- ac_cv_sizeof_long_int=0
- fi ;;
-esac
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef long int ac__type_sizeof_;
-static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
-static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
-#include <stdio.h>
-#include <stdlib.h>
-int
-main ()
-{
-
- FILE *f = fopen ("conftest.val", "w");
- if (! f)
- return 1;
- if (((long int) (sizeof (ac__type_sizeof_))) < 0)
- {
- long int i = longval ();
- if (i != ((long int) (sizeof (ac__type_sizeof_))))
- return 1;
- fprintf (f, "%ld\n", i);
- }
- else
- {
- unsigned long int i = ulongval ();
- if (i != ((long int) (sizeof (ac__type_sizeof_))))
- return 1;
- fprintf (f, "%lu\n", i);
- }
- return ferror (f) || fclose (f) != 0;
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_sizeof_long_int=`cat conftest.val`
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-if test "$ac_cv_type_long_int" = yes; then
- { { echo "$as_me:$LINENO: error: cannot compute sizeof (long int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (long int)
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
- else
- ac_cv_sizeof_long_int=0
- fi
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.val
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_int" >&5
-echo "${ECHO_T}$ac_cv_sizeof_long_int" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG_INT $ac_cv_sizeof_long_int
-_ACEOF
-
-
-{ echo "$as_me:$LINENO: checking for long long int" >&5
-echo $ECHO_N "checking for long long int... $ECHO_C" >&6; }
-if test "${ac_cv_type_long_long_int+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-typedef long long int ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_long_long_int=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_long_long_int=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_long_long_int" >&5
-echo "${ECHO_T}$ac_cv_type_long_long_int" >&6; }
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ echo "$as_me:$LINENO: checking size of long long int" >&5
-echo $ECHO_N "checking size of long long int... $ECHO_C" >&6; }
-if test "${ac_cv_sizeof_long_long_int+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test "$cross_compiling" = yes; then
- # Depending upon the size, compute the lo and hi bounds.
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef long long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_lo=0 ac_mid=0
- while :; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef long long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_hi=$ac_mid; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_lo=`expr $ac_mid + 1`
- if test $ac_lo -le $ac_mid; then
- ac_lo= ac_hi=
- break
- fi
- ac_mid=`expr 2 '*' $ac_mid + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef long long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_hi=-1 ac_mid=-1
- while :; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef long long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_lo=$ac_mid; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_hi=`expr '(' $ac_mid ')' - 1`
- if test $ac_mid -le $ac_hi; then
- ac_lo= ac_hi=
- break
- fi
- ac_mid=`expr 2 '*' $ac_mid`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_lo= ac_hi=
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-# Binary search between lo and hi bounds.
-while test "x$ac_lo" != "x$ac_hi"; do
- ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef long long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_hi=$ac_mid
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_lo=`expr '(' $ac_mid ')' + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-case $ac_lo in
-?*) ac_cv_sizeof_long_long_int=$ac_lo;;
-'') if test "$ac_cv_type_long_long_int" = yes; then
- { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (long long int)
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
- else
- ac_cv_sizeof_long_long_int=0
- fi ;;
-esac
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
- typedef long long int ac__type_sizeof_;
-static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
-static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
-#include <stdio.h>
-#include <stdlib.h>
-int
-main ()
-{
-
- FILE *f = fopen ("conftest.val", "w");
- if (! f)
- return 1;
- if (((long int) (sizeof (ac__type_sizeof_))) < 0)
- {
- long int i = longval ();
- if (i != ((long int) (sizeof (ac__type_sizeof_))))
- return 1;
- fprintf (f, "%ld\n", i);
- }
- else
- {
- unsigned long int i = ulongval ();
- if (i != ((long int) (sizeof (ac__type_sizeof_))))
- return 1;
- fprintf (f, "%lu\n", i);
- }
- return ferror (f) || fclose (f) != 0;
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_sizeof_long_long_int=`cat conftest.val`
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-if test "$ac_cv_type_long_long_int" = yes; then
- { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (long long int)
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
- else
- ac_cv_sizeof_long_long_int=0
- fi
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.val
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long_int" >&5
-echo "${ECHO_T}$ac_cv_sizeof_long_long_int" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG_LONG_INT $ac_cv_sizeof_long_long_int
-_ACEOF
-
-
-
-# Sanity check long long for some platforms (AIX)
-if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then
- ac_cv_sizeof_long_long_int=0
-fi
-
-# compute LLONG_MIN and LLONG_MAX if we don't know them.
-if test -z "$have_llong_max"; then
- { echo "$as_me:$LINENO: checking for max value of long long" >&5
-echo $ECHO_N "checking for max value of long long... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
-
- { echo "$as_me:$LINENO: WARNING: cross compiling: not checking" >&5
-echo "$as_me: WARNING: cross compiling: not checking" >&2;}
-
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-/* Why is this so damn hard? */
-#ifdef __GNUC__
-# undef __GNUC__
-#endif
-#define __USE_ISOC99
-#include <limits.h>
-#define DATA "conftest.llminmax"
-#define my_abs(a) ((a) < 0 ? ((a) * -1) : (a))
-
-/*
- * printf in libc on some platforms (eg old Tru64) does not understand %lld so
- * we do this the hard way.
- */
-static int
-fprint_ll(FILE *f, long long n)
-{
- unsigned int i;
- int l[sizeof(long long) * 8];
-
- if (n < 0)
- if (fprintf(f, "-") < 0)
- return -1;
- for (i = 0; n != 0; i++) {
- l[i] = my_abs(n % 10);
- n /= 10;
- }
- do {
- if (fprintf(f, "%d", l[--i]) < 0)
- return -1;
- } while (i != 0);
- if (fprintf(f, " ") < 0)
- return -1;
- return 0;
-}
-
-int
-main ()
-{
-
- FILE *f;
- long long i, llmin, llmax = 0;
-
- if((f = fopen(DATA,"w")) == NULL)
- exit(1);
-
-#if defined(LLONG_MIN) && defined(LLONG_MAX)
- fprintf(stderr, "Using system header for LLONG_MIN and LLONG_MAX\n");
- llmin = LLONG_MIN;
- llmax = LLONG_MAX;
-#else
- fprintf(stderr, "Calculating LLONG_MIN and LLONG_MAX\n");
- /* This will work on one's complement and two's complement */
- for (i = 1; i > llmax; i <<= 1, i++)
- llmax = i;
- llmin = llmax + 1LL; /* wrap */
-#endif
-
- /* Sanity check */
- if (llmin + 1 < llmin || llmin - 1 < llmin || llmax + 1 > llmax
- || llmax - 1 > llmax || llmin == llmax || llmin == 0
- || llmax == 0 || llmax < LONG_MAX || llmin > LONG_MIN) {
- fprintf(f, "unknown unknown\n");
- exit(2);
- }
-
- if (fprint_ll(f, llmin) < 0)
- exit(3);
- if (fprint_ll(f, llmax) < 0)
- exit(4);
- if (fclose(f) < 0)
- exit(5);
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
- llong_min=`$AWK '{print $1}' conftest.llminmax`
- llong_max=`$AWK '{print $2}' conftest.llminmax`
-
- { echo "$as_me:$LINENO: result: $llong_max" >&5
-echo "${ECHO_T}$llong_max" >&6; }
-
-cat >>confdefs.h <<_ACEOF
-#define LLONG_MAX ${llong_max}LL
-_ACEOF
-
- { echo "$as_me:$LINENO: checking for min value of long long" >&5
-echo $ECHO_N "checking for min value of long long... $ECHO_C" >&6; }
- { echo "$as_me:$LINENO: result: $llong_min" >&5
-echo "${ECHO_T}$llong_min" >&6; }
-
-cat >>confdefs.h <<_ACEOF
-#define LLONG_MIN ${llong_min}LL
-_ACEOF
-
-
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- { echo "$as_me:$LINENO: result: not found" >&5
-echo "${ECHO_T}not found" >&6; }
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-
-
-# More checks for data types
-{ echo "$as_me:$LINENO: checking for u_int type" >&5
-echo $ECHO_N "checking for u_int type... $ECHO_C" >&6; }
-if test "${ac_cv_have_u_int+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <sys/types.h>
-int
-main ()
-{
- u_int a; a = 1;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_u_int="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_u_int="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_u_int" >&5
-echo "${ECHO_T}$ac_cv_have_u_int" >&6; }
-if test "x$ac_cv_have_u_int" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_U_INT 1
-_ACEOF
-
- have_u_int=1
-fi
-
-{ echo "$as_me:$LINENO: checking for intXX_t types" >&5
-echo $ECHO_N "checking for intXX_t types... $ECHO_C" >&6; }
-if test "${ac_cv_have_intxx_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <sys/types.h>
-int
-main ()
-{
- int8_t a; int16_t b; int32_t c; a = b = c = 1;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_intxx_t="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_intxx_t="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_intxx_t" >&5
-echo "${ECHO_T}$ac_cv_have_intxx_t" >&6; }
-if test "x$ac_cv_have_intxx_t" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_INTXX_T 1
-_ACEOF
-
- have_intxx_t=1
-fi
-
-if (test -z "$have_intxx_t" && \
- test "x$ac_cv_header_stdint_h" = "xyes")
-then
- { echo "$as_me:$LINENO: checking for intXX_t types in stdint.h" >&5
-echo $ECHO_N "checking for intXX_t types in stdint.h... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <stdint.h>
-int
-main ()
-{
- int8_t a; int16_t b; int32_t c; a = b = c = 1;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_INTXX_T 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-{ echo "$as_me:$LINENO: checking for int64_t type" >&5
-echo $ECHO_N "checking for int64_t type... $ECHO_C" >&6; }
-if test "${ac_cv_have_int64_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#include <sys/socket.h>
-#ifdef HAVE_SYS_BITYPES_H
-# include <sys/bitypes.h>
-#endif
-
-int
-main ()
-{
-
-int64_t a; a = 1;
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_int64_t="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_int64_t="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_int64_t" >&5
-echo "${ECHO_T}$ac_cv_have_int64_t" >&6; }
-if test "x$ac_cv_have_int64_t" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_INT64_T 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for u_intXX_t types" >&5
-echo $ECHO_N "checking for u_intXX_t types... $ECHO_C" >&6; }
-if test "${ac_cv_have_u_intxx_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <sys/types.h>
-int
-main ()
-{
- u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_u_intxx_t="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_u_intxx_t="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_u_intxx_t" >&5
-echo "${ECHO_T}$ac_cv_have_u_intxx_t" >&6; }
-if test "x$ac_cv_have_u_intxx_t" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_U_INTXX_T 1
-_ACEOF
-
- have_u_intxx_t=1
-fi
-
-if test -z "$have_u_intxx_t" ; then
- { echo "$as_me:$LINENO: checking for u_intXX_t types in sys/socket.h" >&5
-echo $ECHO_N "checking for u_intXX_t types in sys/socket.h... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <sys/socket.h>
-int
-main ()
-{
- u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_U_INTXX_T 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-{ echo "$as_me:$LINENO: checking for u_int64_t types" >&5
-echo $ECHO_N "checking for u_int64_t types... $ECHO_C" >&6; }
-if test "${ac_cv_have_u_int64_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <sys/types.h>
-int
-main ()
-{
- u_int64_t a; a = 1;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_u_int64_t="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_u_int64_t="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_u_int64_t" >&5
-echo "${ECHO_T}$ac_cv_have_u_int64_t" >&6; }
-if test "x$ac_cv_have_u_int64_t" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_U_INT64_T 1
-_ACEOF
-
- have_u_int64_t=1
-fi
-
-if (test -z "$have_u_int64_t" && \
- test "x$ac_cv_header_sys_bitypes_h" = "xyes")
-then
- { echo "$as_me:$LINENO: checking for u_int64_t type in sys/bitypes.h" >&5
-echo $ECHO_N "checking for u_int64_t type in sys/bitypes.h... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <sys/bitypes.h>
-int
-main ()
-{
- u_int64_t a; a = 1
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_U_INT64_T 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-if test -z "$have_u_intxx_t" ; then
- { echo "$as_me:$LINENO: checking for uintXX_t types" >&5
-echo $ECHO_N "checking for uintXX_t types... $ECHO_C" >&6; }
-if test "${ac_cv_have_uintxx_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-
-int
-main ()
-{
-
- uint8_t a;
- uint16_t b;
- uint32_t c;
- a = b = c = 1;
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_uintxx_t="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_uintxx_t="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_uintxx_t" >&5
-echo "${ECHO_T}$ac_cv_have_uintxx_t" >&6; }
- if test "x$ac_cv_have_uintxx_t" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_UINTXX_T 1
-_ACEOF
-
- fi
-fi
-
-if (test -z "$have_uintxx_t" && \
- test "x$ac_cv_header_stdint_h" = "xyes")
-then
- { echo "$as_me:$LINENO: checking for uintXX_t types in stdint.h" >&5
-echo $ECHO_N "checking for uintXX_t types in stdint.h... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <stdint.h>
-int
-main ()
-{
- uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_UINTXX_T 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-if (test -z "$have_uintxx_t" && \
- test "x$ac_cv_header_inttypes_h" = "xyes")
-then
- { echo "$as_me:$LINENO: checking for uintXX_t types in inttypes.h" >&5
-echo $ECHO_N "checking for uintXX_t types in inttypes.h... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <inttypes.h>
-int
-main ()
-{
- uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_UINTXX_T 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-if (test -z "$have_u_intxx_t" || test -z "$have_intxx_t" && \
- test "x$ac_cv_header_sys_bitypes_h" = "xyes")
-then
- { echo "$as_me:$LINENO: checking for intXX_t and u_intXX_t types in sys/bitypes.h" >&5
-echo $ECHO_N "checking for intXX_t and u_intXX_t types in sys/bitypes.h... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/bitypes.h>
-
-int
-main ()
-{
-
- int8_t a; int16_t b; int32_t c;
- u_int8_t e; u_int16_t f; u_int32_t g;
- a = b = c = e = f = g = 1;
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_U_INTXX_T 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_INTXX_T 1
-_ACEOF
-
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-{ echo "$as_me:$LINENO: checking for u_char" >&5
-echo $ECHO_N "checking for u_char... $ECHO_C" >&6; }
-if test "${ac_cv_have_u_char+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <sys/types.h>
-int
-main ()
-{
- u_char foo; foo = 125;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_u_char="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_u_char="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_u_char" >&5
-echo "${ECHO_T}$ac_cv_have_u_char" >&6; }
-if test "x$ac_cv_have_u_char" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_U_CHAR 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for intmax_t" >&5
-echo $ECHO_N "checking for intmax_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_intmax_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <stdint.h>
-
-
-typedef intmax_t ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_intmax_t=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_intmax_t=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_intmax_t" >&5
-echo "${ECHO_T}$ac_cv_type_intmax_t" >&6; }
-if test $ac_cv_type_intmax_t = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_INTMAX_T 1
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking for uintmax_t" >&5
-echo $ECHO_N "checking for uintmax_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_uintmax_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <stdint.h>
-
-
-typedef uintmax_t ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_uintmax_t=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_uintmax_t=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_uintmax_t" >&5
-echo "${ECHO_T}$ac_cv_type_uintmax_t" >&6; }
-if test $ac_cv_type_uintmax_t = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UINTMAX_T 1
-_ACEOF
-
-
-fi
-
-
-
- { echo "$as_me:$LINENO: checking for socklen_t" >&5
-echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_socklen_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/socket.h>
-
-typedef socklen_t ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_socklen_t=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_socklen_t=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_socklen_t" >&5
-echo "${ECHO_T}$ac_cv_type_socklen_t" >&6; }
-if test $ac_cv_type_socklen_t = yes; then
- :
-else
-
- { echo "$as_me:$LINENO: checking for socklen_t equivalent" >&5
-echo $ECHO_N "checking for socklen_t equivalent... $ECHO_C" >&6; }
- if test "${curl_cv_socklen_t_equiv+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- # Systems have either "struct sockaddr *" or
- # "void *" as the second argument to getpeername
- curl_cv_socklen_t_equiv=
- for arg2 in "struct sockaddr" void; do
- for t in int size_t unsigned long "unsigned long"; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
- #include <sys/types.h>
- #include <sys/socket.h>
-
- int getpeername (int, $arg2 *, $t *);
-
-int
-main ()
-{
-
- $t len;
- getpeername(0,0,&len);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
-
- curl_cv_socklen_t_equiv="$t"
- break
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- done
- done
-
- if test "x$curl_cv_socklen_t_equiv" = x; then
- { { echo "$as_me:$LINENO: error: Cannot find a type to use in place of socklen_t" >&5
-echo "$as_me: error: Cannot find a type to use in place of socklen_t" >&2;}
- { (exit 1); exit 1; }; }
- fi
-
-fi
-
- { echo "$as_me:$LINENO: result: $curl_cv_socklen_t_equiv" >&5
-echo "${ECHO_T}$curl_cv_socklen_t_equiv" >&6; }
-
-cat >>confdefs.h <<_ACEOF
-#define socklen_t $curl_cv_socklen_t_equiv
-_ACEOF
-
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking for sig_atomic_t" >&5
-echo $ECHO_N "checking for sig_atomic_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_sig_atomic_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <signal.h>
-
-typedef sig_atomic_t ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_sig_atomic_t=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_sig_atomic_t=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_sig_atomic_t" >&5
-echo "${ECHO_T}$ac_cv_type_sig_atomic_t" >&6; }
-if test $ac_cv_type_sig_atomic_t = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_SIG_ATOMIC_T 1
-_ACEOF
-
-
-fi
-
-{ echo "$as_me:$LINENO: checking for fsblkcnt_t" >&5
-echo $ECHO_N "checking for fsblkcnt_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_fsblkcnt_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-#ifdef HAVE_SYS_STATFS_H
-#include <sys/statfs.h>
-#endif
-#ifdef HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#endif
-
-
-typedef fsblkcnt_t ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_fsblkcnt_t=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_fsblkcnt_t=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_fsblkcnt_t" >&5
-echo "${ECHO_T}$ac_cv_type_fsblkcnt_t" >&6; }
-if test $ac_cv_type_fsblkcnt_t = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_FSBLKCNT_T 1
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking for fsfilcnt_t" >&5
-echo $ECHO_N "checking for fsfilcnt_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_fsfilcnt_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-#ifdef HAVE_SYS_STATFS_H
-#include <sys/statfs.h>
-#endif
-#ifdef HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#endif
-
-
-typedef fsfilcnt_t ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_fsfilcnt_t=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_fsfilcnt_t=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_fsfilcnt_t" >&5
-echo "${ECHO_T}$ac_cv_type_fsfilcnt_t" >&6; }
-if test $ac_cv_type_fsfilcnt_t = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_FSFILCNT_T 1
-_ACEOF
-
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking for in_addr_t" >&5
-echo $ECHO_N "checking for in_addr_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_in_addr_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <netinet/in.h>
-
-typedef in_addr_t ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_in_addr_t=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_in_addr_t=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_in_addr_t" >&5
-echo "${ECHO_T}$ac_cv_type_in_addr_t" >&6; }
-if test $ac_cv_type_in_addr_t = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_IN_ADDR_T 1
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking for in_port_t" >&5
-echo $ECHO_N "checking for in_port_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_in_port_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <netinet/in.h>
-
-typedef in_port_t ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_in_port_t=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_in_port_t=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_in_port_t" >&5
-echo "${ECHO_T}$ac_cv_type_in_port_t" >&6; }
-if test $ac_cv_type_in_port_t = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_IN_PORT_T 1
-_ACEOF
-
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking for size_t" >&5
-echo $ECHO_N "checking for size_t... $ECHO_C" >&6; }
-if test "${ac_cv_have_size_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <sys/types.h>
-int
-main ()
-{
- size_t foo; foo = 1235;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_size_t="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_size_t="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_size_t" >&5
-echo "${ECHO_T}$ac_cv_have_size_t" >&6; }
-if test "x$ac_cv_have_size_t" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_SIZE_T 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for ssize_t" >&5
-echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6; }
-if test "${ac_cv_have_ssize_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <sys/types.h>
-int
-main ()
-{
- ssize_t foo; foo = 1235;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_ssize_t="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_ssize_t="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_ssize_t" >&5
-echo "${ECHO_T}$ac_cv_have_ssize_t" >&6; }
-if test "x$ac_cv_have_ssize_t" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_SSIZE_T 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for clock_t" >&5
-echo $ECHO_N "checking for clock_t... $ECHO_C" >&6; }
-if test "${ac_cv_have_clock_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <time.h>
-int
-main ()
-{
- clock_t foo; foo = 1235;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_clock_t="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_clock_t="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_clock_t" >&5
-echo "${ECHO_T}$ac_cv_have_clock_t" >&6; }
-if test "x$ac_cv_have_clock_t" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_CLOCK_T 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for sa_family_t" >&5
-echo $ECHO_N "checking for sa_family_t... $ECHO_C" >&6; }
-if test "${ac_cv_have_sa_family_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-int
-main ()
-{
- sa_family_t foo; foo = 1235;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_sa_family_t="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-int
-main ()
-{
- sa_family_t foo; foo = 1235;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_sa_family_t="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_sa_family_t="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_sa_family_t" >&5
-echo "${ECHO_T}$ac_cv_have_sa_family_t" >&6; }
-if test "x$ac_cv_have_sa_family_t" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_SA_FAMILY_T 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for pid_t" >&5
-echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; }
-if test "${ac_cv_have_pid_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <sys/types.h>
-int
-main ()
-{
- pid_t foo; foo = 1235;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_pid_t="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_pid_t="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_pid_t" >&5
-echo "${ECHO_T}$ac_cv_have_pid_t" >&6; }
-if test "x$ac_cv_have_pid_t" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_PID_T 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for mode_t" >&5
-echo $ECHO_N "checking for mode_t... $ECHO_C" >&6; }
-if test "${ac_cv_have_mode_t+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <sys/types.h>
-int
-main ()
-{
- mode_t foo; foo = 1235;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_mode_t="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_mode_t="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_mode_t" >&5
-echo "${ECHO_T}$ac_cv_have_mode_t" >&6; }
-if test "x$ac_cv_have_mode_t" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_MODE_T 1
-_ACEOF
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking for struct sockaddr_storage" >&5
-echo $ECHO_N "checking for struct sockaddr_storage... $ECHO_C" >&6; }
-if test "${ac_cv_have_struct_sockaddr_storage+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-int
-main ()
-{
- struct sockaddr_storage s;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_struct_sockaddr_storage="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_struct_sockaddr_storage="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_struct_sockaddr_storage" >&5
-echo "${ECHO_T}$ac_cv_have_struct_sockaddr_storage" >&6; }
-if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_STRUCT_SOCKADDR_STORAGE 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for struct sockaddr_in6" >&5
-echo $ECHO_N "checking for struct sockaddr_in6... $ECHO_C" >&6; }
-if test "${ac_cv_have_struct_sockaddr_in6+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <netinet/in.h>
-
-int
-main ()
-{
- struct sockaddr_in6 s; s.sin6_family = 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_struct_sockaddr_in6="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_struct_sockaddr_in6="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_struct_sockaddr_in6" >&5
-echo "${ECHO_T}$ac_cv_have_struct_sockaddr_in6" >&6; }
-if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_STRUCT_SOCKADDR_IN6 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for struct in6_addr" >&5
-echo $ECHO_N "checking for struct in6_addr... $ECHO_C" >&6; }
-if test "${ac_cv_have_struct_in6_addr+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <netinet/in.h>
-
-int
-main ()
-{
- struct in6_addr s; s.s6_addr[0] = 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_struct_in6_addr="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_struct_in6_addr="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_struct_in6_addr" >&5
-echo "${ECHO_T}$ac_cv_have_struct_in6_addr" >&6; }
-if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_STRUCT_IN6_ADDR 1
-_ACEOF
-
-
- { echo "$as_me:$LINENO: checking for struct sockaddr_in6.sin6_scope_id" >&5
-echo $ECHO_N "checking for struct sockaddr_in6.sin6_scope_id... $ECHO_C" >&6; }
-if test "${ac_cv_member_struct_sockaddr_in6_sin6_scope_id+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#include <netinet/in.h>
-
-
-int
-main ()
-{
-static struct sockaddr_in6 ac_aggr;
-if (ac_aggr.sin6_scope_id)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_sockaddr_in6_sin6_scope_id=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#include <netinet/in.h>
-
-
-int
-main ()
-{
-static struct sockaddr_in6 ac_aggr;
-if (sizeof ac_aggr.sin6_scope_id)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_sockaddr_in6_sin6_scope_id=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_member_struct_sockaddr_in6_sin6_scope_id=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_in6_sin6_scope_id" >&5
-echo "${ECHO_T}$ac_cv_member_struct_sockaddr_in6_sin6_scope_id" >&6; }
-if test $ac_cv_member_struct_sockaddr_in6_sin6_scope_id = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1
-_ACEOF
-
-
-fi
-
-fi
-
-{ echo "$as_me:$LINENO: checking for struct addrinfo" >&5
-echo $ECHO_N "checking for struct addrinfo... $ECHO_C" >&6; }
-if test "${ac_cv_have_struct_addrinfo+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-int
-main ()
-{
- struct addrinfo s; s.ai_flags = AI_PASSIVE;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_struct_addrinfo="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_struct_addrinfo="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_struct_addrinfo" >&5
-echo "${ECHO_T}$ac_cv_have_struct_addrinfo" >&6; }
-if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_STRUCT_ADDRINFO 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for struct timeval" >&5
-echo $ECHO_N "checking for struct timeval... $ECHO_C" >&6; }
-if test "${ac_cv_have_struct_timeval+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <sys/time.h>
-int
-main ()
-{
- struct timeval tv; tv.tv_sec = 1;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_struct_timeval="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_struct_timeval="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_struct_timeval" >&5
-echo "${ECHO_T}$ac_cv_have_struct_timeval" >&6; }
-if test "x$ac_cv_have_struct_timeval" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_STRUCT_TIMEVAL 1
-_ACEOF
-
- have_struct_timeval=1
-fi
-
-{ echo "$as_me:$LINENO: checking for struct timespec" >&5
-echo $ECHO_N "checking for struct timespec... $ECHO_C" >&6; }
-if test "${ac_cv_type_struct_timespec+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-typedef struct timespec ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
- return 0;
-if (sizeof (ac__type_new_))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_type_struct_timespec=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_struct_timespec=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_struct_timespec" >&5
-echo "${ECHO_T}$ac_cv_type_struct_timespec" >&6; }
-if test $ac_cv_type_struct_timespec = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_TIMESPEC 1
-_ACEOF
-
-
-fi
-
-
-# We need int64_t or else certian parts of the compile will fail.
-if test "x$ac_cv_have_int64_t" = "xno" && \
- test "x$ac_cv_sizeof_long_int" != "x8" && \
- test "x$ac_cv_sizeof_long_long_int" = "x0" ; then
- echo "OpenSSH requires int64_t support. Contact your vendor or install"
- echo "an alternative compiler (I.E., GCC) before continuing."
- echo ""
- exit 1;
-else
- if test "$cross_compiling" = yes; then
- { echo "$as_me:$LINENO: WARNING: cross compiling: Assuming working snprintf()" >&5
-echo "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;}
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_SNPRINTF
-main()
-{
- char buf[50];
- char expected_out[50];
- int mazsize = 50 ;
-#if (SIZEOF_LONG_INT == 8)
- long int num = 0x7fffffffffffffff;
-#else
- long long num = 0x7fffffffffffffffll;
-#endif
- strcpy(expected_out, "9223372036854775807");
- snprintf(buf, mazsize, "%lld", num);
- if(strcmp(buf, expected_out) != 0)
- exit(1);
- exit(0);
-}
-#else
-main() { exit(0); }
-#endif
-
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- true
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
- cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SNPRINTF 1
-_ACEOF
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-
-
-# look for field 'ut_host' in header 'utmp.h'
- ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_host
- { echo "$as_me:$LINENO: checking for ut_host field in utmp.h" >&5
-echo $ECHO_N "checking for ut_host field in utmp.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmp.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_host" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_HOST_IN_UTMP 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_host' in header 'utmpx.h'
- ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_host
- { echo "$as_me:$LINENO: checking for ut_host field in utmpx.h" >&5
-echo $ECHO_N "checking for ut_host field in utmpx.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmpx.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_host" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_HOST_IN_UTMPX 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'syslen' in header 'utmpx.h'
- ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"syslen
- { echo "$as_me:$LINENO: checking for syslen field in utmpx.h" >&5
-echo $ECHO_N "checking for syslen field in utmpx.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmpx.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "syslen" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_SYSLEN_IN_UTMPX 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_pid' in header 'utmp.h'
- ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_pid
- { echo "$as_me:$LINENO: checking for ut_pid field in utmp.h" >&5
-echo $ECHO_N "checking for ut_pid field in utmp.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmp.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_pid" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_PID_IN_UTMP 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_type' in header 'utmp.h'
- ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_type
- { echo "$as_me:$LINENO: checking for ut_type field in utmp.h" >&5
-echo $ECHO_N "checking for ut_type field in utmp.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmp.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_type" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_TYPE_IN_UTMP 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_type' in header 'utmpx.h'
- ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_type
- { echo "$as_me:$LINENO: checking for ut_type field in utmpx.h" >&5
-echo $ECHO_N "checking for ut_type field in utmpx.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmpx.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_type" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_TYPE_IN_UTMPX 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_tv' in header 'utmp.h'
- ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_tv
- { echo "$as_me:$LINENO: checking for ut_tv field in utmp.h" >&5
-echo $ECHO_N "checking for ut_tv field in utmp.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmp.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_tv" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_TV_IN_UTMP 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_id' in header 'utmp.h'
- ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_id
- { echo "$as_me:$LINENO: checking for ut_id field in utmp.h" >&5
-echo $ECHO_N "checking for ut_id field in utmp.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmp.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_id" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ID_IN_UTMP 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_id' in header 'utmpx.h'
- ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_id
- { echo "$as_me:$LINENO: checking for ut_id field in utmpx.h" >&5
-echo $ECHO_N "checking for ut_id field in utmpx.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmpx.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_id" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ID_IN_UTMPX 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_addr' in header 'utmp.h'
- ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr
- { echo "$as_me:$LINENO: checking for ut_addr field in utmp.h" >&5
-echo $ECHO_N "checking for ut_addr field in utmp.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmp.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_addr" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ADDR_IN_UTMP 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_addr' in header 'utmpx.h'
- ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr
- { echo "$as_me:$LINENO: checking for ut_addr field in utmpx.h" >&5
-echo $ECHO_N "checking for ut_addr field in utmpx.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmpx.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_addr" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ADDR_IN_UTMPX 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_addr_v6' in header 'utmp.h'
- ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr_v6
- { echo "$as_me:$LINENO: checking for ut_addr_v6 field in utmp.h" >&5
-echo $ECHO_N "checking for ut_addr_v6 field in utmp.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmp.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_addr_v6" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ADDR_V6_IN_UTMP 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_addr_v6' in header 'utmpx.h'
- ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr_v6
- { echo "$as_me:$LINENO: checking for ut_addr_v6 field in utmpx.h" >&5
-echo $ECHO_N "checking for ut_addr_v6 field in utmpx.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmpx.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_addr_v6" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ADDR_V6_IN_UTMPX 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_exit' in header 'utmp.h'
- ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_exit
- { echo "$as_me:$LINENO: checking for ut_exit field in utmp.h" >&5
-echo $ECHO_N "checking for ut_exit field in utmp.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmp.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_exit" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_EXIT_IN_UTMP 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_time' in header 'utmp.h'
- ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_time
- { echo "$as_me:$LINENO: checking for ut_time field in utmp.h" >&5
-echo $ECHO_N "checking for ut_time field in utmp.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmp.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_time" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_TIME_IN_UTMP 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_time' in header 'utmpx.h'
- ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_time
- { echo "$as_me:$LINENO: checking for ut_time field in utmpx.h" >&5
-echo $ECHO_N "checking for ut_time field in utmpx.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmpx.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_time" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_TIME_IN_UTMPX 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-# look for field 'ut_tv' in header 'utmpx.h'
- ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
- ossh_varname="ossh_cv_$ossh_safe""_has_"ut_tv
- { echo "$as_me:$LINENO: checking for ut_tv field in utmpx.h" >&5
-echo $ECHO_N "checking for ut_tv field in utmpx.h... $ECHO_C" >&6; }
- if { as_var=$ossh_varname; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <utmpx.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "ut_tv" >/dev/null 2>&1; then
- eval "$ossh_varname=yes"
-else
- eval "$ossh_varname=no"
-fi
-rm -f conftest*
-
-fi
-
- ossh_result=`eval 'echo $'"$ossh_varname"`
- if test -n "`echo $ossh_varname`"; then
- { echo "$as_me:$LINENO: result: $ossh_result" >&5
-echo "${ECHO_T}$ossh_result" >&6; }
- if test "x$ossh_result" = "xyes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_TV_IN_UTMPX 1
-_ACEOF
-
- fi
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-
-{ echo "$as_me:$LINENO: checking for struct stat.st_blksize" >&5
-echo $ECHO_N "checking for struct stat.st_blksize... $ECHO_C" >&6; }
-if test "${ac_cv_member_struct_stat_st_blksize+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-static struct stat ac_aggr;
-if (ac_aggr.st_blksize)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_stat_st_blksize=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-static struct stat ac_aggr;
-if (sizeof ac_aggr.st_blksize)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_stat_st_blksize=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_member_struct_stat_st_blksize=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_blksize" >&5
-echo "${ECHO_T}$ac_cv_member_struct_stat_st_blksize" >&6; }
-if test $ac_cv_member_struct_stat_st_blksize = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
-_ACEOF
-
-
-fi
-
-{ echo "$as_me:$LINENO: checking for struct passwd.pw_gecos" >&5
-echo $ECHO_N "checking for struct passwd.pw_gecos... $ECHO_C" >&6; }
-if test "${ac_cv_member_struct_passwd_pw_gecos+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <pwd.h>
-
-
-int
-main ()
-{
-static struct passwd ac_aggr;
-if (ac_aggr.pw_gecos)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_passwd_pw_gecos=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <pwd.h>
-
-
-int
-main ()
-{
-static struct passwd ac_aggr;
-if (sizeof ac_aggr.pw_gecos)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_passwd_pw_gecos=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_member_struct_passwd_pw_gecos=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_passwd_pw_gecos" >&5
-echo "${ECHO_T}$ac_cv_member_struct_passwd_pw_gecos" >&6; }
-if test $ac_cv_member_struct_passwd_pw_gecos = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_PASSWD_PW_GECOS 1
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking for struct passwd.pw_class" >&5
-echo $ECHO_N "checking for struct passwd.pw_class... $ECHO_C" >&6; }
-if test "${ac_cv_member_struct_passwd_pw_class+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <pwd.h>
-
-
-int
-main ()
-{
-static struct passwd ac_aggr;
-if (ac_aggr.pw_class)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_passwd_pw_class=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <pwd.h>
-
-
-int
-main ()
-{
-static struct passwd ac_aggr;
-if (sizeof ac_aggr.pw_class)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_passwd_pw_class=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_member_struct_passwd_pw_class=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_passwd_pw_class" >&5
-echo "${ECHO_T}$ac_cv_member_struct_passwd_pw_class" >&6; }
-if test $ac_cv_member_struct_passwd_pw_class = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_PASSWD_PW_CLASS 1
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking for struct passwd.pw_change" >&5
-echo $ECHO_N "checking for struct passwd.pw_change... $ECHO_C" >&6; }
-if test "${ac_cv_member_struct_passwd_pw_change+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <pwd.h>
-
-
-int
-main ()
-{
-static struct passwd ac_aggr;
-if (ac_aggr.pw_change)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_passwd_pw_change=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <pwd.h>
-
-
-int
-main ()
-{
-static struct passwd ac_aggr;
-if (sizeof ac_aggr.pw_change)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_passwd_pw_change=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_member_struct_passwd_pw_change=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_passwd_pw_change" >&5
-echo "${ECHO_T}$ac_cv_member_struct_passwd_pw_change" >&6; }
-if test $ac_cv_member_struct_passwd_pw_change = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_PASSWD_PW_CHANGE 1
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking for struct passwd.pw_expire" >&5
-echo $ECHO_N "checking for struct passwd.pw_expire... $ECHO_C" >&6; }
-if test "${ac_cv_member_struct_passwd_pw_expire+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <pwd.h>
-
-
-int
-main ()
-{
-static struct passwd ac_aggr;
-if (ac_aggr.pw_expire)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_passwd_pw_expire=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <pwd.h>
-
-
-int
-main ()
-{
-static struct passwd ac_aggr;
-if (sizeof ac_aggr.pw_expire)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_passwd_pw_expire=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_member_struct_passwd_pw_expire=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_passwd_pw_expire" >&5
-echo "${ECHO_T}$ac_cv_member_struct_passwd_pw_expire" >&6; }
-if test $ac_cv_member_struct_passwd_pw_expire = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_PASSWD_PW_EXPIRE 1
-_ACEOF
-
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking for struct __res_state.retrans" >&5
-echo $ECHO_N "checking for struct __res_state.retrans... $ECHO_C" >&6; }
-if test "${ac_cv_member_struct___res_state_retrans+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-
-
-int
-main ()
-{
-static struct __res_state ac_aggr;
-if (ac_aggr.retrans)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct___res_state_retrans=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-
-
-int
-main ()
-{
-static struct __res_state ac_aggr;
-if (sizeof ac_aggr.retrans)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct___res_state_retrans=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_member_struct___res_state_retrans=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_member_struct___res_state_retrans" >&5
-echo "${ECHO_T}$ac_cv_member_struct___res_state_retrans" >&6; }
-if test $ac_cv_member_struct___res_state_retrans = yes; then
- :
-else
-
-cat >>confdefs.h <<\_ACEOF
-#define __res_state state
-_ACEOF
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking for ss_family field in struct sockaddr_storage" >&5
-echo $ECHO_N "checking for ss_family field in struct sockaddr_storage... $ECHO_C" >&6; }
-if test "${ac_cv_have_ss_family_in_struct_ss+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-int
-main ()
-{
- struct sockaddr_storage s; s.ss_family = 1;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_ss_family_in_struct_ss="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_ss_family_in_struct_ss="no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_ss_family_in_struct_ss" >&5
-echo "${ECHO_T}$ac_cv_have_ss_family_in_struct_ss" >&6; }
-if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_SS_FAMILY_IN_SS 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for __ss_family field in struct sockaddr_storage" >&5
-echo $ECHO_N "checking for __ss_family field in struct sockaddr_storage... $ECHO_C" >&6; }
-if test "${ac_cv_have___ss_family_in_struct_ss+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-int
-main ()
-{
- struct sockaddr_storage s; s.__ss_family = 1;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have___ss_family_in_struct_ss="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have___ss_family_in_struct_ss="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have___ss_family_in_struct_ss" >&5
-echo "${ECHO_T}$ac_cv_have___ss_family_in_struct_ss" >&6; }
-if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE___SS_FAMILY_IN_SS 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for msg_accrights field in struct msghdr" >&5
-echo $ECHO_N "checking for msg_accrights field in struct msghdr... $ECHO_C" >&6; }
-if test "${ac_cv_have_accrights_in_msghdr+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-
-int
-main ()
-{
-
-#ifdef msg_accrights
-#error "msg_accrights is a macro"
-exit(1);
-#endif
-struct msghdr m;
-m.msg_accrights = 0;
-exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_accrights_in_msghdr="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_accrights_in_msghdr="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_accrights_in_msghdr" >&5
-echo "${ECHO_T}$ac_cv_have_accrights_in_msghdr" >&6; }
-if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ACCRIGHTS_IN_MSGHDR 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking if struct statvfs.f_fsid is integral type" >&5
-echo $ECHO_N "checking if struct statvfs.f_fsid is integral type... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/param.h>
-#include <sys/stat.h>
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_MOUNT_H
-#include <sys/mount.h>
-#endif
-#ifdef HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#endif
-
-int
-main ()
-{
- struct statvfs s; s.f_fsid = 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
- { echo "$as_me:$LINENO: checking if fsid_t has member val" >&5
-echo $ECHO_N "checking if fsid_t has member val... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/statvfs.h>
-
-int
-main ()
-{
- fsid_t t; t.val[0] = 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define FSID_HAS_VAL 1
-_ACEOF
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
- { echo "$as_me:$LINENO: checking if f_fsid has member __val" >&5
-echo $ECHO_N "checking if f_fsid has member __val... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/statvfs.h>
-
-int
-main ()
-{
- fsid_t t; t.__val[0] = 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define FSID_HAS___VAL 1
-_ACEOF
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-{ echo "$as_me:$LINENO: checking for msg_control field in struct msghdr" >&5
-echo $ECHO_N "checking for msg_control field in struct msghdr... $ECHO_C" >&6; }
-if test "${ac_cv_have_control_in_msghdr+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-
-int
-main ()
-{
-
-#ifdef msg_control
-#error "msg_control is a macro"
-exit(1);
-#endif
-struct msghdr m;
-m.msg_control = 0;
-exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_control_in_msghdr="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_control_in_msghdr="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_control_in_msghdr" >&5
-echo "${ECHO_T}$ac_cv_have_control_in_msghdr" >&6; }
-if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_CONTROL_IN_MSGHDR 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking if libc defines __progname" >&5
-echo $ECHO_N "checking if libc defines __progname... $ECHO_C" >&6; }
-if test "${ac_cv_libc_defines___progname+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
- extern char *__progname; printf("%s", __progname);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_libc_defines___progname="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_libc_defines___progname="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_libc_defines___progname" >&5
-echo "${ECHO_T}$ac_cv_libc_defines___progname" >&6; }
-if test "x$ac_cv_libc_defines___progname" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE___PROGNAME 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking whether $CC implements __FUNCTION__" >&5
-echo $ECHO_N "checking whether $CC implements __FUNCTION__... $ECHO_C" >&6; }
-if test "${ac_cv_cc_implements___FUNCTION__+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <stdio.h>
-int
-main ()
-{
- printf("%s", __FUNCTION__);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_cc_implements___FUNCTION__="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_cc_implements___FUNCTION__="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_cc_implements___FUNCTION__" >&5
-echo "${ECHO_T}$ac_cv_cc_implements___FUNCTION__" >&6; }
-if test "x$ac_cv_cc_implements___FUNCTION__" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE___FUNCTION__ 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking whether $CC implements __func__" >&5
-echo $ECHO_N "checking whether $CC implements __func__... $ECHO_C" >&6; }
-if test "${ac_cv_cc_implements___func__+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <stdio.h>
-int
-main ()
-{
- printf("%s", __func__);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_cc_implements___func__="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_cc_implements___func__="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_cc_implements___func__" >&5
-echo "${ECHO_T}$ac_cv_cc_implements___func__" >&6; }
-if test "x$ac_cv_cc_implements___func__" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE___func__ 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking whether va_copy exists" >&5
-echo $ECHO_N "checking whether va_copy exists... $ECHO_C" >&6; }
-if test "${ac_cv_have_va_copy+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdarg.h>
-va_list x,y;
-
-int
-main ()
-{
- va_copy(x,y);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_have_va_copy="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_va_copy="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_va_copy" >&5
-echo "${ECHO_T}$ac_cv_have_va_copy" >&6; }
-if test "x$ac_cv_have_va_copy" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_VA_COPY 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking whether __va_copy exists" >&5
-echo $ECHO_N "checking whether __va_copy exists... $ECHO_C" >&6; }
-if test "${ac_cv_have___va_copy+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdarg.h>
-va_list x,y;
-
-int
-main ()
-{
- __va_copy(x,y);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_have___va_copy="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have___va_copy="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have___va_copy" >&5
-echo "${ECHO_T}$ac_cv_have___va_copy" >&6; }
-if test "x$ac_cv_have___va_copy" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE___VA_COPY 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking whether getopt has optreset support" >&5
-echo $ECHO_N "checking whether getopt has optreset support... $ECHO_C" >&6; }
-if test "${ac_cv_have_getopt_optreset+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <getopt.h>
-int
-main ()
-{
- extern int optreset; optreset = 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_have_getopt_optreset="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_getopt_optreset="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_getopt_optreset" >&5
-echo "${ECHO_T}$ac_cv_have_getopt_optreset" >&6; }
-if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_GETOPT_OPTRESET 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking if libc defines sys_errlist" >&5
-echo $ECHO_N "checking if libc defines sys_errlist... $ECHO_C" >&6; }
-if test "${ac_cv_libc_defines_sys_errlist+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
- extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_libc_defines_sys_errlist="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_libc_defines_sys_errlist="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_libc_defines_sys_errlist" >&5
-echo "${ECHO_T}$ac_cv_libc_defines_sys_errlist" >&6; }
-if test "x$ac_cv_libc_defines_sys_errlist" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_SYS_ERRLIST 1
-_ACEOF
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking if libc defines sys_nerr" >&5
-echo $ECHO_N "checking if libc defines sys_nerr... $ECHO_C" >&6; }
-if test "${ac_cv_libc_defines_sys_nerr+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
- extern int sys_nerr; printf("%i", sys_nerr);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_libc_defines_sys_nerr="yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_libc_defines_sys_nerr="no"
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_libc_defines_sys_nerr" >&5
-echo "${ECHO_T}$ac_cv_libc_defines_sys_nerr" >&6; }
-if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_SYS_NERR 1
-_ACEOF
-
-fi
-
-# Check libraries needed by DNS fingerprint support
-{ echo "$as_me:$LINENO: checking for library containing getrrsetbyname" >&5
-echo $ECHO_N "checking for library containing getrrsetbyname... $ECHO_C" >&6; }
-if test "${ac_cv_search_getrrsetbyname+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getrrsetbyname ();
-int
-main ()
-{
-return getrrsetbyname ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' resolv; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_getrrsetbyname=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_getrrsetbyname+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_getrrsetbyname+set}" = set; then
- :
-else
- ac_cv_search_getrrsetbyname=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_getrrsetbyname" >&5
-echo "${ECHO_T}$ac_cv_search_getrrsetbyname" >&6; }
-ac_res=$ac_cv_search_getrrsetbyname
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_GETRRSETBYNAME 1
-_ACEOF
-
-else
-
- # Needed by our getrrsetbyname()
- { echo "$as_me:$LINENO: checking for library containing res_query" >&5
-echo $ECHO_N "checking for library containing res_query... $ECHO_C" >&6; }
-if test "${ac_cv_search_res_query+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char res_query ();
-int
-main ()
-{
-return res_query ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' resolv; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_res_query=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_res_query+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_res_query+set}" = set; then
- :
-else
- ac_cv_search_res_query=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_res_query" >&5
-echo "${ECHO_T}$ac_cv_search_res_query" >&6; }
-ac_res=$ac_cv_search_res_query
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
- { echo "$as_me:$LINENO: checking for library containing dn_expand" >&5
-echo $ECHO_N "checking for library containing dn_expand... $ECHO_C" >&6; }
-if test "${ac_cv_search_dn_expand+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dn_expand ();
-int
-main ()
-{
-return dn_expand ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' resolv; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_dn_expand=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_dn_expand+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_dn_expand+set}" = set; then
- :
-else
- ac_cv_search_dn_expand=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_dn_expand" >&5
-echo "${ECHO_T}$ac_cv_search_dn_expand" >&6; }
-ac_res=$ac_cv_search_dn_expand
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
- { echo "$as_me:$LINENO: checking if res_query will link" >&5
-echo $ECHO_N "checking if res_query will link... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <netdb.h>
-#include <resolv.h>
-
-int
-main ()
-{
-
- res_query (0, 0, 0, 0, 0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- saved_LIBS="$LIBS"
- LIBS="$LIBS -lresolv"
- { echo "$as_me:$LINENO: checking for res_query in -lresolv" >&5
-echo $ECHO_N "checking for res_query in -lresolv... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <netdb.h>
-#include <resolv.h>
-
-int
-main ()
-{
-
- res_query (0, 0, 0, 0, 0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- LIBS="$saved_LIBS"
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-
-for ac_func in _getshort _getlong
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
- { echo "$as_me:$LINENO: checking whether _getshort is declared" >&5
-echo $ECHO_N "checking whether _getshort is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl__getshort+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
- #include <arpa/nameser.h>
-
-int
-main ()
-{
-#ifndef _getshort
- (void) _getshort;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl__getshort=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl__getshort=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl__getshort" >&5
-echo "${ECHO_T}$ac_cv_have_decl__getshort" >&6; }
-if test $ac_cv_have_decl__getshort = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL__GETSHORT 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL__GETSHORT 0
-_ACEOF
-
-
-fi
-{ echo "$as_me:$LINENO: checking whether _getlong is declared" >&5
-echo $ECHO_N "checking whether _getlong is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl__getlong+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
- #include <arpa/nameser.h>
-
-int
-main ()
-{
-#ifndef _getlong
- (void) _getlong;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl__getlong=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl__getlong=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl__getlong" >&5
-echo "${ECHO_T}$ac_cv_have_decl__getlong" >&6; }
-if test $ac_cv_have_decl__getlong = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL__GETLONG 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL__GETLONG 0
-_ACEOF
-
-
-fi
-
-
- { echo "$as_me:$LINENO: checking for HEADER.ad" >&5
-echo $ECHO_N "checking for HEADER.ad... $ECHO_C" >&6; }
-if test "${ac_cv_member_HEADER_ad+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <arpa/nameser.h>
-
-int
-main ()
-{
-static HEADER ac_aggr;
-if (ac_aggr.ad)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_HEADER_ad=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <arpa/nameser.h>
-
-int
-main ()
-{
-static HEADER ac_aggr;
-if (sizeof ac_aggr.ad)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_HEADER_ad=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_member_HEADER_ad=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_member_HEADER_ad" >&5
-echo "${ECHO_T}$ac_cv_member_HEADER_ad" >&6; }
-if test $ac_cv_member_HEADER_ad = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_HEADER_AD 1
-_ACEOF
-
-fi
-
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking if struct __res_state _res is an extern" >&5
-echo $ECHO_N "checking if struct __res_state _res is an extern... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-extern struct __res_state _res;
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE__RES_EXTERN 1
-_ACEOF
-
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-
-# Check whether user wants SELinux support
-SELINUX_MSG="no"
-LIBSELINUX=""
-
-# Check whether --with-selinux was given.
-if test "${with_selinux+set}" = set; then
- withval=$with_selinux; if test "x$withval" != "xno" ; then
- save_LIBS="$LIBS"
-
-cat >>confdefs.h <<\_ACEOF
-#define WITH_SELINUX 1
-_ACEOF
-
- SELINUX_MSG="yes"
- if test "${ac_cv_header_selinux_selinux_h+set}" = set; then
- { echo "$as_me:$LINENO: checking for selinux/selinux.h" >&5
-echo $ECHO_N "checking for selinux/selinux.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_selinux_selinux_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_selinux_selinux_h" >&5
-echo "${ECHO_T}$ac_cv_header_selinux_selinux_h" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking selinux/selinux.h usability" >&5
-echo $ECHO_N "checking selinux/selinux.h usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <selinux/selinux.h>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking selinux/selinux.h presence" >&5
-echo $ECHO_N "checking selinux/selinux.h presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <selinux/selinux.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: selinux/selinux.h: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: selinux/selinux.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: selinux/selinux.h: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: selinux/selinux.h: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: selinux/selinux.h: present but cannot be compiled" >&5
-echo "$as_me: WARNING: selinux/selinux.h: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: selinux/selinux.h: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: selinux/selinux.h: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: selinux/selinux.h: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: selinux/selinux.h: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: selinux/selinux.h: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: selinux/selinux.h: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: selinux/selinux.h: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: selinux/selinux.h: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: selinux/selinux.h: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: selinux/selinux.h: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for selinux/selinux.h" >&5
-echo $ECHO_N "checking for selinux/selinux.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_selinux_selinux_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_header_selinux_selinux_h=$ac_header_preproc
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_selinux_selinux_h" >&5
-echo "${ECHO_T}$ac_cv_header_selinux_selinux_h" >&6; }
-
-fi
-if test $ac_cv_header_selinux_selinux_h = yes; then
- :
-else
- { { echo "$as_me:$LINENO: error: SELinux support requires selinux.h header" >&5
-echo "$as_me: error: SELinux support requires selinux.h header" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-
- { echo "$as_me:$LINENO: checking for setexeccon in -lselinux" >&5
-echo $ECHO_N "checking for setexeccon in -lselinux... $ECHO_C" >&6; }
-if test "${ac_cv_lib_selinux_setexeccon+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lselinux $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char setexeccon ();
-int
-main ()
-{
-return setexeccon ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_selinux_setexeccon=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_selinux_setexeccon=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_selinux_setexeccon" >&5
-echo "${ECHO_T}$ac_cv_lib_selinux_setexeccon" >&6; }
-if test $ac_cv_lib_selinux_setexeccon = yes; then
- LIBSELINUX="-lselinux"
- LIBS="$LIBS -lselinux"
-
-else
- { { echo "$as_me:$LINENO: error: SELinux support requires libselinux library" >&5
-echo "$as_me: error: SELinux support requires libselinux library" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
- SSHLIBS="$SSHLIBS $LIBSELINUX"
- SSHDLIBS="$SSHDLIBS $LIBSELINUX"
-
-
-for ac_func in getseuserbyname get_default_context_with_level
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
- LIBS="$save_LIBS"
- fi
-
-fi
-
-
-
-
-# Check whether user wants Kerberos 5 support
-KRB5_MSG="no"
-
-# Check whether --with-kerberos5 was given.
-if test "${with_kerberos5+set}" = set; then
- withval=$with_kerberos5; if test "x$withval" != "xno" ; then
- if test "x$withval" = "xyes" ; then
- KRB5ROOT="/usr/local"
- else
- KRB5ROOT=${withval}
- fi
-
-
-cat >>confdefs.h <<\_ACEOF
-#define KRB5 1
-_ACEOF
-
- KRB5_MSG="yes"
-
- # Extract the first word of "krb5-config", so it can be a program name with args.
-set dummy krb5-config; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_KRB5CONF+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $KRB5CONF in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_KRB5CONF="$KRB5CONF" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-as_dummy="$KRB5ROOT/bin:$PATH"
-for as_dir in $as_dummy
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_KRB5CONF="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- test -z "$ac_cv_path_KRB5CONF" && ac_cv_path_KRB5CONF="$KRB5ROOT/bin/krb5-config"
- ;;
-esac
-fi
-KRB5CONF=$ac_cv_path_KRB5CONF
-if test -n "$KRB5CONF"; then
- { echo "$as_me:$LINENO: result: $KRB5CONF" >&5
-echo "${ECHO_T}$KRB5CONF" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- if test -x $KRB5CONF ; then
- K5CFLAGS="`$KRB5CONF --cflags`"
- K5LIBS="`$KRB5CONF --libs`"
- CPPFLAGS="$CPPFLAGS $K5CFLAGS"
-
- { echo "$as_me:$LINENO: checking for gssapi support" >&5
-echo $ECHO_N "checking for gssapi support... $ECHO_C" >&6; }
- if $KRB5CONF | grep gssapi >/dev/null ; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define GSSAPI 1
-_ACEOF
-
- GSSCFLAGS="`$KRB5CONF --cflags gssapi`"
- GSSLIBS="`$KRB5CONF --libs gssapi`"
- CPPFLAGS="$CPPFLAGS $GSSCFLAGS"
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
- { echo "$as_me:$LINENO: checking whether we are using Heimdal" >&5
-echo $ECHO_N "checking whether we are using Heimdal... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <krb5.h>
-
-int
-main ()
-{
- char *tmp = heimdal_version;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define HEIMDAL 1
-_ACEOF
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- else
- CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include"
- LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib"
- { echo "$as_me:$LINENO: checking whether we are using Heimdal" >&5
-echo $ECHO_N "checking whether we are using Heimdal... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
- #include <krb5.h>
-
-int
-main ()
-{
- char *tmp = heimdal_version;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- cat >>confdefs.h <<\_ACEOF
-#define HEIMDAL 1
-_ACEOF
-
- K5LIBS="-lkrb5"
- K5LIBS="$K5LIBS -lcom_err -lasn1"
- { echo "$as_me:$LINENO: checking for net_write in -lroken" >&5
-echo $ECHO_N "checking for net_write in -lroken... $ECHO_C" >&6; }
-if test "${ac_cv_lib_roken_net_write+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lroken $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char net_write ();
-int
-main ()
-{
-return net_write ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_roken_net_write=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_roken_net_write=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_roken_net_write" >&5
-echo "${ECHO_T}$ac_cv_lib_roken_net_write" >&6; }
-if test $ac_cv_lib_roken_net_write = yes; then
- K5LIBS="$K5LIBS -lroken"
-fi
-
- { echo "$as_me:$LINENO: checking for des_cbc_encrypt in -ldes" >&5
-echo $ECHO_N "checking for des_cbc_encrypt in -ldes... $ECHO_C" >&6; }
-if test "${ac_cv_lib_des_des_cbc_encrypt+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldes $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char des_cbc_encrypt ();
-int
-main ()
-{
-return des_cbc_encrypt ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_des_des_cbc_encrypt=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_des_des_cbc_encrypt=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_des_des_cbc_encrypt" >&5
-echo "${ECHO_T}$ac_cv_lib_des_des_cbc_encrypt" >&6; }
-if test $ac_cv_lib_des_des_cbc_encrypt = yes; then
- K5LIBS="$K5LIBS -ldes"
-fi
-
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- K5LIBS="-lkrb5 -lk5crypto -lcom_err"
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- { echo "$as_me:$LINENO: checking for library containing dn_expand" >&5
-echo $ECHO_N "checking for library containing dn_expand... $ECHO_C" >&6; }
-if test "${ac_cv_search_dn_expand+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dn_expand ();
-int
-main ()
-{
-return dn_expand ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' resolv; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_dn_expand=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_dn_expand+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_dn_expand+set}" = set; then
- :
-else
- ac_cv_search_dn_expand=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_dn_expand" >&5
-echo "${ECHO_T}$ac_cv_search_dn_expand" >&6; }
-ac_res=$ac_cv_search_dn_expand
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-
- { echo "$as_me:$LINENO: checking for gss_init_sec_context in -lgssapi_krb5" >&5
-echo $ECHO_N "checking for gss_init_sec_context in -lgssapi_krb5... $ECHO_C" >&6; }
-if test "${ac_cv_lib_gssapi_krb5_gss_init_sec_context+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lgssapi_krb5 $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char gss_init_sec_context ();
-int
-main ()
-{
-return gss_init_sec_context ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_gssapi_krb5_gss_init_sec_context=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_gssapi_krb5_gss_init_sec_context=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_gssapi_krb5_gss_init_sec_context" >&5
-echo "${ECHO_T}$ac_cv_lib_gssapi_krb5_gss_init_sec_context" >&6; }
-if test $ac_cv_lib_gssapi_krb5_gss_init_sec_context = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define GSSAPI 1
-_ACEOF
-
- GSSLIBS="-lgssapi_krb5"
-else
- { echo "$as_me:$LINENO: checking for gss_init_sec_context in -lgssapi" >&5
-echo $ECHO_N "checking for gss_init_sec_context in -lgssapi... $ECHO_C" >&6; }
-if test "${ac_cv_lib_gssapi_gss_init_sec_context+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lgssapi $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char gss_init_sec_context ();
-int
-main ()
-{
-return gss_init_sec_context ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_gssapi_gss_init_sec_context=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_gssapi_gss_init_sec_context=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_gssapi_gss_init_sec_context" >&5
-echo "${ECHO_T}$ac_cv_lib_gssapi_gss_init_sec_context" >&6; }
-if test $ac_cv_lib_gssapi_gss_init_sec_context = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define GSSAPI 1
-_ACEOF
-
- GSSLIBS="-lgssapi"
-else
- { echo "$as_me:$LINENO: checking for gss_init_sec_context in -lgss" >&5
-echo $ECHO_N "checking for gss_init_sec_context in -lgss... $ECHO_C" >&6; }
-if test "${ac_cv_lib_gss_gss_init_sec_context+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lgss $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char gss_init_sec_context ();
-int
-main ()
-{
-return gss_init_sec_context ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_gss_gss_init_sec_context=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_gss_gss_init_sec_context=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_gss_gss_init_sec_context" >&5
-echo "${ECHO_T}$ac_cv_lib_gss_gss_init_sec_context" >&6; }
-if test $ac_cv_lib_gss_gss_init_sec_context = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define GSSAPI 1
-_ACEOF
-
- GSSLIBS="-lgss"
-else
- { echo "$as_me:$LINENO: WARNING: Cannot find any suitable gss-api library - build may fail" >&5
-echo "$as_me: WARNING: Cannot find any suitable gss-api library - build may fail" >&2;}
-fi
-
-
-fi
-
-
-fi
-
-
- if test "${ac_cv_header_gssapi_h+set}" = set; then
- { echo "$as_me:$LINENO: checking for gssapi.h" >&5
-echo $ECHO_N "checking for gssapi.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_gssapi_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_gssapi_h" >&5
-echo "${ECHO_T}$ac_cv_header_gssapi_h" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking gssapi.h usability" >&5
-echo $ECHO_N "checking gssapi.h usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <gssapi.h>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking gssapi.h presence" >&5
-echo $ECHO_N "checking gssapi.h presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <gssapi.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: gssapi.h: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: gssapi.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: gssapi.h: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: gssapi.h: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: gssapi.h: present but cannot be compiled" >&5
-echo "$as_me: WARNING: gssapi.h: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: gssapi.h: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: gssapi.h: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: gssapi.h: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: gssapi.h: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: gssapi.h: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: gssapi.h: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: gssapi.h: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: gssapi.h: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: gssapi.h: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: gssapi.h: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for gssapi.h" >&5
-echo $ECHO_N "checking for gssapi.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_gssapi_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_header_gssapi_h=$ac_header_preproc
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_gssapi_h" >&5
-echo "${ECHO_T}$ac_cv_header_gssapi_h" >&6; }
-
-fi
-if test $ac_cv_header_gssapi_h = yes; then
- :
-else
- unset ac_cv_header_gssapi_h
- CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
-
-for ac_header in gssapi.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-else
- { echo "$as_me:$LINENO: WARNING: Cannot find any suitable gss-api header - build may fail" >&5
-echo "$as_me: WARNING: Cannot find any suitable gss-api header - build may fail" >&2;}
-
-fi
-
-done
-
-
-
-fi
-
-
-
- oldCPP="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
- if test "${ac_cv_header_gssapi_krb5_h+set}" = set; then
- { echo "$as_me:$LINENO: checking for gssapi_krb5.h" >&5
-echo $ECHO_N "checking for gssapi_krb5.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_gssapi_krb5_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_gssapi_krb5_h" >&5
-echo "${ECHO_T}$ac_cv_header_gssapi_krb5_h" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking gssapi_krb5.h usability" >&5
-echo $ECHO_N "checking gssapi_krb5.h usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <gssapi_krb5.h>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking gssapi_krb5.h presence" >&5
-echo $ECHO_N "checking gssapi_krb5.h presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <gssapi_krb5.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: gssapi_krb5.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: gssapi_krb5.h: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: present but cannot be compiled" >&5
-echo "$as_me: WARNING: gssapi_krb5.h: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: gssapi_krb5.h: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: gssapi_krb5.h: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: gssapi_krb5.h: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: gssapi_krb5.h: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: gssapi_krb5.h: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for gssapi_krb5.h" >&5
-echo $ECHO_N "checking for gssapi_krb5.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_gssapi_krb5_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_header_gssapi_krb5_h=$ac_header_preproc
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_gssapi_krb5_h" >&5
-echo "${ECHO_T}$ac_cv_header_gssapi_krb5_h" >&6; }
-
-fi
-if test $ac_cv_header_gssapi_krb5_h = yes; then
- :
-else
- CPPFLAGS="$oldCPP"
-fi
-
-
-
- fi
- if test ! -z "$need_dash_r" ; then
- LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib"
- fi
- if test ! -z "$blibpath" ; then
- blibpath="$blibpath:${KRB5ROOT}/lib"
- fi
-
-
-
-for ac_header in gssapi.h gssapi/gssapi.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-
-for ac_header in gssapi_krb5.h gssapi/gssapi_krb5.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-
-for ac_header in gssapi_generic.h gssapi/gssapi_generic.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
- # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- ( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to openssh-unix-dev@mindrot.org ##
-## ------------------------------------------- ##
-_ASBOX
- ) | sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
- { echo "$as_me:$LINENO: checking for library containing k_hasafs" >&5
-echo $ECHO_N "checking for library containing k_hasafs... $ECHO_C" >&6; }
-if test "${ac_cv_search_k_hasafs+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char k_hasafs ();
-int
-main ()
-{
-return k_hasafs ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' kafs; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_search_k_hasafs=$ac_res
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_k_hasafs+set}" = set; then
- break
-fi
-done
-if test "${ac_cv_search_k_hasafs+set}" = set; then
- :
-else
- ac_cv_search_k_hasafs=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_k_hasafs" >&5
-echo "${ECHO_T}$ac_cv_search_k_hasafs" >&6; }
-ac_res=$ac_cv_search_k_hasafs
-if test "$ac_res" != no; then
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_AFS 1
-_ACEOF
-
-fi
-
-
- { echo "$as_me:$LINENO: checking whether GSS_C_NT_HOSTBASED_SERVICE is declared" >&5
-echo $ECHO_N "checking whether GSS_C_NT_HOSTBASED_SERVICE is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#ifdef HAVE_GSSAPI_H
-# include <gssapi.h>
-#elif defined(HAVE_GSSAPI_GSSAPI_H)
-# include <gssapi/gssapi.h>
-#endif
-
-#ifdef HAVE_GSSAPI_GENERIC_H
-# include <gssapi_generic.h>
-#elif defined(HAVE_GSSAPI_GSSAPI_GENERIC_H)
-# include <gssapi/gssapi_generic.h>
-#endif
-
-
-int
-main ()
-{
-#ifndef GSS_C_NT_HOSTBASED_SERVICE
- (void) GSS_C_NT_HOSTBASED_SERVICE;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE" >&5
-echo "${ECHO_T}$ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE" >&6; }
-if test $ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_GSS_C_NT_HOSTBASED_SERVICE 1
-_ACEOF
-
-
-else
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_GSS_C_NT_HOSTBASED_SERVICE 0
-_ACEOF
-
-
-fi
-
-
- saved_LIBS="$LIBS"
- LIBS="$LIBS $K5LIBS"
-
-
-
-for ac_func in krb5_cc_new_unique krb5_get_error_message krb5_free_error_message
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
- { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
- LIBS="$saved_LIBS"
-
- fi
-
-
-fi
-
-
-
-
-# Looking for programs, paths and files
-
-PRIVSEP_PATH=/var/empty
-
-# Check whether --with-privsep-path was given.
-if test "${with_privsep_path+set}" = set; then
- withval=$with_privsep_path;
- if test -n "$withval" && test "x$withval" != "xno" && \
- test "x${withval}" != "xyes"; then
- PRIVSEP_PATH=$withval
- fi
-
-
-fi
-
-
-
-
-# Check whether --with-xauth was given.
-if test "${with_xauth+set}" = set; then
- withval=$with_xauth;
- if test -n "$withval" && test "x$withval" != "xno" && \
- test "x${withval}" != "xyes"; then
- xauth_path=$withval
- fi
-
-else
-
- TestPath="$PATH"
- TestPath="${TestPath}${PATH_SEPARATOR}/usr/X/bin"
- TestPath="${TestPath}${PATH_SEPARATOR}/usr/bin/X11"
- TestPath="${TestPath}${PATH_SEPARATOR}/usr/X11R6/bin"
- TestPath="${TestPath}${PATH_SEPARATOR}/usr/openwin/bin"
- # Extract the first word of "xauth", so it can be a program name with args.
-set dummy xauth; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_xauth_path+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $xauth_path in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_xauth_path="$xauth_path" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $TestPath
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_xauth_path="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-xauth_path=$ac_cv_path_xauth_path
-if test -n "$xauth_path"; then
- { echo "$as_me:$LINENO: result: $xauth_path" >&5
-echo "${ECHO_T}$xauth_path" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- if (test ! -z "$xauth_path" && test -x "/usr/openwin/bin/xauth") ; then
- xauth_path="/usr/openwin/bin/xauth"
- fi
-
-
-fi
-
-
-STRIP_OPT=-s
-# Check whether --enable-strip was given.
-if test "${enable_strip+set}" = set; then
- enableval=$enable_strip;
- if test "x$enableval" = "xno" ; then
- STRIP_OPT=
- fi
-
-
-fi
-
-
-
-if test -z "$xauth_path" ; then
- XAUTH_PATH="undefined"
-
-else
-
-cat >>confdefs.h <<_ACEOF
-#define XAUTH_PATH "$xauth_path"
-_ACEOF
-
- XAUTH_PATH=$xauth_path
-
-fi
-
-# Check for mail directory
-
-# Check whether --with-maildir was given.
-if test "${with_maildir+set}" = set; then
- withval=$with_maildir;
- if test "X$withval" != X && test "x$withval" != xno && \
- test "x${withval}" != xyes; then
-
-cat >>confdefs.h <<_ACEOF
-#define MAIL_DIRECTORY "$withval"
-_ACEOF
-
- fi
-
-else
-
- if test "X$maildir" != "X"; then
- cat >>confdefs.h <<_ACEOF
-#define MAIL_DIRECTORY "$maildir"
-_ACEOF
-
- else
- { echo "$as_me:$LINENO: checking Discovering system mail directory" >&5
-echo $ECHO_N "checking Discovering system mail directory... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
-
- { echo "$as_me:$LINENO: WARNING: cross compiling: use --with-maildir=/path/to/mail" >&5
-echo "$as_me: WARNING: cross compiling: use --with-maildir=/path/to/mail" >&2;}
-
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_PATHS_H
-#include <paths.h>
-#endif
-#ifdef HAVE_MAILLOCK_H
-#include <maillock.h>
-#endif
-#define DATA "conftest.maildir"
-
-int
-main ()
-{
-
- FILE *fd;
- int rc;
-
- fd = fopen(DATA,"w");
- if(fd == NULL)
- exit(1);
-
-#if defined (_PATH_MAILDIR)
- if ((rc = fprintf(fd ,"_PATH_MAILDIR:%s\n", _PATH_MAILDIR)) <0)
- exit(1);
-#elif defined (MAILDIR)
- if ((rc = fprintf(fd ,"MAILDIR:%s\n", MAILDIR)) <0)
- exit(1);
-#elif defined (_PATH_MAIL)
- if ((rc = fprintf(fd ,"_PATH_MAIL:%s\n", _PATH_MAIL)) <0)
- exit(1);
-#else
- exit (2);
-#endif
-
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
- maildir_what=`awk -F: '{print $1}' conftest.maildir`
- maildir=`awk -F: '{print $2}' conftest.maildir \
- | sed 's|/$||'`
- { echo "$as_me:$LINENO: result: Using: $maildir from $maildir_what" >&5
-echo "${ECHO_T}Using: $maildir from $maildir_what" >&6; }
- if test "x$maildir_what" != "x_PATH_MAILDIR"; then
- cat >>confdefs.h <<_ACEOF
-#define MAIL_DIRECTORY "$maildir"
-_ACEOF
-
- fi
-
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
- if test "X$ac_status" = "X2";then
-# our test program didn't find it. Default to /var/spool/mail
- { echo "$as_me:$LINENO: result: Using: default value of /var/spool/mail" >&5
-echo "${ECHO_T}Using: default value of /var/spool/mail" >&6; }
- cat >>confdefs.h <<_ACEOF
-#define MAIL_DIRECTORY "/var/spool/mail"
-_ACEOF
-
- else
- { echo "$as_me:$LINENO: result: *** not found ***" >&5
-echo "${ECHO_T}*** not found ***" >&6; }
- fi
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
- fi
-
-
-fi
- # maildir
-
-if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then
- { echo "$as_me:$LINENO: WARNING: cross compiling: Disabling /dev/ptmx test" >&5
-echo "$as_me: WARNING: cross compiling: Disabling /dev/ptmx test" >&2;}
- disable_ptmx_check=yes
-fi
-if test -z "$no_dev_ptmx" ; then
- if test "x$disable_ptmx_check" != "xyes" ; then
- { echo "$as_me:$LINENO: checking for \"/dev/ptmx\"" >&5
-echo $ECHO_N "checking for \"/dev/ptmx\"... $ECHO_C" >&6; }
-if test "${ac_cv_file___dev_ptmx_+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- test "$cross_compiling" = yes &&
- { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
-echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
- { (exit 1); exit 1; }; }
-if test -r ""/dev/ptmx""; then
- ac_cv_file___dev_ptmx_=yes
-else
- ac_cv_file___dev_ptmx_=no
-fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_file___dev_ptmx_" >&5
-echo "${ECHO_T}$ac_cv_file___dev_ptmx_" >&6; }
-if test $ac_cv_file___dev_ptmx_ = yes; then
-
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DEV_PTMX 1
-_ACEOF
-
- have_dev_ptmx=1
-
-
-fi
-
- fi
-fi
-
-if test ! -z "$cross_compiling" && test "x$cross_compiling" != "xyes"; then
- { echo "$as_me:$LINENO: checking for \"/dev/ptc\"" >&5
-echo $ECHO_N "checking for \"/dev/ptc\"... $ECHO_C" >&6; }
-if test "${ac_cv_file___dev_ptc_+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- test "$cross_compiling" = yes &&
- { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
-echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
- { (exit 1); exit 1; }; }
-if test -r ""/dev/ptc""; then
- ac_cv_file___dev_ptc_=yes
-else
- ac_cv_file___dev_ptc_=no
-fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_file___dev_ptc_" >&5
-echo "${ECHO_T}$ac_cv_file___dev_ptc_" >&6; }
-if test $ac_cv_file___dev_ptc_ = yes; then
-
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DEV_PTS_AND_PTC 1
-_ACEOF
-
- have_dev_ptc=1
-
-
-fi
-
-else
- { echo "$as_me:$LINENO: WARNING: cross compiling: Disabling /dev/ptc test" >&5
-echo "$as_me: WARNING: cross compiling: Disabling /dev/ptc test" >&2;}
-fi
-
-# Options from here on. Some of these are preset by platform above
-
-# Check whether --with-mantype was given.
-if test "${with_mantype+set}" = set; then
- withval=$with_mantype;
- case "$withval" in
- man|cat|doc)
- MANTYPE=$withval
- ;;
- *)
- { { echo "$as_me:$LINENO: error: invalid man type: $withval" >&5
-echo "$as_me: error: invalid man type: $withval" >&2;}
- { (exit 1); exit 1; }; }
- ;;
- esac
-
-
-fi
-
-if test -z "$MANTYPE"; then
- TestPath="/usr/bin${PATH_SEPARATOR}/usr/ucb"
- for ac_prog in nroff awf
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_NROFF+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $NROFF in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_NROFF="$NROFF" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $TestPath
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_NROFF="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-NROFF=$ac_cv_path_NROFF
-if test -n "$NROFF"; then
- { echo "$as_me:$LINENO: result: $NROFF" >&5
-echo "${ECHO_T}$NROFF" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- test -n "$NROFF" && break
-done
-test -n "$NROFF" || NROFF="/bin/false"
-
- if ${NROFF} -mdoc ${srcdir}/ssh.1 >/dev/null 2>&1; then
- MANTYPE=doc
- elif ${NROFF} -man ${srcdir}/ssh.1 >/dev/null 2>&1; then
- MANTYPE=man
- else
- MANTYPE=cat
- fi
-fi
-
-if test "$MANTYPE" = "doc"; then
- mansubdir=man;
-else
- mansubdir=$MANTYPE;
-fi
-
-
-# Check whether to enable MD5 passwords
-MD5_MSG="no"
-
-# Check whether --with-md5-passwords was given.
-if test "${with_md5_passwords+set}" = set; then
- withval=$with_md5_passwords;
- if test "x$withval" != "xno" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_MD5_PASSWORDS 1
-_ACEOF
-
- MD5_MSG="yes"
- fi
-
-
-fi
-
-
-# Whether to disable shadow password support
-
-# Check whether --with-shadow was given.
-if test "${with_shadow+set}" = set; then
- withval=$with_shadow;
- if test "x$withval" = "xno" ; then
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_SHADOW 1
-_ACEOF
-
- disable_shadow=yes
- fi
-
-
-fi
-
-
-if test -z "$disable_shadow" ; then
- { echo "$as_me:$LINENO: checking if the systems has expire shadow information" >&5
-echo $ECHO_N "checking if the systems has expire shadow information... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <shadow.h>
-struct spwd sp;
-
-int
-main ()
-{
- sp.sp_expire = sp.sp_lstchg = sp.sp_inact = 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- sp_expire_available=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
- if test "x$sp_expire_available" = "xyes" ; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define HAS_SHADOW_EXPIRE 1
-_ACEOF
-
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-fi
-
-# Use ip address instead of hostname in $DISPLAY
-if test ! -z "$IPADDR_IN_DISPLAY" ; then
- DISPLAY_HACK_MSG="yes"
-
-cat >>confdefs.h <<\_ACEOF
-#define IPADDR_IN_DISPLAY 1
-_ACEOF
-
-else
- DISPLAY_HACK_MSG="no"
-
-# Check whether --with-ipaddr-display was given.
-if test "${with_ipaddr_display+set}" = set; then
- withval=$with_ipaddr_display;
- if test "x$withval" != "xno" ; then
- cat >>confdefs.h <<\_ACEOF
-#define IPADDR_IN_DISPLAY 1
-_ACEOF
-
- DISPLAY_HACK_MSG="yes"
- fi
-
-
-fi
-
-fi
-
-# check for /etc/default/login and use it if present.
-# Check whether --enable-etc-default-login was given.
-if test "${enable_etc_default_login+set}" = set; then
- enableval=$enable_etc_default_login; if test "x$enableval" = "xno"; then
- { echo "$as_me:$LINENO: /etc/default/login handling disabled" >&5
-echo "$as_me: /etc/default/login handling disabled" >&6;}
- etc_default_login=no
- else
- etc_default_login=yes
- fi
-else
- if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes";
- then
- { echo "$as_me:$LINENO: WARNING: cross compiling: not checking /etc/default/login" >&5
-echo "$as_me: WARNING: cross compiling: not checking /etc/default/login" >&2;}
- etc_default_login=no
- else
- etc_default_login=yes
- fi
-
-fi
-
-
-if test "x$etc_default_login" != "xno"; then
- { echo "$as_me:$LINENO: checking for \"/etc/default/login\"" >&5
-echo $ECHO_N "checking for \"/etc/default/login\"... $ECHO_C" >&6; }
-if test "${ac_cv_file___etc_default_login_+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- test "$cross_compiling" = yes &&
- { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
-echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
- { (exit 1); exit 1; }; }
-if test -r ""/etc/default/login""; then
- ac_cv_file___etc_default_login_=yes
-else
- ac_cv_file___etc_default_login_=no
-fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_file___etc_default_login_" >&5
-echo "${ECHO_T}$ac_cv_file___etc_default_login_" >&6; }
-if test $ac_cv_file___etc_default_login_ = yes; then
- external_path_file=/etc/default/login
-fi
-
- if test "x$external_path_file" = "x/etc/default/login"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ETC_DEFAULT_LOGIN 1
-_ACEOF
-
- fi
-fi
-
-if test $ac_cv_func_login_getcapbool = "yes" && \
- test $ac_cv_header_login_cap_h = "yes" ; then
- external_path_file=/etc/login.conf
-fi
-
-# Whether to mess with the default path
-SERVER_PATH_MSG="(default)"
-
-# Check whether --with-default-path was given.
-if test "${with_default_path+set}" = set; then
- withval=$with_default_path;
- if test "x$external_path_file" = "x/etc/login.conf" ; then
- { echo "$as_me:$LINENO: WARNING:
---with-default-path=PATH has no effect on this system.
-Edit /etc/login.conf instead." >&5
-echo "$as_me: WARNING:
---with-default-path=PATH has no effect on this system.
-Edit /etc/login.conf instead." >&2;}
- elif test "x$withval" != "xno" ; then
- if test ! -z "$external_path_file" ; then
- { echo "$as_me:$LINENO: WARNING:
---with-default-path=PATH will only be used if PATH is not defined in
-$external_path_file ." >&5
-echo "$as_me: WARNING:
---with-default-path=PATH will only be used if PATH is not defined in
-$external_path_file ." >&2;}
- fi
- user_path="$withval"
- SERVER_PATH_MSG="$withval"
- fi
-
-else
- if test "x$external_path_file" = "x/etc/login.conf" ; then
- { echo "$as_me:$LINENO: WARNING: Make sure the path to scp is in /etc/login.conf" >&5
-echo "$as_me: WARNING: Make sure the path to scp is in /etc/login.conf" >&2;}
- else
- if test ! -z "$external_path_file" ; then
- { echo "$as_me:$LINENO: WARNING:
-If PATH is defined in $external_path_file, ensure the path to scp is included,
-otherwise scp will not work." >&5
-echo "$as_me: WARNING:
-If PATH is defined in $external_path_file, ensure the path to scp is included,
-otherwise scp will not work." >&2;}
- fi
- if test "$cross_compiling" = yes; then
- user_path="/usr/bin:/bin:/usr/sbin:/sbin"
-
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* find out what STDPATH is */
-#include <stdio.h>
-#ifdef HAVE_PATHS_H
-# include <paths.h>
-#endif
-#ifndef _PATH_STDPATH
-# ifdef _PATH_USERPATH /* Irix */
-# define _PATH_STDPATH _PATH_USERPATH
-# else
-# define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"
-# endif
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#define DATA "conftest.stdpath"
-
-int
-main ()
-{
-
- FILE *fd;
- int rc;
-
- fd = fopen(DATA,"w");
- if(fd == NULL)
- exit(1);
-
- if ((rc = fprintf(fd,"%s", _PATH_STDPATH)) < 0)
- exit(1);
-
- exit(0);
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- user_path=`cat conftest.stdpath`
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
- user_path="/usr/bin:/bin:/usr/sbin:/sbin"
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-# make sure $bindir is in USER_PATH so scp will work
- t_bindir="${bindir}"
- while echo "${t_bindir}" | egrep '\$\{|NONE/' >/dev/null 2>&1; do
- t_bindir=`eval echo ${t_bindir}`
- case $t_bindir in
- NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$prefix~"` ;;
- esac
- case $t_bindir in
- NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$ac_default_prefix~"` ;;
- esac
- done
- echo $user_path | grep ":$t_bindir" > /dev/null 2>&1
- if test $? -ne 0 ; then
- echo $user_path | grep "^$t_bindir" > /dev/null 2>&1
- if test $? -ne 0 ; then
- user_path=$user_path:$t_bindir
- { echo "$as_me:$LINENO: result: Adding $t_bindir to USER_PATH so scp will work" >&5
-echo "${ECHO_T}Adding $t_bindir to USER_PATH so scp will work" >&6; }
- fi
- fi
- fi
-
-fi
-
-if test "x$external_path_file" != "x/etc/login.conf" ; then
-
-cat >>confdefs.h <<_ACEOF
-#define USER_PATH "$user_path"
-_ACEOF
-
-
-fi
-
-# Set superuser path separately to user path
-
-# Check whether --with-superuser-path was given.
-if test "${with_superuser_path+set}" = set; then
- withval=$with_superuser_path;
- if test -n "$withval" && test "x$withval" != "xno" && \
- test "x${withval}" != "xyes"; then
-
-cat >>confdefs.h <<_ACEOF
-#define SUPERUSER_PATH "$withval"
-_ACEOF
-
- superuser_path=$withval
- fi
-
-
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking if we need to convert IPv4 in IPv6-mapped addresses" >&5
-echo $ECHO_N "checking if we need to convert IPv4 in IPv6-mapped addresses... $ECHO_C" >&6; }
-IPV4_IN6_HACK_MSG="no"
-
-# Check whether --with-4in6 was given.
-if test "${with_4in6+set}" = set; then
- withval=$with_4in6;
- if test "x$withval" != "xno" ; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define IPV4_IN_IPV6 1
-_ACEOF
-
- IPV4_IN6_HACK_MSG="yes"
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
-
-else
-
- if test "x$inet6_default_4in6" = "xyes"; then
- { echo "$as_me:$LINENO: result: yes (default)" >&5
-echo "${ECHO_T}yes (default)" >&6; }
- cat >>confdefs.h <<\_ACEOF
-#define IPV4_IN_IPV6 1
-_ACEOF
-
- IPV4_IN6_HACK_MSG="yes"
- else
- { echo "$as_me:$LINENO: result: no (default)" >&5
-echo "${ECHO_T}no (default)" >&6; }
- fi
-
-
-fi
-
-
-# Whether to enable BSD auth support
-BSD_AUTH_MSG=no
-
-# Check whether --with-bsd-auth was given.
-if test "${with_bsd_auth+set}" = set; then
- withval=$with_bsd_auth;
- if test "x$withval" != "xno" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define BSD_AUTH 1
-_ACEOF
-
- BSD_AUTH_MSG=yes
- fi
-
-
-fi
-
-
-# Where to place sshd.pid
-piddir=/var/run
-# make sure the directory exists
-if test ! -d $piddir ; then
- piddir=`eval echo ${sysconfdir}`
- case $piddir in
- NONE/*) piddir=`echo $piddir | sed "s~NONE~$ac_default_prefix~"` ;;
- esac
-fi
-
-
-# Check whether --with-pid-dir was given.
-if test "${with_pid_dir+set}" = set; then
- withval=$with_pid_dir;
- if test -n "$withval" && test "x$withval" != "xno" && \
- test "x${withval}" != "xyes"; then
- piddir=$withval
- if test ! -d $piddir ; then
- { echo "$as_me:$LINENO: WARNING: ** no $piddir directory on this system **" >&5
-echo "$as_me: WARNING: ** no $piddir directory on this system **" >&2;}
- fi
- fi
-
-
-fi
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define _PATH_SSH_PIDDIR "$piddir"
-_ACEOF
-
-
-
-# Check whether --enable-lastlog was given.
-if test "${enable_lastlog+set}" = set; then
- enableval=$enable_lastlog;
- if test "x$enableval" = "xno" ; then
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_LASTLOG 1
-_ACEOF
-
- fi
-
-
-fi
-
-# Check whether --enable-utmp was given.
-if test "${enable_utmp+set}" = set; then
- enableval=$enable_utmp;
- if test "x$enableval" = "xno" ; then
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_UTMP 1
-_ACEOF
-
- fi
-
-
-fi
-
-# Check whether --enable-utmpx was given.
-if test "${enable_utmpx+set}" = set; then
- enableval=$enable_utmpx;
- if test "x$enableval" = "xno" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define DISABLE_UTMPX 1
-_ACEOF
-
- fi
-
-
-fi
-
-# Check whether --enable-wtmp was given.
-if test "${enable_wtmp+set}" = set; then
- enableval=$enable_wtmp;
- if test "x$enableval" = "xno" ; then
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_WTMP 1
-_ACEOF
-
- fi
-
-
-fi
-
-# Check whether --enable-wtmpx was given.
-if test "${enable_wtmpx+set}" = set; then
- enableval=$enable_wtmpx;
- if test "x$enableval" = "xno" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define DISABLE_WTMPX 1
-_ACEOF
-
- fi
-
-
-fi
-
-# Check whether --enable-libutil was given.
-if test "${enable_libutil+set}" = set; then
- enableval=$enable_libutil;
- if test "x$enableval" = "xno" ; then
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_LOGIN 1
-_ACEOF
-
- fi
-
-
-fi
-
-# Check whether --enable-pututline was given.
-if test "${enable_pututline+set}" = set; then
- enableval=$enable_pututline;
- if test "x$enableval" = "xno" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define DISABLE_PUTUTLINE 1
-_ACEOF
-
- fi
-
-
-fi
-
-# Check whether --enable-pututxline was given.
-if test "${enable_pututxline+set}" = set; then
- enableval=$enable_pututxline;
- if test "x$enableval" = "xno" ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define DISABLE_PUTUTXLINE 1
-_ACEOF
-
- fi
-
-
-fi
-
-
-# Check whether --with-lastlog was given.
-if test "${with_lastlog+set}" = set; then
- withval=$with_lastlog;
- if test "x$withval" = "xno" ; then
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_LASTLOG 1
-_ACEOF
-
- elif test -n "$withval" && test "x${withval}" != "xyes"; then
- conf_lastlog_location=$withval
- fi
-
-
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking if your system defines LASTLOG_FILE" >&5
-echo $ECHO_N "checking if your system defines LASTLOG_FILE... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <utmp.h>
-#ifdef HAVE_LASTLOG_H
-# include <lastlog.h>
-#endif
-#ifdef HAVE_PATHS_H
-# include <paths.h>
-#endif
-#ifdef HAVE_LOGIN_H
-# include <login.h>
-#endif
-
-int
-main ()
-{
- char *lastlog = LASTLOG_FILE;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- { echo "$as_me:$LINENO: checking if your system defines _PATH_LASTLOG" >&5
-echo $ECHO_N "checking if your system defines _PATH_LASTLOG... $ECHO_C" >&6; }
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <utmp.h>
-#ifdef HAVE_LASTLOG_H
-# include <lastlog.h>
-#endif
-#ifdef HAVE_PATHS_H
-# include <paths.h>
-#endif
-
-int
-main ()
-{
- char *lastlog = _PATH_LASTLOG;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- system_lastlog_path=no
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test -z "$conf_lastlog_location"; then
- if test x"$system_lastlog_path" = x"no" ; then
- for f in /var/log/lastlog /usr/adm/lastlog /var/adm/lastlog /etc/security/lastlog ; do
- if (test -d "$f" || test -f "$f") ; then
- conf_lastlog_location=$f
- fi
- done
- if test -z "$conf_lastlog_location"; then
- { echo "$as_me:$LINENO: WARNING: ** Cannot find lastlog **" >&5
-echo "$as_me: WARNING: ** Cannot find lastlog **" >&2;}
- fi
- fi
-fi
-
-if test -n "$conf_lastlog_location"; then
-
-cat >>confdefs.h <<_ACEOF
-#define CONF_LASTLOG_FILE "$conf_lastlog_location"
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking if your system defines UTMP_FILE" >&5
-echo $ECHO_N "checking if your system defines UTMP_FILE... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <utmp.h>
-#ifdef HAVE_PATHS_H
-# include <paths.h>
-#endif
-
-int
-main ()
-{
- char *utmp = UTMP_FILE;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- system_utmp_path=no
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-if test -z "$conf_utmp_location"; then
- if test x"$system_utmp_path" = x"no" ; then
- for f in /etc/utmp /usr/adm/utmp /var/run/utmp; do
- if test -f $f ; then
- conf_utmp_location=$f
- fi
- done
- if test -z "$conf_utmp_location"; then
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_UTMP 1
-_ACEOF
-
- fi
- fi
-fi
-if test -n "$conf_utmp_location"; then
-
-cat >>confdefs.h <<_ACEOF
-#define CONF_UTMP_FILE "$conf_utmp_location"
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking if your system defines WTMP_FILE" >&5
-echo $ECHO_N "checking if your system defines WTMP_FILE... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <utmp.h>
-#ifdef HAVE_PATHS_H
-# include <paths.h>
-#endif
-
-int
-main ()
-{
- char *wtmp = WTMP_FILE;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- system_wtmp_path=no
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-if test -z "$conf_wtmp_location"; then
- if test x"$system_wtmp_path" = x"no" ; then
- for f in /usr/adm/wtmp /var/log/wtmp; do
- if test -f $f ; then
- conf_wtmp_location=$f
- fi
- done
- if test -z "$conf_wtmp_location"; then
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_WTMP 1
-_ACEOF
-
- fi
- fi
-fi
-if test -n "$conf_wtmp_location"; then
-
-cat >>confdefs.h <<_ACEOF
-#define CONF_WTMP_FILE "$conf_wtmp_location"
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking if your system defines WTMPX_FILE" >&5
-echo $ECHO_N "checking if your system defines WTMPX_FILE... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <utmp.h>
-#ifdef HAVE_UTMPX_H
-#include <utmpx.h>
-#endif
-#ifdef HAVE_PATHS_H
-# include <paths.h>
-#endif
-
-int
-main ()
-{
- char *wtmpx = WTMPX_FILE;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- system_wtmpx_path=no
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-if test -z "$conf_wtmpx_location"; then
- if test x"$system_wtmpx_path" = x"no" ; then
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_WTMPX 1
-_ACEOF
-
- fi
-else
-
-cat >>confdefs.h <<_ACEOF
-#define CONF_WTMPX_FILE "$conf_wtmpx_location"
-_ACEOF
-
-fi
-
-
-if test ! -z "$blibpath" ; then
- LDFLAGS="$LDFLAGS $blibflags$blibpath"
- { echo "$as_me:$LINENO: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&5
-echo "$as_me: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&2;}
-fi
-
-{ echo "$as_me:$LINENO: checking for struct lastlog.ll_line" >&5
-echo $ECHO_N "checking for struct lastlog.ll_line... $ECHO_C" >&6; }
-if test "${ac_cv_member_struct_lastlog_ll_line+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_UTMP_H
-#include <utmp.h>
-#endif
-#ifdef HAVE_UTMPX_H
-#include <utmpx.h>
-#endif
-#ifdef HAVE_LASTLOG_H
-#include <lastlog.h>
-#endif
-
-
-int
-main ()
-{
-static struct lastlog ac_aggr;
-if (ac_aggr.ll_line)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_lastlog_ll_line=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_UTMP_H
-#include <utmp.h>
-#endif
-#ifdef HAVE_UTMPX_H
-#include <utmpx.h>
-#endif
-#ifdef HAVE_LASTLOG_H
-#include <lastlog.h>
-#endif
-
-
-int
-main ()
-{
-static struct lastlog ac_aggr;
-if (sizeof ac_aggr.ll_line)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_lastlog_ll_line=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_member_struct_lastlog_ll_line=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_lastlog_ll_line" >&5
-echo "${ECHO_T}$ac_cv_member_struct_lastlog_ll_line" >&6; }
-if test $ac_cv_member_struct_lastlog_ll_line = yes; then
- :
-else
-
- if test x$SKIP_DISABLE_LASTLOG_DEFINE != "xyes" ; then
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_LASTLOG 1
-_ACEOF
-
- fi
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking for struct utmp.ut_line" >&5
-echo $ECHO_N "checking for struct utmp.ut_line... $ECHO_C" >&6; }
-if test "${ac_cv_member_struct_utmp_ut_line+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_UTMP_H
-#include <utmp.h>
-#endif
-#ifdef HAVE_UTMPX_H
-#include <utmpx.h>
-#endif
-#ifdef HAVE_LASTLOG_H
-#include <lastlog.h>
-#endif
-
-
-int
-main ()
-{
-static struct utmp ac_aggr;
-if (ac_aggr.ut_line)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_utmp_ut_line=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_UTMP_H
-#include <utmp.h>
-#endif
-#ifdef HAVE_UTMPX_H
-#include <utmpx.h>
-#endif
-#ifdef HAVE_LASTLOG_H
-#include <lastlog.h>
-#endif
-
-
-int
-main ()
-{
-static struct utmp ac_aggr;
-if (sizeof ac_aggr.ut_line)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_member_struct_utmp_ut_line=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_member_struct_utmp_ut_line=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_utmp_ut_line" >&5
-echo "${ECHO_T}$ac_cv_member_struct_utmp_ut_line" >&6; }
-if test $ac_cv_member_struct_utmp_ut_line = yes; then
- :
-else
-
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_UTMP 1
-_ACEOF
-
- cat >>confdefs.h <<\_ACEOF
-#define DISABLE_WTMP 1
-_ACEOF
-
-
-fi
-
-
-CFLAGS="$CFLAGS $werror_flags"
-
-if test "x$ac_cv_func_getaddrinfo" != "xyes" ; then
- TEST_SSH_IPV6=no
-else
- TEST_SSH_IPV6=yes
-fi
-{ echo "$as_me:$LINENO: checking whether BROKEN_GETADDRINFO is declared" >&5
-echo $ECHO_N "checking whether BROKEN_GETADDRINFO is declared... $ECHO_C" >&6; }
-if test "${ac_cv_have_decl_BROKEN_GETADDRINFO+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-#ifndef BROKEN_GETADDRINFO
- (void) BROKEN_GETADDRINFO;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_have_decl_BROKEN_GETADDRINFO=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_have_decl_BROKEN_GETADDRINFO=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_BROKEN_GETADDRINFO" >&5
-echo "${ECHO_T}$ac_cv_have_decl_BROKEN_GETADDRINFO" >&6; }
-if test $ac_cv_have_decl_BROKEN_GETADDRINFO = yes; then
- TEST_SSH_IPV6=no
-fi
-
-TEST_SSH_IPV6=$TEST_SSH_IPV6
-
-TEST_MALLOC_OPTIONS=$TEST_MALLOC_OPTIONS
-
-UNSUPPORTED_ALGORITHMS=$unsupported_algorithms
-
-
-
-ac_config_files="$ac_config_files Makefile buildpkg.sh opensshd.init openssh.xml openbsd-compat/Makefile openbsd-compat/regress/Makefile survey.sh"
-
-cat >confcache <<\_ACEOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems. If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-_ACEOF
-
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, we kill variables containing newlines.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(
- for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
- eval ac_val=\$$ac_var
- case $ac_val in #(
- *${as_nl}*)
- case $ac_var in #(
- *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
-echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
- esac
- case $ac_var in #(
- _ | IFS | as_nl) ;; #(
- *) $as_unset $ac_var ;;
- esac ;;
- esac
- done
-
- (set) 2>&1 |
- case $as_nl`(ac_space=' '; set) 2>&1` in #(
- *${as_nl}ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote
- # substitution turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- "s/'/'\\\\''/g;
- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
- ;; #(
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
- ;;
- esac |
- sort
-) |
- sed '
- /^ac_cv_env_/b end
- t clear
- :clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
- t end
- s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
- :end' >>confcache
-if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
- if test -w "$cache_file"; then
- test "x$cache_file" != "x/dev/null" &&
- { echo "$as_me:$LINENO: updating cache $cache_file" >&5
-echo "$as_me: updating cache $cache_file" >&6;}
- cat confcache >$cache_file
- else
- { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
-echo "$as_me: not updating unwritable cache $cache_file" >&6;}
- fi
-fi
-rm -f confcache
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-DEFS=-DHAVE_CONFIG_H
-
-ac_libobjs=
-ac_ltlibobjs=
-for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
- # 1. Remove the extension, and $U if already installed.
- ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`echo "$ac_i" | sed "$ac_script"`
- # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
- # will be set to the directory where LIBOBJS objects are built.
- ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
- ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
-done
-LIBOBJS=$ac_libobjs
-
-LTLIBOBJS=$ac_ltlibobjs
-
-
-
-: ${CONFIG_STATUS=./config.status}
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
-echo "$as_me: creating $CONFIG_STATUS" >&6;}
-cat >$CONFIG_STATUS <<_ACEOF
-#! $SHELL
-# Generated by $as_me.
-# Run this file to recreate the current configuration.
-# Compiler output produced by configure, useful for debugging
-# configure, is in config.log if it exists.
-
-debug=false
-ac_cs_recheck=false
-ac_cs_silent=false
-SHELL=\${CONFIG_SHELL-$SHELL}
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-## --------------------- ##
-## M4sh Initialization. ##
-## --------------------- ##
-
-# Be more Bourne compatible
-DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in
- *posix*) set -o posix ;;
-esac
-
-fi
-
-
-
-
-# PATH needs CR
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- echo "#! /bin/sh" >conf$$.sh
- echo "exit 0" >>conf$$.sh
- chmod +x conf$$.sh
- if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
- PATH_SEPARATOR=';'
- else
- PATH_SEPARATOR=:
- fi
- rm -f conf$$.sh
-fi
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- as_unset=unset
-else
- as_unset=false
-fi
-
-
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-as_nl='
-'
-IFS=" "" $as_nl"
-
-# Find who we are. Look in the path if we contain no directory separator.
-case $0 in
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
-# in which case we are not to be found in the path.
-if test "x$as_myself" = x; then
- as_myself=$0
-fi
-if test ! -f "$as_myself"; then
- echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
- { (exit 1); exit 1; }
-fi
-
-# Work around bugs in pre-3.0 UWIN ksh.
-for as_var in ENV MAIL MAILPATH
-do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
- LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
- LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
- LC_TELEPHONE LC_TIME
-do
- if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
- eval $as_var=C; export $as_var
- else
- ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
- fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{
- s//\1/
- q
- }
- /^X\/\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\/\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
-
-# CDPATH.
-$as_unset CDPATH
-
-
-
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
-
- # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
- # uniformly replaced by the line number. The first 'sed' inserts a
- # line-number line after each line using $LINENO; the second 'sed'
- # does the real work. The second script uses 'N' to pair each
- # line-number line with the line containing $LINENO, and appends
- # trailing '-' during substitution so that $LINENO is not a special
- # case at line end.
- # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
- # scripts with optimization help from Paolo Bonzini. Blame Lee
- # E. McMahon (1931-1989) for sed's syntax. :-)
- sed -n '
- p
- /[$]LINENO/=
- ' <$as_myself |
- sed '
- s/[$]LINENO.*/&-/
- t lineno
- b
- :lineno
- N
- :loop
- s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
- t loop
- s/-\n.*//
- ' >$as_me.lineno &&
- chmod +x "$as_me.lineno" ||
- { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
- { (exit 1); exit 1; }; }
-
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensitive to this).
- . "./$as_me.lineno"
- # Exit status is that of the last command.
- exit
-}
-
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
- as_dirname=dirname
-else
- as_dirname=false
-fi
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in
--n*)
- case `echo 'x\c'` in
- *c*) ECHO_T=' ';; # ECHO_T is single tab character.
- *) ECHO_C='\c';;
- esac;;
-*)
- ECHO_N='-n';;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-if test -d conf$$.dir; then
- rm -f conf$$.dir/conf$$.file
-else
- rm -f conf$$.dir
- mkdir conf$$.dir
-fi
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
- as_ln_s='ln -s'
- # ... but there are two gotchas:
- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -p'.
- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -p'
-elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
-else
- as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
-rmdir conf$$.dir 2>/dev/null
-
-if mkdir -p . 2>/dev/null; then
- as_mkdir_p=:
-else
- test -d ./-p && rmdir ./-p
- as_mkdir_p=false
-fi
-
-if test -x / >/dev/null 2>&1; then
- as_test_x='test -x'
-else
- if ls -dL / >/dev/null 2>&1; then
- as_ls_L_option=L
- else
- as_ls_L_option=
- fi
- as_test_x='
- eval sh -c '\''
- if test -d "$1"; then
- test -d "$1/.";
- else
- case $1 in
- -*)set "./$1";;
- esac;
- case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
- ???[sx]*):;;*)false;;esac;fi
- '\'' sh
- '
-fi
-as_executable_p=$as_test_x
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-exec 6>&1
-
-# Save the log message, to keep $[0] and so on meaningful, and to
-# report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling.
-ac_log="
-This file was extended by OpenSSH $as_me Portable, which was
-generated by GNU Autoconf 2.61. Invocation command line was
-
- CONFIG_FILES = $CONFIG_FILES
- CONFIG_HEADERS = $CONFIG_HEADERS
- CONFIG_LINKS = $CONFIG_LINKS
- CONFIG_COMMANDS = $CONFIG_COMMANDS
- $ $0 $@
-
-on `(hostname || uname -n) 2>/dev/null | sed 1q`
-"
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-# Files that config.status was made for.
-config_files="$ac_config_files"
-config_headers="$ac_config_headers"
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-ac_cs_usage="\
-\`$as_me' instantiates files from templates according to the
-current configuration.
-
-Usage: $0 [OPTIONS] [FILE]...
-
- -h, --help print this help, then exit
- -V, --version print version number and configuration settings, then exit
- -q, --quiet do not print progress messages
- -d, --debug don't remove temporary files
- --recheck update $as_me by reconfiguring in the same conditions
- --file=FILE[:TEMPLATE]
- instantiate the configuration file FILE
- --header=FILE[:TEMPLATE]
- instantiate the configuration header FILE
-
-Configuration files:
-$config_files
-
-Configuration headers:
-$config_headers
-
-Report bugs to <bug-autoconf@gnu.org>."
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-ac_cs_version="\\
-OpenSSH config.status Portable
-configured by $0, generated by GNU Autoconf 2.61,
- with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
-
-Copyright (C) 2006 Free Software Foundation, Inc.
-This config.status script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it."
-
-ac_pwd='$ac_pwd'
-srcdir='$srcdir'
-INSTALL='$INSTALL'
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-# If no file are specified by the user, then we need to provide default
-# value. By we need to know if files were specified by the user.
-ac_need_defaults=:
-while test $# != 0
-do
- case $1 in
- --*=*)
- ac_option=`expr "X$1" : 'X\([^=]*\)='`
- ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
- ac_shift=:
- ;;
- *)
- ac_option=$1
- ac_optarg=$2
- ac_shift=shift
- ;;
- esac
-
- case $ac_option in
- # Handling of the options.
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- ac_cs_recheck=: ;;
- --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- echo "$ac_cs_version"; exit ;;
- --debug | --debu | --deb | --de | --d | -d )
- debug=: ;;
- --file | --fil | --fi | --f )
- $ac_shift
- CONFIG_FILES="$CONFIG_FILES $ac_optarg"
- ac_need_defaults=false;;
- --header | --heade | --head | --hea )
- $ac_shift
- CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
- ac_need_defaults=false;;
- --he | --h)
- # Conflict between --help and --header
- { echo "$as_me: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&2
- { (exit 1); exit 1; }; };;
- --help | --hel | -h )
- echo "$ac_cs_usage"; exit ;;
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil | --si | --s)
- ac_cs_silent=: ;;
-
- # This is an error.
- -*) { echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2
- { (exit 1); exit 1; }; } ;;
-
- *) ac_config_targets="$ac_config_targets $1"
- ac_need_defaults=false ;;
-
- esac
- shift
-done
-
-ac_configure_extra_args=
-
-if $ac_cs_silent; then
- exec 6>/dev/null
- ac_configure_extra_args="$ac_configure_extra_args --silent"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-if \$ac_cs_recheck; then
- echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
- CONFIG_SHELL=$SHELL
- export CONFIG_SHELL
- exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-exec 5>>config.log
-{
- echo
- sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
- echo "$ac_log"
-} >&5
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-# Handling of arguments.
-for ac_config_target in $ac_config_targets
-do
- case $ac_config_target in
- "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
- "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
- "buildpkg.sh") CONFIG_FILES="$CONFIG_FILES buildpkg.sh" ;;
- "opensshd.init") CONFIG_FILES="$CONFIG_FILES opensshd.init" ;;
- "openssh.xml") CONFIG_FILES="$CONFIG_FILES openssh.xml" ;;
- "openbsd-compat/Makefile") CONFIG_FILES="$CONFIG_FILES openbsd-compat/Makefile" ;;
- "openbsd-compat/regress/Makefile") CONFIG_FILES="$CONFIG_FILES openbsd-compat/regress/Makefile" ;;
- "survey.sh") CONFIG_FILES="$CONFIG_FILES survey.sh" ;;
-
- *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
-echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
- { (exit 1); exit 1; }; };;
- esac
-done
-
-
-# If the user did not use the arguments to specify the items to instantiate,
-# then the envvar interface is used. Set only those that are not.
-# We use the long form for the default assignment because of an extremely
-# bizarre bug on SunOS 4.1.3.
-if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
- test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
-fi
-
-# Have a temporary directory for convenience. Make it in the build tree
-# simply because there is no reason against having it here, and in addition,
-# creating and moving files from /tmp can sometimes cause problems.
-# Hook for its removal unless debugging.
-# Note that there is a small window in which the directory will not be cleaned:
-# after its creation but before its name has been assigned to `$tmp'.
-$debug ||
-{
- tmp=
- trap 'exit_status=$?
- { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
-' 0
- trap '{ (exit 1); exit 1; }' 1 2 13 15
-}
-# Create a (secure) tmp directory for tmp files.
-
-{
- tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
- test -n "$tmp" && test -d "$tmp"
-} ||
-{
- tmp=./conf$$-$RANDOM
- (umask 077 && mkdir "$tmp")
-} ||
-{
- echo "$me: cannot create a temporary directory in ." >&2
- { (exit 1); exit 1; }
-}
-
-#
-# Set up the sed scripts for CONFIG_FILES section.
-#
-
-# No need to generate the scripts if there are no CONFIG_FILES.
-# This happens for instance when ./config.status config.h
-if test -n "$CONFIG_FILES"; then
-
-_ACEOF
-
-
-
-ac_delim='%!_!# '
-for ac_last_try in false false false false false :; do
- cat >conf$$subs.sed <<_ACEOF
-SHELL!$SHELL$ac_delim
-PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
-PACKAGE_NAME!$PACKAGE_NAME$ac_delim
-PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
-PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
-PACKAGE_STRING!$PACKAGE_STRING$ac_delim
-PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
-exec_prefix!$exec_prefix$ac_delim
-prefix!$prefix$ac_delim
-program_transform_name!$program_transform_name$ac_delim
-bindir!$bindir$ac_delim
-sbindir!$sbindir$ac_delim
-libexecdir!$libexecdir$ac_delim
-datarootdir!$datarootdir$ac_delim
-datadir!$datadir$ac_delim
-sysconfdir!$sysconfdir$ac_delim
-sharedstatedir!$sharedstatedir$ac_delim
-localstatedir!$localstatedir$ac_delim
-includedir!$includedir$ac_delim
-oldincludedir!$oldincludedir$ac_delim
-docdir!$docdir$ac_delim
-infodir!$infodir$ac_delim
-htmldir!$htmldir$ac_delim
-dvidir!$dvidir$ac_delim
-pdfdir!$pdfdir$ac_delim
-psdir!$psdir$ac_delim
-libdir!$libdir$ac_delim
-localedir!$localedir$ac_delim
-mandir!$mandir$ac_delim
-DEFS!$DEFS$ac_delim
-ECHO_C!$ECHO_C$ac_delim
-ECHO_N!$ECHO_N$ac_delim
-ECHO_T!$ECHO_T$ac_delim
-LIBS!$LIBS$ac_delim
-build_alias!$build_alias$ac_delim
-host_alias!$host_alias$ac_delim
-target_alias!$target_alias$ac_delim
-CC!$CC$ac_delim
-CFLAGS!$CFLAGS$ac_delim
-LDFLAGS!$LDFLAGS$ac_delim
-CPPFLAGS!$CPPFLAGS$ac_delim
-ac_ct_CC!$ac_ct_CC$ac_delim
-EXEEXT!$EXEEXT$ac_delim
-OBJEXT!$OBJEXT$ac_delim
-build!$build$ac_delim
-build_cpu!$build_cpu$ac_delim
-build_vendor!$build_vendor$ac_delim
-build_os!$build_os$ac_delim
-host!$host$ac_delim
-host_cpu!$host_cpu$ac_delim
-host_vendor!$host_vendor$ac_delim
-host_os!$host_os$ac_delim
-CPP!$CPP$ac_delim
-GREP!$GREP$ac_delim
-EGREP!$EGREP$ac_delim
-AWK!$AWK$ac_delim
-RANLIB!$RANLIB$ac_delim
-INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
-INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
-INSTALL_DATA!$INSTALL_DATA$ac_delim
-AR!$AR$ac_delim
-CAT!$CAT$ac_delim
-KILL!$KILL$ac_delim
-PERL!$PERL$ac_delim
-SED!$SED$ac_delim
-ENT!$ENT$ac_delim
-TEST_MINUS_S_SH!$TEST_MINUS_S_SH$ac_delim
-SH!$SH$ac_delim
-GROFF!$GROFF$ac_delim
-NROFF!$NROFF$ac_delim
-MANDOC!$MANDOC$ac_delim
-TEST_SHELL!$TEST_SHELL$ac_delim
-MANFMT!$MANFMT$ac_delim
-PATH_GROUPADD_PROG!$PATH_GROUPADD_PROG$ac_delim
-PATH_USERADD_PROG!$PATH_USERADD_PROG$ac_delim
-MAKE_PACKAGE_SUPPORTED!$MAKE_PACKAGE_SUPPORTED$ac_delim
-STARTUP_SCRIPT_SHELL!$STARTUP_SCRIPT_SHELL$ac_delim
-LOGIN_PROGRAM_FALLBACK!$LOGIN_PROGRAM_FALLBACK$ac_delim
-PATH_PASSWD_PROG!$PATH_PASSWD_PROG$ac_delim
-LD!$LD$ac_delim
-PKGCONFIG!$PKGCONFIG$ac_delim
-LIBEDIT!$LIBEDIT$ac_delim
-TEST_SSH_ECC!$TEST_SSH_ECC$ac_delim
-COMMENT_OUT_ECC!$COMMENT_OUT_ECC$ac_delim
-SSH_PRIVSEP_USER!$SSH_PRIVSEP_USER$ac_delim
-SSHLIBS!$SSHLIBS$ac_delim
-SSHDLIBS!$SSHDLIBS$ac_delim
-KRB5CONF!$KRB5CONF$ac_delim
-GSSLIBS!$GSSLIBS$ac_delim
-K5LIBS!$K5LIBS$ac_delim
-PRIVSEP_PATH!$PRIVSEP_PATH$ac_delim
-xauth_path!$xauth_path$ac_delim
-STRIP_OPT!$STRIP_OPT$ac_delim
-XAUTH_PATH!$XAUTH_PATH$ac_delim
-MANTYPE!$MANTYPE$ac_delim
-mansubdir!$mansubdir$ac_delim
-user_path!$user_path$ac_delim
-_ACEOF
-
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
- break
- elif $ac_last_try; then
- { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
-echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
- { (exit 1); exit 1; }; }
- else
- ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
- fi
-done
-
-ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
-if test -n "$ac_eof"; then
- ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
- ac_eof=`expr $ac_eof + 1`
-fi
-
-cat >>$CONFIG_STATUS <<_ACEOF
-cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-_ACEOF
-sed '
-s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
-s/^/s,@/; s/!/@,|#_!!_#|/
-:n
-t n
-s/'"$ac_delim"'$/,g/; t
-s/$/\\/; p
-N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
-' >>$CONFIG_STATUS <conf$$subs.sed
-rm -f conf$$subs.sed
-cat >>$CONFIG_STATUS <<_ACEOF
-CEOF$ac_eof
-_ACEOF
-
-
-ac_delim='%!_!# '
-for ac_last_try in false false false false false :; do
- cat >conf$$subs.sed <<_ACEOF
-piddir!$piddir$ac_delim
-TEST_SSH_IPV6!$TEST_SSH_IPV6$ac_delim
-TEST_MALLOC_OPTIONS!$TEST_MALLOC_OPTIONS$ac_delim
-UNSUPPORTED_ALGORITHMS!$UNSUPPORTED_ALGORITHMS$ac_delim
-LIBOBJS!$LIBOBJS$ac_delim
-LTLIBOBJS!$LTLIBOBJS$ac_delim
-_ACEOF
-
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 6; then
- break
- elif $ac_last_try; then
- { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
-echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
- { (exit 1); exit 1; }; }
- else
- ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
- fi
-done
-
-ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
-if test -n "$ac_eof"; then
- ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
- ac_eof=`expr $ac_eof + 1`
-fi
-
-cat >>$CONFIG_STATUS <<_ACEOF
-cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
-_ACEOF
-sed '
-s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
-s/^/s,@/; s/!/@,|#_!!_#|/
-:n
-t n
-s/'"$ac_delim"'$/,g/; t
-s/$/\\/; p
-N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
-' >>$CONFIG_STATUS <conf$$subs.sed
-rm -f conf$$subs.sed
-cat >>$CONFIG_STATUS <<_ACEOF
-:end
-s/|#_!!_#|//g
-CEOF$ac_eof
-_ACEOF
-
-
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=/{
-s/:*\$(srcdir):*/:/
-s/:*\${srcdir}:*/:/
-s/:*@srcdir@:*/:/
-s/^\([^=]*=[ ]*\):*/\1/
-s/:*$//
-s/^[^=]*=[ ]*$//
-}'
-fi
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-fi # test -n "$CONFIG_FILES"
-
-
-for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS
-do
- case $ac_tag in
- :[FHLC]) ac_mode=$ac_tag; continue;;
- esac
- case $ac_mode$ac_tag in
- :[FHL]*:*);;
- :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
-echo "$as_me: error: Invalid tag $ac_tag." >&2;}
- { (exit 1); exit 1; }; };;
- :[FH]-) ac_tag=-:-;;
- :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
- esac
- ac_save_IFS=$IFS
- IFS=:
- set x $ac_tag
- IFS=$ac_save_IFS
- shift
- ac_file=$1
- shift
-
- case $ac_mode in
- :L) ac_source=$1;;
- :[FH])
- ac_file_inputs=
- for ac_f
- do
- case $ac_f in
- -) ac_f="$tmp/stdin";;
- *) # Look for the file first in the build tree, then in the source tree
- # (if the path is not absolute). The absolute path cannot be DOS-style,
- # because $ac_f cannot contain `:'.
- test -f "$ac_f" ||
- case $ac_f in
- [\\/$]*) false;;
- *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
- esac ||
- { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
-echo "$as_me: error: cannot find input file: $ac_f" >&2;}
- { (exit 1); exit 1; }; };;
- esac
- ac_file_inputs="$ac_file_inputs $ac_f"
- done
-
- # Let's still pretend it is `configure' which instantiates (i.e., don't
- # use $as_me), people would be surprised to read:
- # /* config.h. Generated by config.status. */
- configure_input="Generated from "`IFS=:
- echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
- if test x"$ac_file" != x-; then
- configure_input="$ac_file. $configure_input"
- { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
- fi
-
- case $ac_tag in
- *:-:* | *:-) cat >"$tmp/stdin";;
- esac
- ;;
- esac
-
- ac_dir=`$as_dirname -- "$ac_file" ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$ac_file" : 'X\(//\)[^/]' \| \
- X"$ac_file" : 'X\(//\)$' \| \
- X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-echo X"$ac_file" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- { as_dir="$ac_dir"
- case $as_dir in #(
- -*) as_dir=./$as_dir;;
- esac
- test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
- as_dirs=
- while :; do
- case $as_dir in #(
- *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
- *) as_qdir=$as_dir;;
- esac
- as_dirs="'$as_qdir' $as_dirs"
- as_dir=`$as_dirname -- "$as_dir" ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- test -d "$as_dir" && break
- done
- test -z "$as_dirs" || eval "mkdir $as_dirs"
- } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
-echo "$as_me: error: cannot create directory $as_dir" >&2;}
- { (exit 1); exit 1; }; }; }
- ac_builddir=.
-
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
- ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
- # A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
- case $ac_top_builddir_sub in
- "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
- *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
- esac ;;
-esac
-ac_abs_top_builddir=$ac_pwd
-ac_abs_builddir=$ac_pwd$ac_dir_suffix
-# for backward compatibility:
-ac_top_builddir=$ac_top_build_prefix
-
-case $srcdir in
- .) # We are building in place.
- ac_srcdir=.
- ac_top_srcdir=$ac_top_builddir_sub
- ac_abs_top_srcdir=$ac_pwd ;;
- [\\/]* | ?:[\\/]* ) # Absolute name.
- ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir
- ac_abs_top_srcdir=$srcdir ;;
- *) # Relative name.
- ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_build_prefix$srcdir
- ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
-esac
-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
-
-
- case $ac_mode in
- :F)
- #
- # CONFIG_FILE
- #
-
- case $INSTALL in
- [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
- *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
- esac
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-# If the template does not know about datarootdir, expand it.
-# FIXME: This hack should be removed a few years after 2.60.
-ac_datarootdir_hack=; ac_datarootdir_seen=
-
-case `sed -n '/datarootdir/ {
- p
- q
-}
-/@datadir@/p
-/@docdir@/p
-/@infodir@/p
-/@localedir@/p
-/@mandir@/p
-' $ac_file_inputs` in
-*datarootdir*) ac_datarootdir_seen=yes;;
-*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
- ac_datarootdir_hack='
- s&@datadir@&$datadir&g
- s&@docdir@&$docdir&g
- s&@infodir@&$infodir&g
- s&@localedir@&$localedir&g
- s&@mandir@&$mandir&g
- s&\\\${datarootdir}&$datarootdir&g' ;;
-esac
-_ACEOF
-
-# Neutralize VPATH when `$srcdir' = `.'.
-# Shell code in configure.ac might set extrasub.
-# FIXME: do we really want to maintain this feature?
-cat >>$CONFIG_STATUS <<_ACEOF
- sed "$ac_vpsub
-$extrasub
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-:t
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s&@configure_input@&$configure_input&;t t
-s&@top_builddir@&$ac_top_builddir_sub&;t t
-s&@srcdir@&$ac_srcdir&;t t
-s&@abs_srcdir@&$ac_abs_srcdir&;t t
-s&@top_srcdir@&$ac_top_srcdir&;t t
-s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
-s&@builddir@&$ac_builddir&;t t
-s&@abs_builddir@&$ac_abs_builddir&;t t
-s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
-s&@INSTALL@&$ac_INSTALL&;t t
-$ac_datarootdir_hack
-" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
-
-test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
- { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
- { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
- { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined." >&5
-echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined." >&2;}
-
- rm -f "$tmp/stdin"
- case $ac_file in
- -) cat "$tmp/out"; rm -f "$tmp/out";;
- *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
- esac
- ;;
- :H)
- #
- # CONFIG_HEADER
- #
-_ACEOF
-
-# Transform confdefs.h into a sed script `conftest.defines', that
-# substitutes the proper values into config.h.in to produce config.h.
-rm -f conftest.defines conftest.tail
-# First, append a space to every undef/define line, to ease matching.
-echo 's/$/ /' >conftest.defines
-# Then, protect against being on the right side of a sed subst, or in
-# an unquoted here document, in config.status. If some macros were
-# called several times there might be several #defines for the same
-# symbol, which is useless. But do not sort them, since the last
-# AC_DEFINE must be honored.
-ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
-# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
-# NAME is the cpp macro being defined, VALUE is the value it is being given.
-# PARAMS is the parameter list in the macro definition--in most cases, it's
-# just an empty string.
-ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
-ac_dB='\\)[ (].*,\\1define\\2'
-ac_dC=' '
-ac_dD=' ,'
-
-uniq confdefs.h |
- sed -n '
- t rset
- :rset
- s/^[ ]*#[ ]*define[ ][ ]*//
- t ok
- d
- :ok
- s/[\\&,]/\\&/g
- s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
- s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
- ' >>conftest.defines
-
-# Remove the space that was appended to ease matching.
-# Then replace #undef with comments. This is necessary, for
-# example, in the case of _POSIX_SOURCE, which is predefined and required
-# on some systems where configure will not decide to define it.
-# (The regexp can be short, since the line contains either #define or #undef.)
-echo 's/ $//
-s,^[ #]*u.*,/* & */,' >>conftest.defines
-
-# Break up conftest.defines:
-ac_max_sed_lines=50
-
-# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
-# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
-# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
-# et cetera.
-ac_in='$ac_file_inputs'
-ac_out='"$tmp/out1"'
-ac_nxt='"$tmp/out2"'
-
-while :
-do
- # Write a here document:
- cat >>$CONFIG_STATUS <<_ACEOF
- # First, check the format of the line:
- cat >"\$tmp/defines.sed" <<\\CEOF
-/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
-/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
-b
-:def
-_ACEOF
- sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
- echo 'CEOF
- sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
- ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
- sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
- grep . conftest.tail >/dev/null || break
- rm -f conftest.defines
- mv conftest.tail conftest.defines
-done
-rm -f conftest.defines conftest.tail
-
-echo "ac_result=$ac_in" >>$CONFIG_STATUS
-cat >>$CONFIG_STATUS <<\_ACEOF
- if test x"$ac_file" != x-; then
- echo "/* $configure_input */" >"$tmp/config.h"
- cat "$ac_result" >>"$tmp/config.h"
- if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
- { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
-echo "$as_me: $ac_file is unchanged" >&6;}
- else
- rm -f $ac_file
- mv "$tmp/config.h" $ac_file
- fi
- else
- echo "/* $configure_input */"
- cat "$ac_result"
- fi
- rm -f "$tmp/out12"
- ;;
-
-
- esac
-
-done # for ac_tag
-
-
-{ (exit 0); exit 0; }
-_ACEOF
-chmod +x $CONFIG_STATUS
-ac_clean_files=$ac_clean_files_save
-
-
-# configure is writing to config.log, and then calls config.status.
-# config.status does its own redirection, appending to config.log.
-# Unfortunately, on DOS this fails, as config.log is still kept open
-# by configure, so config.status won't be able to write to it; its
-# output is simply discarded. So we exec the FD to /dev/null,
-# effectively closing config.log, so it can be properly (re)opened and
-# appended to by config.status. When coming back to configure, we
-# need to make the FD available again.
-if test "$no_create" != yes; then
- ac_cs_success=:
- ac_config_status_args=
- test "$silent" = yes &&
- ac_config_status_args="$ac_config_status_args --quiet"
- exec 5>/dev/null
- $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
- exec 5>>config.log
- # Use ||, not &&, to avoid exiting from the if with $? = 1, which
- # would make configure fail if this is the last instruction.
- $ac_cs_success || { (exit 1); exit 1; }
-fi
-
-
-# Print summary of options
-
-# Someone please show me a better way :)
-A=`eval echo ${prefix}` ; A=`eval echo ${A}`
-B=`eval echo ${bindir}` ; B=`eval echo ${B}`
-C=`eval echo ${sbindir}` ; C=`eval echo ${C}`
-D=`eval echo ${sysconfdir}` ; D=`eval echo ${D}`
-E=`eval echo ${libexecdir}/ssh-askpass` ; E=`eval echo ${E}`
-F=`eval echo ${mandir}/${mansubdir}X` ; F=`eval echo ${F}`
-G=`eval echo ${piddir}` ; G=`eval echo ${G}`
-H=`eval echo ${PRIVSEP_PATH}` ; H=`eval echo ${H}`
-I=`eval echo ${user_path}` ; I=`eval echo ${I}`
-J=`eval echo ${superuser_path}` ; J=`eval echo ${J}`
-
-echo ""
-echo "OpenSSH has been configured with the following options:"
-echo " User binaries: $B"
-echo " System binaries: $C"
-echo " Configuration files: $D"
-echo " Askpass program: $E"
-echo " Manual pages: $F"
-echo " PID file: $G"
-echo " Privilege separation chroot path: $H"
-if test "x$external_path_file" = "x/etc/login.conf" ; then
-echo " At runtime, sshd will use the path defined in $external_path_file"
-echo " Make sure the path to scp is present, otherwise scp will not work"
-else
-echo " sshd default user PATH: $I"
- if test ! -z "$external_path_file"; then
-echo " (If PATH is set in $external_path_file it will be used instead. If"
-echo " used, ensure the path to scp is present, otherwise scp will not work.)"
- fi
-fi
-if test ! -z "$superuser_path" ; then
-echo " sshd superuser user PATH: $J"
-fi
-echo " Manpage format: $MANTYPE"
-echo " PAM support: $PAM_MSG"
-echo " OSF SIA support: $SIA_MSG"
-echo " KerberosV support: $KRB5_MSG"
-echo " SELinux support: $SELINUX_MSG"
-echo " Smartcard support: $SCARD_MSG"
-echo " S/KEY support: $SKEY_MSG"
-echo " MD5 password support: $MD5_MSG"
-echo " libedit support: $LIBEDIT_MSG"
-echo " Solaris process contract support: $SPC_MSG"
-echo " Solaris project support: $SP_MSG"
-echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
-echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
-echo " BSD Auth support: $BSD_AUTH_MSG"
-echo " Random number source: $RAND_MSG"
-echo " Privsep sandbox style: $SANDBOX_STYLE"
-
-echo ""
-
-echo " Host: ${host}"
-echo " Compiler: ${CC}"
-echo " Compiler flags: ${CFLAGS}"
-echo "Preprocessor flags: ${CPPFLAGS}"
-echo " Linker flags: ${LDFLAGS}"
-echo " Libraries: ${LIBS}"
-if test ! -z "${SSHDLIBS}"; then
-echo " +for sshd: ${SSHDLIBS}"
-fi
-if test ! -z "${SSHLIBS}"; then
-echo " +for ssh: ${SSHLIBS}"
-fi
-
-echo ""
-
-if test "x$MAKE_PACKAGE_SUPPORTED" = "xyes" ; then
- echo "SVR4 style packages are supported with \"make package\""
- echo ""
-fi
-
-if test "x$PAM_MSG" = "xyes" ; then
- echo "PAM is enabled. You may need to install a PAM control file "
- echo "for sshd, otherwise password authentication may fail. "
- echo "Example PAM control files can be found in the contrib/ "
- echo "subdirectory"
- echo ""
-fi
-
-if test ! -z "$NO_PEERCHECK" ; then
- echo "WARNING: the operating system that you are using does not"
- echo "appear to support getpeereid(), getpeerucred() or the"
- echo "SO_PEERCRED getsockopt() option. These facilities are used to"
- echo "enforce security checks to prevent unauthorised connections to"
- echo "ssh-agent. Their absence increases the risk that a malicious"
- echo "user can connect to your agent."
- echo ""
-fi
-
-if test "$AUDIT_MODULE" = "bsm" ; then
- echo "WARNING: BSM audit support is currently considered EXPERIMENTAL."
- echo "See the Solaris section in README.platform for details."
-fi
diff --git a/configure.ac b/configure.ac
index b4d6598d..46038375 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,3 @@
-# $Id: configure.ac,v 1.583 2014/08/26 20:32:01 djm Exp $
#
# Copyright (c) 1999-2004 Damien Miller
#
@@ -20,7 +19,7 @@ AC_CONFIG_SRCDIR([ssh.c])
AC_LANG([C])
AC_CONFIG_HEADER([config.h])
-AC_PROG_CC
+AC_PROG_CC([cc gcc])
AC_CANONICAL_HOST
AC_C_BIGENDIAN
@@ -30,12 +29,11 @@ AC_PROG_CPP
AC_PROG_RANLIB
AC_PROG_INSTALL
AC_PROG_EGREP
-AC_PATH_PROG([AR], [ar])
+AC_PROG_MKDIR_P
+AC_CHECK_TOOLS([AR], [ar])
AC_PATH_PROG([CAT], [cat])
AC_PATH_PROG([KILL], [kill])
-AC_PATH_PROGS([PERL], [perl5 perl])
AC_PATH_PROG([SED], [sed])
-AC_SUBST([PERL])
AC_PATH_PROG([ENT], [ent])
AC_SUBST([ENT])
AC_PATH_PROG([TEST_MINUS_S_SH], [bash])
@@ -43,11 +41,11 @@ AC_PATH_PROG([TEST_MINUS_S_SH], [ksh])
AC_PATH_PROG([TEST_MINUS_S_SH], [sh])
AC_PATH_PROG([SH], [sh])
AC_PATH_PROG([GROFF], [groff])
-AC_PATH_PROG([NROFF], [nroff])
+AC_PATH_PROG([NROFF], [nroff awf])
AC_PATH_PROG([MANDOC], [mandoc])
AC_SUBST([TEST_SHELL], [sh])
-dnl select manpage formatter
+dnl select manpage formatter to be used to build "cat" format pages.
if test "x$MANDOC" != "x" ; then
MANFMT="$MANDOC"
elif test "x$NROFF" != "x" ; then
@@ -55,7 +53,7 @@ elif test "x$NROFF" != "x" ; then
elif test "x$GROFF" != "x" ; then
MANFMT="$GROFF -mandoc -Tascii"
else
- AC_MSG_WARN([no manpage formatted found])
+ AC_MSG_WARN([no manpage formatter found])
MANFMT="false"
fi
AC_SUBST([MANFMT])
@@ -79,33 +77,23 @@ if test -z "$AR" ; then
AC_MSG_ERROR([*** 'ar' missing, please install or fix your \$PATH ***])
fi
-# Use LOGIN_PROGRAM from environment if possible
-if test ! -z "$LOGIN_PROGRAM" ; then
- AC_DEFINE_UNQUOTED([LOGIN_PROGRAM_FALLBACK], ["$LOGIN_PROGRAM"],
- [If your header files don't define LOGIN_PROGRAM,
- then use this (detected) from environment and PATH])
-else
- # Search for login
- AC_PATH_PROG([LOGIN_PROGRAM_FALLBACK], [login])
- if test ! -z "$LOGIN_PROGRAM_FALLBACK" ; then
- AC_DEFINE_UNQUOTED([LOGIN_PROGRAM_FALLBACK], ["$LOGIN_PROGRAM_FALLBACK"])
- fi
-fi
-
AC_PATH_PROG([PATH_PASSWD_PROG], [passwd])
if test ! -z "$PATH_PASSWD_PROG" ; then
AC_DEFINE_UNQUOTED([_PATH_PASSWD_PROG], ["$PATH_PASSWD_PROG"],
[Full path of your "passwd" program])
fi
-if test -z "$LD" ; then
- LD=$CC
-fi
+dnl Since autoconf doesn't support it very well, we no longer allow users to
+dnl override LD, however keeping the hook here for now in case there's a use
+dnl use case we overlooked and someone needs to re-enable it. Unless a good
+dnl reason is found we'll be removing this in future.
+LD="$CC"
AC_SUBST([LD])
AC_C_INLINE
AC_CHECK_DECL([LLONG_MAX], [have_llong_max=1], , [#include <limits.h>])
+AC_CHECK_DECL([LONG_LONG_MAX], [have_long_long_max=1], , [#include <limits.h>])
AC_CHECK_DECL([SYSTR_POLICY_KILL], [have_systr_policy_kill=1], , [
#include <sys/types.h>
#include <sys/param.h>
@@ -122,12 +110,10 @@ AC_CHECK_DECL([PR_SET_NO_NEW_PRIVS], [have_linux_no_new_privs=1], , [
])
openssl=yes
-ssh1=yes
AC_ARG_WITH([openssl],
[ --without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL** ],
[ if test "x$withval" = "xno" ; then
openssl=no
- ssh1=no
fi
]
)
@@ -139,24 +125,6 @@ else
AC_MSG_RESULT([no])
fi
-AC_ARG_WITH([ssh1],
- [ --without-ssh1 Disable support for SSH protocol 1],
- [
- if test "x$withval" = "xno" ; then
- ssh1=no
- elif test "x$openssl" = "xno" ; then
- AC_MSG_ERROR([Cannot enable SSH protocol 1 with OpenSSL disabled])
- fi
- ]
-)
-AC_MSG_CHECKING([whether SSH protocol 1 support is enabled])
-if test "x$ssh1" = "xyes" ; then
- AC_MSG_RESULT([yes])
- AC_DEFINE_UNQUOTED([WITH_SSH1], [1], [include SSH protocol version 1 support])
-else
- AC_MSG_RESULT([no])
-fi
-
use_stack_protector=1
use_toolchain_hardening=1
AC_ARG_WITH([stackprotect],
@@ -184,9 +152,12 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int main(void) { return 0; }]])],
CFLAGS="$saved_CFLAGS"
if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
- OSSH_CHECK_CFLAG_COMPILE([-Qunused-arguments])
+ OSSH_CHECK_CFLAG_COMPILE([-pipe])
OSSH_CHECK_CFLAG_COMPILE([-Wunknown-warning-option])
+ OSSH_CHECK_CFLAG_COMPILE([-Wno-error=format-truncation])
+ OSSH_CHECK_CFLAG_COMPILE([-Qunused-arguments])
OSSH_CHECK_CFLAG_COMPILE([-Wall])
+ OSSH_CHECK_CFLAG_COMPILE([-Wextra])
OSSH_CHECK_CFLAG_COMPILE([-Wpointer-arith])
OSSH_CHECK_CFLAG_COMPILE([-Wuninitialized])
OSSH_CHECK_CFLAG_COMPILE([-Wsign-compare])
@@ -194,9 +165,12 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
OSSH_CHECK_CFLAG_COMPILE([-Wsizeof-pointer-memaccess])
OSSH_CHECK_CFLAG_COMPILE([-Wpointer-sign], [-Wno-pointer-sign])
OSSH_CHECK_CFLAG_COMPILE([-Wunused-result], [-Wno-unused-result])
+ OSSH_CHECK_CFLAG_COMPILE([-Wimplicit-fallthrough])
OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing])
- OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2])
if test "x$use_toolchain_hardening" = "x1"; then
+ OSSH_CHECK_CFLAG_COMPILE([-mretpoline]) # clang
+ OSSH_CHECK_LDFLAG_LINK([-Wl,-z,retpolineplt])
+ OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2])
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,relro])
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,now])
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,noexecstack])
@@ -241,20 +215,26 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
CFLAGS="$CFLAGS $t -Werror"
LDFLAGS="$LDFLAGS $t -Werror"
AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([[ #include <stdio.h> ]],
+ [AC_LANG_PROGRAM([[
+ #include <stdio.h>
+ int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;}
+ ]],
[[
char x[256];
- snprintf(x, sizeof(x), "XXX");
+ snprintf(x, sizeof(x), "XXX%d", func(1));
]])],
[ AC_MSG_RESULT([yes])
CFLAGS="$saved_CFLAGS $t"
LDFLAGS="$saved_LDFLAGS $t"
AC_MSG_CHECKING([if $t works])
AC_RUN_IFELSE(
- [AC_LANG_PROGRAM([[ #include <stdio.h> ]],
+ [AC_LANG_PROGRAM([[
+ #include <stdio.h>
+ int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;}
+ ]],
[[
char x[256];
- snprintf(x, sizeof(x), "XXX");
+ snprintf(x, sizeof(x), "XXX%d", func(1));
]])],
[ AC_MSG_RESULT([yes])
break ],
@@ -295,6 +275,18 @@ __attribute__((__unused__)) static void foo(void){return;}]],
[compiler does not accept __attribute__ on return types]) ]
)
+AC_MSG_CHECKING([if compiler allows __attribute__ prototype args])
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[
+#include <stdlib.h>
+typedef void foo(const char *, ...) __attribute__((format(printf, 1, 2)));]],
+ [[ exit(0); ]])],
+ [ AC_MSG_RESULT([yes]) ],
+ [ AC_MSG_RESULT([no])
+ AC_DEFINE(NO_ATTRIBUTE_ON_PROTOTYPE_ARGS, 1,
+ [compiler does not accept __attribute__ on prototype args]) ]
+)
+
if test "x$no_attrib_nonnull" != "x1" ; then
AC_DEFINE([HAVE_ATTRIBUTE__NONNULL__], [1], [Have attribute nonnull])
fi
@@ -303,10 +295,11 @@ AC_ARG_WITH([rpath],
[ --without-rpath Disable auto-added -R linker paths],
[
if test "x$withval" = "xno" ; then
- need_dash_r=""
- fi
- if test "x$withval" = "xyes" ; then
- need_dash_r=1
+ rpath_opt=""
+ elif test "x$withval" = "xyes" ; then
+ rpath_opt="-R"
+ else
+ rpath_opt="$withval"
fi
]
)
@@ -321,6 +314,16 @@ AC_ARG_WITH([cflags],
fi
]
)
+
+AC_ARG_WITH([cflags-after],
+ [ --with-cflags-after Specify additional flags to pass to compiler after configure],
+ [
+ if test -n "$withval" && test "x$withval" != "xno" && \
+ test "x${withval}" != "xyes"; then
+ CFLAGS_AFTER="$withval"
+ fi
+ ]
+)
AC_ARG_WITH([cppflags],
[ --with-cppflags Specify additional flags to pass to preprocessor] ,
[
@@ -339,6 +342,15 @@ AC_ARG_WITH([ldflags],
fi
]
)
+AC_ARG_WITH([ldflags-after],
+ [ --with-ldflags-after Specify additional flags to pass to linker after configure],
+ [
+ if test -n "$withval" && test "x$withval" != "xno" && \
+ test "x${withval}" != "xyes"; then
+ LDFLAGS_AFTER="$withval"
+ fi
+ ]
+)
AC_ARG_WITH([libs],
[ --with-libs Specify additional libraries to link with],
[
@@ -368,14 +380,18 @@ AC_CHECK_HEADERS([ \
dirent.h \
endian.h \
elf.h \
+ err.h \
features.h \
fcntl.h \
floatingpoint.h \
+ fnmatch.h \
getopt.h \
glob.h \
ia.h \
iaf.h \
+ ifaddrs.h \
inttypes.h \
+ langinfo.h \
limits.h \
locale.h \
login.h \
@@ -397,17 +413,20 @@ AC_CHECK_HEADERS([ \
stdint.h \
string.h \
strings.h \
- sys/audit.h \
sys/bitypes.h \
+ sys/byteorder.h \
sys/bsdtty.h \
- sys/capability.h \
sys/cdefs.h \
sys/dir.h \
+ sys/file.h \
sys/mman.h \
+ sys/label.h \
sys/ndir.h \
sys/poll.h \
sys/prctl.h \
sys/pstat.h \
+ sys/ptrace.h \
+ sys/random.h \
sys/select.h \
sys/stat.h \
sys/stream.h \
@@ -417,6 +436,7 @@ AC_CHECK_HEADERS([ \
sys/sysmacros.h \
sys/time.h \
sys/timers.h \
+ sys/vfs.h \
time.h \
tmpdir.h \
ttyent.h \
@@ -428,6 +448,38 @@ AC_CHECK_HEADERS([ \
utmp.h \
utmpx.h \
vis.h \
+ wchar.h \
+])
+
+# On some platforms (eg SunOS4) sys/audit.h requires sys/[time|types|label.h]
+# to be included first.
+AC_CHECK_HEADERS([sys/audit.h], [], [], [
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_LABEL_H
+# include <sys/label.h>
+#endif
+])
+
+# sys/capsicum.h requires sys/types.h
+AC_CHECK_HEADERS([sys/capsicum.h], [], [], [
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+])
+
+# net/route.h requires sys/socket.h and sys/types.h.
+# sys/sysctl.h also requires sys/param.h
+AC_CHECK_HEADERS([net/route.h sys/sysctl.h], [], [], [
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#include <sys/param.h>
+#include <sys/socket.h>
])
# lastlog.h requires sys/time.h to be included first on Solaris
@@ -464,6 +516,11 @@ AC_CHECK_HEADERS([sys/un.h], [], [], [
SIA_MSG="no"
SPC_MSG="no"
SP_MSG="no"
+SPP_MSG="no"
+
+# Support for Solaris/Illumos privileges (this test is used by both
+# the --with-solaris-privs option and --with-sandbox=solaris).
+SOLARIS_PRIVS="no"
# Check for some target-specific stuff
case "$host" in
@@ -471,7 +528,7 @@ case "$host" in
# Some versions of VAC won't allow macro redefinitions at
# -qlanglevel=ansi, and autoconf 2.60 sometimes insists on using that
# particularly with older versions of vac or xlc.
- # It also throws errors about null macro argments, but these are
+ # It also throws errors about null macro arguments, but these are
# not fatal.
AC_MSG_CHECKING([if compiler allows macro redefinitions])
AC_COMPILE_IFELSE(
@@ -482,7 +539,6 @@ case "$host" in
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
CC="`echo $CC | sed 's/-qlanglvl\=ansi//g'`"
- LD="`echo $LD | sed 's/-qlanglvl\=ansi//g'`"
CFLAGS="`echo $CFLAGS | sed 's/-qlanglvl\=ansi//g'`"
CPPFLAGS="`echo $CPPFLAGS | sed 's/-qlanglvl\=ansi//g'`"
]
@@ -544,7 +600,6 @@ case "$host" in
#include <fcntl.h> ]
)
check_for_aix_broken_getaddrinfo=1
- AC_DEFINE([BROKEN_REALPATH], [1], [Define if you have a broken realpath.])
AC_DEFINE([SETEUID_BREAKS_SETUID], [1],
[Define if your platform breaks doing a seteuid before a setuid])
AC_DEFINE([BROKEN_SETREUID], [1], [Define if your setreuid() is broken])
@@ -560,6 +615,8 @@ case "$host" in
[AIX 5.2 and 5.3 (and presumably newer) require this])
AC_DEFINE([PTY_ZEROREAD], [1], [read(1) can return 0 for a non-closed fd])
AC_DEFINE([PLATFORM_SYS_DIR_UID], 2, [System dirs owned by bin (uid 2)])
+ AC_DEFINE([BROKEN_STRNDUP], 1, [strndup broken, see APAR IY61211])
+ AC_DEFINE([BROKEN_STRNLEN], 1, [strnlen broken, see APAR IY62551])
;;
*-*-android*)
AC_DEFINE([DISABLE_UTMP], [1], [Define if you don't want to use utmp])
@@ -570,13 +627,12 @@ case "$host" in
LIBS="$LIBS /usr/lib/textreadmode.o"
AC_DEFINE([HAVE_CYGWIN], [1], [Define if you are on Cygwin])
AC_DEFINE([USE_PIPES], [1], [Use PIPES instead of a socketpair()])
+ AC_DEFINE([NO_UID_RESTORATION_TEST], [1],
+ [Define to disable UID restoration test])
AC_DEFINE([DISABLE_SHADOW], [1],
[Define if you want to disable shadow passwords])
AC_DEFINE([NO_X11_UNIX_SOCKETS], [1],
[Define if X11 doesn't support AF_UNIX sockets on that system])
- AC_DEFINE([NO_IPPORT_RESERVED_CONCEPT], [1],
- [Define if the concept of ports only accessible to
- superusers isn't known])
AC_DEFINE([DISABLE_FD_PASSING], [1],
[Define if your platform needs to skip post auth
file descriptor passing])
@@ -621,7 +677,7 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
[Prepend the address family to IP tunnel traffic])
m4_pattern_allow([AU_IPv])
- AC_CHECK_DECL([AU_IPv4], [],
+ AC_CHECK_DECL([AU_IPv4], [],
AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])
[#include <bsm/audit.h>]
AC_DEFINE([LASTLOG_WRITE_PUTUTXLINE], [1],
@@ -632,24 +688,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
supported by bsd-setproctitle.c])
AC_CHECK_FUNCS([sandbox_init])
AC_CHECK_HEADERS([sandbox.h])
+ AC_CHECK_LIB([sandbox], [sandbox_apply], [
+ SSHDLIBS="$SSHDLIBS -lsandbox"
+ ])
+ # proc_pidinfo()-based closefrom() replacement.
+ AC_CHECK_HEADERS([libproc.h])
+ AC_CHECK_FUNCS([proc_pidinfo])
;;
*-*-dragonfly*)
SSHDLIBS="$SSHDLIBS -lcrypt"
TEST_MALLOC_OPTIONS="AFGJPRX"
;;
-*-*-haiku*)
- LIBS="$LIBS -lbsd "
- AC_CHECK_LIB([network], [socket])
- AC_DEFINE([HAVE_U_INT64_T])
- MANTYPE=man
- ;;
+*-*-haiku*)
+ LIBS="$LIBS -lbsd "
+ CFLAGS="$CFLAGS -D_BSD_SOURCE"
+ AC_CHECK_LIB([network], [socket])
+ AC_DEFINE([HAVE_U_INT64_T])
+ AC_DEFINE([DISABLE_UTMPX], [1], [no utmpx])
+ MANTYPE=man
+ ;;
*-*-hpux*)
# first we define all of the options common to all HP-UX releases
CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1"
IPADDR_IN_DISPLAY=yes
AC_DEFINE([USE_PIPES])
- AC_DEFINE([LOGIN_NO_ENDOPT], [1],
- [Define if your login program cannot handle end of options ("--")])
AC_DEFINE([LOGIN_NEEDS_UTMPX])
AC_DEFINE([LOCKED_PASSWD_STRING], ["*"],
[String used in /etc/passwd to denote locked account])
@@ -708,7 +770,7 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
PATH="$PATH:/usr/etc"
AC_DEFINE([WITH_IRIX_ARRAY], [1],
[Define if you have/want arrays
- (cluster-wide session managment, not C arrays)])
+ (cluster-wide session management, not C arrays)])
AC_DEFINE([WITH_IRIX_PROJECT], [1],
[Define if you want IRIX project management])
AC_DEFINE([WITH_IRIX_AUDIT], [1],
@@ -736,6 +798,9 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
use_pie=auto
check_for_libcrypt_later=1
check_for_openpty_ctty_bug=1
+ dnl Target SUSv3/POSIX.1-2001 plus BSD specifics.
+ dnl _DEFAULT_SOURCE is the new name for _BSD_SOURCE
+ CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE"
AC_DEFINE([PAM_TTY_KLUDGE], [1],
[Work around problematic Linux PAM modules handling of PAM_TTY])
AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"],
@@ -764,9 +829,36 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
[Prepend the address family to IP tunnel traffic])
fi
+ AC_CHECK_HEADER([linux/if.h],
+ AC_DEFINE([SYS_RDOMAIN_LINUX], [1],
+ [Support routing domains using Linux VRF]), [], [
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+ ])
AC_CHECK_HEADERS([linux/seccomp.h linux/filter.h linux/audit.h], [],
[], [#include <linux/types.h>])
- AC_CHECK_FUNCS([prctl])
+ # Obtain MIPS ABI
+ case "$host" in
+ mips*)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if _MIPS_SIM != _ABIO32
+#error
+#endif
+ ]])],[mips_abi="o32"],[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if _MIPS_SIM != _ABIN32
+#error
+#endif
+ ]])],[mips_abi="n32"],[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if _MIPS_SIM != _ABI64
+#error
+#endif
+ ]])],[mips_abi="n64"],[AC_MSG_ERROR([unknown MIPS ABI])
+ ])
+ ])
+ ])
+ ;;
+ esac
AC_MSG_CHECKING([for seccomp architecture])
seccomp_audit_arch=
case "$host" in
@@ -776,14 +868,55 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
i*86-*)
seccomp_audit_arch=AUDIT_ARCH_I386
;;
- arm*-*)
+ arm*-*)
seccomp_audit_arch=AUDIT_ARCH_ARM
- ;;
+ ;;
+ aarch64*-*)
+ seccomp_audit_arch=AUDIT_ARCH_AARCH64
+ ;;
+ s390x-*)
+ seccomp_audit_arch=AUDIT_ARCH_S390X
+ ;;
+ s390-*)
+ seccomp_audit_arch=AUDIT_ARCH_S390
+ ;;
+ powerpc64-*)
+ seccomp_audit_arch=AUDIT_ARCH_PPC64
+ ;;
+ powerpc64le-*)
+ seccomp_audit_arch=AUDIT_ARCH_PPC64LE
+ ;;
+ mips-*)
+ seccomp_audit_arch=AUDIT_ARCH_MIPS
+ ;;
+ mipsel-*)
+ seccomp_audit_arch=AUDIT_ARCH_MIPSEL
+ ;;
+ mips64-*)
+ case "$mips_abi" in
+ "n32")
+ seccomp_audit_arch=AUDIT_ARCH_MIPS64N32
+ ;;
+ "n64")
+ seccomp_audit_arch=AUDIT_ARCH_MIPS64
+ ;;
+ esac
+ ;;
+ mips64el-*)
+ case "$mips_abi" in
+ "n32")
+ seccomp_audit_arch=AUDIT_ARCH_MIPSEL64N32
+ ;;
+ "n64")
+ seccomp_audit_arch=AUDIT_ARCH_MIPSEL64
+ ;;
+ esac
+ ;;
esac
if test "x$seccomp_audit_arch" != "x" ; then
AC_MSG_RESULT(["$seccomp_audit_arch"])
- AC_DEFINE_UNQUOTED([SECCOMP_AUDIT_ARCH], [$seccomp_audit_arch],
- [Specify the system call convention in use])
+ AC_DEFINE_UNQUOTED([SECCOMP_AUDIT_ARCH], [$seccomp_audit_arch],
+ [Specify the system call convention in use])
else
AC_MSG_RESULT([architecture not supported])
fi
@@ -795,16 +928,15 @@ mips-sony-bsd|mips-sony-newsos4)
*-*-netbsd*)
check_for_libcrypt_before=1
if test "x$withval" != "xno" ; then
- need_dash_r=1
+ rpath_opt="-R"
fi
+ CPPFLAGS="$CPPFLAGS -D_OPENBSD_SOURCE"
AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way])
AC_CHECK_HEADER([net/if_tap.h], ,
AC_DEFINE([SSH_TUN_NO_L2], [1], [No layer 2 tunnel support]))
AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
[Prepend the address family to IP tunnel traffic])
TEST_MALLOC_OPTIONS="AJRX"
- AC_DEFINE([BROKEN_STRNVIS], [1],
- [NetBSD strnvis argument order is swapped compared to OpenBSD])
AC_DEFINE([BROKEN_READ_COMPARISON], [1],
[NetBSD read function is sometimes redirected, breaking atomicio comparisons against it])
;;
@@ -815,8 +947,6 @@ mips-sony-bsd|mips-sony-newsos4)
AC_CHECK_HEADER([net/if_tap.h], ,
AC_DEFINE([SSH_TUN_NO_L2], [1], [No layer 2 tunnel support]))
AC_DEFINE([BROKEN_GLOB], [1], [FreeBSD glob does not do what we need])
- AC_DEFINE([BROKEN_STRNVIS], [1],
- [FreeBSD strnvis argument order is swapped compared to OpenBSD])
TEST_MALLOC_OPTIONS="AJRX"
# Preauth crypto occasionally uses file descriptors for crypto offload
# and will crash if they cannot be opened.
@@ -834,7 +964,6 @@ mips-sony-bsd|mips-sony-newsos4)
conf_wtmp_location=/usr/adm/wtmp
maildir=/usr/spool/mail
AC_DEFINE([HAVE_NEXT], [1], [Define if you are on NeXT])
- AC_DEFINE([BROKEN_REALPATH])
AC_DEFINE([USE_PIPES])
AC_DEFINE([BROKEN_SAVED_UIDS], [1], [Needed for NeXT])
;;
@@ -849,13 +978,10 @@ mips-sony-bsd|mips-sony-newsos4)
;;
*-*-solaris*)
if test "x$withval" != "xno" ; then
- need_dash_r=1
+ rpath_opt="-R"
fi
AC_DEFINE([PAM_SUN_CODEBASE])
AC_DEFINE([LOGIN_NEEDS_UTMPX])
- AC_DEFINE([LOGIN_NEEDS_TERM], [1],
- [Some versions of /bin/login need the TERM supplied
- on the commandline])
AC_DEFINE([PAM_TTY_KLUDGE])
AC_DEFINE([SSHPAM_CHAUTHTOK_NEEDS_RUID], [1],
[Define if pam_chauthtok wants real uid set
@@ -881,13 +1007,17 @@ mips-sony-bsd|mips-sony-newsos4)
else
AC_MSG_RESULT([no])
fi
+ AC_CHECK_FUNCS([setpflags])
+ AC_CHECK_FUNCS([setppriv])
+ AC_CHECK_FUNCS([priv_basicset])
+ AC_CHECK_HEADERS([priv.h])
AC_ARG_WITH([solaris-contracts],
[ --with-solaris-contracts Enable Solaris process contracts (experimental)],
[
AC_CHECK_LIB([contract], [ct_tmpl_activate],
[ AC_DEFINE([USE_SOLARIS_PROCESS_CONTRACTS], [1],
[Define if you have Solaris process contracts])
- SSHDLIBS="$SSHDLIBS -lcontract"
+ LIBS="$LIBS -lcontract"
SPC_MSG="yes" ], )
],
)
@@ -897,10 +1027,29 @@ mips-sony-bsd|mips-sony-newsos4)
AC_CHECK_LIB([project], [setproject],
[ AC_DEFINE([USE_SOLARIS_PROJECTS], [1],
[Define if you have Solaris projects])
- SSHDLIBS="$SSHDLIBS -lproject"
+ LIBS="$LIBS -lproject"
SP_MSG="yes" ], )
],
)
+ AC_ARG_WITH([solaris-privs],
+ [ --with-solaris-privs Enable Solaris/Illumos privileges (experimental)],
+ [
+ AC_MSG_CHECKING([for Solaris/Illumos privilege support])
+ if test "x$ac_cv_func_setppriv" = "xyes" -a \
+ "x$ac_cv_header_priv_h" = "xyes" ; then
+ SOLARIS_PRIVS=yes
+ AC_MSG_RESULT([found])
+ AC_DEFINE([NO_UID_RESTORATION_TEST], [1],
+ [Define to disable UID restoration test])
+ AC_DEFINE([USE_SOLARIS_PRIVS], [1],
+ [Define if you have Solaris privileges])
+ SPP_MSG="yes"
+ else
+ AC_MSG_RESULT([not found])
+ AC_MSG_ERROR([*** must have support for Solaris privileges to use --with-solaris-privs])
+ fi
+ ],
+ )
TEST_SHELL=$SHELL # let configure find us a capable shell
;;
*-*-sunos4*)
@@ -911,6 +1060,7 @@ mips-sony-bsd|mips-sony-newsos4)
conf_wtmp_location=/var/adm/wtmp
conf_lastlog_location=/var/adm/lastlog
AC_DEFINE([USE_PIPES])
+ AC_DEFINE([DISABLE_UTMPX], [1], [no utmpx])
;;
*-ncr-sysv*)
LIBS="$LIBS -lc89"
@@ -957,21 +1107,18 @@ mips-sony-bsd|mips-sony-newsos4)
AC_DEFINE([BROKEN_SETREUID])
AC_DEFINE([BROKEN_SETREGID])
AC_DEFINE([PASSWD_NEEDS_USERNAME])
+ AC_DEFINE([BROKEN_TCGETATTR_ICANON])
TEST_SHELL=$SHELL # let configure find us a capable shell
+ check_for_libcrypt_later=1
case "$host" in
*-*-sysv5SCO_SV*) # SCO OpenServer 6.x
maildir=/var/spool/mail
- AC_DEFINE([BROKEN_LIBIAF], [1],
- [ia_uinfo routines not supported by OS yet])
AC_DEFINE([BROKEN_UPDWTMPX])
AC_CHECK_LIB([prot], [getluid], [ LIBS="$LIBS -lprot"
AC_CHECK_FUNCS([getluid setluid], , , [-lprot])
- AC_DEFINE([HAVE_SECUREWARE])
- AC_DEFINE([DISABLE_SHADOW])
], , )
;;
*) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"])
- check_for_libcrypt_later=1
;;
esac
;;
@@ -1004,40 +1151,6 @@ mips-sony-bsd|mips-sony-newsos4)
TEST_SHELL=$SHELL # let configure find us a capable shell
SKIP_DISABLE_LASTLOG_DEFINE=yes
;;
-*-*-unicosmk*)
- AC_DEFINE([NO_SSH_LASTLOG], [1],
- [Define if you don't want to use lastlog in session.c])
- AC_DEFINE([SETEUID_BREAKS_SETUID])
- AC_DEFINE([BROKEN_SETREUID])
- AC_DEFINE([BROKEN_SETREGID])
- AC_DEFINE([USE_PIPES])
- AC_DEFINE([DISABLE_FD_PASSING])
- LDFLAGS="$LDFLAGS"
- LIBS="$LIBS -lgen -lrsc -lshare -luex -lacm"
- MANTYPE=cat
- ;;
-*-*-unicosmp*)
- AC_DEFINE([SETEUID_BREAKS_SETUID])
- AC_DEFINE([BROKEN_SETREUID])
- AC_DEFINE([BROKEN_SETREGID])
- AC_DEFINE([WITH_ABBREV_NO_TTY])
- AC_DEFINE([USE_PIPES])
- AC_DEFINE([DISABLE_FD_PASSING])
- LDFLAGS="$LDFLAGS"
- LIBS="$LIBS -lgen -lacid -ldb"
- MANTYPE=cat
- ;;
-*-*-unicos*)
- AC_DEFINE([SETEUID_BREAKS_SETUID])
- AC_DEFINE([BROKEN_SETREUID])
- AC_DEFINE([BROKEN_SETREGID])
- AC_DEFINE([USE_PIPES])
- AC_DEFINE([DISABLE_FD_PASSING])
- AC_DEFINE([NO_SSH_LASTLOG])
- LDFLAGS="$LDFLAGS -Wl,-Dmsglevel=334:fatal"
- LIBS="$LIBS -lgen -lrsc -lshare -luex -lacm"
- MANTYPE=cat
- ;;
*-dec-osf*)
AC_MSG_CHECKING([for Digital Unix SIA])
no_osfsia=""
@@ -1091,15 +1204,32 @@ mips-sony-bsd|mips-sony-newsos4)
*-*-ultrix*)
AC_DEFINE([BROKEN_GETGROUPS], [1], [getgroups(0,NULL) will return -1])
- AC_DEFINE([BROKEN_MMAP], [1], [Ultrix mmap can't map files])
- AC_DEFINE([NEED_SETPGRP])
+ AC_DEFINE([NEED_SETPGRP], [1], [Need setpgrp to for controlling tty])
AC_DEFINE([HAVE_SYS_SYSLOG_H], [1], [Force use of sys/syslog.h on Ultrix])
+ AC_DEFINE([DISABLE_UTMPX], [1], [Disable utmpx])
+ # DISABLE_FD_PASSING so that we call setpgrp as root, otherwise we
+ # don't get a controlling tty.
+ AC_DEFINE([DISABLE_FD_PASSING], [1], [Need to call setpgrp as root])
+ # On Ultrix some headers are not protected against multiple includes,
+ # so we create wrappers and put it where the compiler will find it.
+ AC_MSG_WARN([creating compat wrappers for headers])
+ mkdir -p netinet
+ for header in netinet/ip.h netdb.h resolv.h; do
+ name=`echo $header | tr 'a-z/.' 'A-Z__'`
+ cat >$header <<EOD
+#ifndef _SSH_COMPAT_${name}
+#define _SSH_COMPAT_${name}
+#include "/usr/include/${header}"
+#endif
+EOD
+ done
;;
*-*-lynxos)
- CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__"
- AC_DEFINE([BROKEN_SETVBUF], [1], [LynxOS has broken setvbuf() implementation])
- ;;
+ CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__"
+ AC_DEFINE([BROKEN_SETVBUF], [1],
+ [LynxOS has broken setvbuf() implementation])
+ ;;
esac
AC_MSG_CHECKING([compiler and flags for sanity])
@@ -1114,7 +1244,6 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]], [[ exit(0); ]])],
dnl Checks for header files.
# Checks for libraries.
-AC_CHECK_FUNC([yp_match], , [AC_CHECK_LIB([nsl], [yp_match])])
AC_CHECK_FUNC([setsockopt], , [AC_CHECK_LIB([socket], [setsockopt])])
dnl IRIX and Solaris 2.5.1 have dirname() in libgen
@@ -1160,21 +1289,22 @@ AC_CHECK_FUNC([getspnam], ,
AC_SEARCH_LIBS([basename], [gen], [AC_DEFINE([HAVE_BASENAME], [1],
[Define if you have the basename function.])])
-dnl zlib is required
+dnl zlib defaults to enabled
+zlib=yes
AC_ARG_WITH([zlib],
[ --with-zlib=PATH Use zlib in PATH],
[ if test "x$withval" = "xno" ; then
- AC_MSG_ERROR([*** zlib is required ***])
+ zlib=no
elif test "x$withval" != "xyes"; then
if test -d "$withval/lib"; then
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}"
else
LDFLAGS="-L${withval}/lib ${LDFLAGS}"
fi
else
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval} ${rpath_opt}${withval} ${LDFLAGS}"
else
LDFLAGS="-L${withval} ${LDFLAGS}"
fi
@@ -1187,15 +1317,21 @@ AC_ARG_WITH([zlib],
fi ]
)
-AC_CHECK_HEADER([zlib.h], ,[AC_MSG_ERROR([*** zlib.h missing - please install first or check config.log ***])])
-AC_CHECK_LIB([z], [deflate], ,
+AC_MSG_CHECKING([for zlib])
+if test "x${zlib}" = "xno"; then
+ AC_MSG_RESULT([no])
+else
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([WITH_ZLIB], [1], [Enable zlib])
+ AC_CHECK_HEADER([zlib.h], ,[AC_MSG_ERROR([*** zlib.h missing - please install first or check config.log ***])])
+ AC_CHECK_LIB([z], [deflate], ,
[
saved_CPPFLAGS="$CPPFLAGS"
saved_LDFLAGS="$LDFLAGS"
save_LIBS="$LIBS"
dnl Check default zlib install dir
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L/usr/local/lib -R/usr/local/lib ${saved_LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L/usr/local/lib ${rpath_opt}/usr/local/lib ${saved_LDFLAGS}"
else
LDFLAGS="-L/usr/local/lib ${saved_LDFLAGS}"
fi
@@ -1207,18 +1343,18 @@ AC_CHECK_LIB([z], [deflate], ,
]
)
]
-)
+ )
-AC_ARG_WITH([zlib-version-check],
+ AC_ARG_WITH([zlib-version-check],
[ --without-zlib-version-check Disable zlib version check],
[ if test "x$withval" = "xno" ; then
zlib_check_nonfatal=1
fi
]
-)
+ )
-AC_MSG_CHECKING([for possibly buggy zlib])
-AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+ AC_MSG_CHECKING([for possibly buggy zlib])
+ AC_RUN_IFELSE([AC_LANG_PROGRAM([[
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>
@@ -1256,7 +1392,8 @@ See http://www.gzip.org/zlib/ for details.])
fi
],
[ AC_MSG_WARN([cross compiling: not checking zlib version]) ]
-)
+ )
+fi
dnl UnixWare 2.x
AC_CHECK_FUNC([strcasecmp],
@@ -1278,10 +1415,37 @@ AC_SEARCH_LIBS([openpty], [util bsd])
AC_SEARCH_LIBS([updwtmp], [util bsd])
AC_CHECK_FUNCS([fmt_scaled scan_scaled login logout openpty updwtmp logwtmp])
-# On some platforms, inet_ntop may be found in libresolv or libnsl.
+# On some platforms, inet_ntop and gethostbyname may be found in libresolv
+# or libnsl.
AC_SEARCH_LIBS([inet_ntop], [resolv nsl])
+AC_SEARCH_LIBS([gethostbyname], [resolv nsl])
+# "Particular Function Checks"
+# see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html
AC_FUNC_STRFTIME
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
+# autoconf doesn't have AC_FUNC_CALLOC so fake it if malloc returns NULL;
+AC_MSG_CHECKING([if calloc(0, N) returns non-null])
+AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[ #include <stdlib.h> ]],
+ [[ void *p = calloc(0, 1); exit(p == NULL); ]]
+ )],
+ [ func_calloc_0_nonnull=yes ],
+ [ func_calloc_0_nonnull=no ],
+ [ AC_MSG_WARN([cross compiling: assuming same as malloc])
+ func_calloc_0_nonnull="$ac_cv_func_malloc_0_nonnull"]
+)
+AC_MSG_RESULT([$func_calloc_0_nonnull])
+
+if test "x$func_calloc_0_nonnull" = "xyes"; then
+ AC_DEFINE(HAVE_CALLOC, 1, [calloc(0, x) returns non-null])
+else
+ AC_DEFINE(HAVE_CALLOC, 0, [calloc(0, x) returns NULL])
+ AC_DEFINE(calloc, rpl_calloc,
+ [Define to rpl_calloc if the replacement function should be used.])
+fi
# Check for ALTDIRFUNC glob() extension
AC_MSG_CHECKING([for GLOB_ALTDIRFUNC support])
@@ -1337,6 +1501,9 @@ g.gl_statv = NULL;
AC_CHECK_DECLS([GLOB_NOMATCH], , , [#include <glob.h>])
+AC_CHECK_DECL([VIS_ALL], ,
+ AC_DEFINE(BROKEN_STRNVIS, 1, [missing VIS_ALL]), [#include <vis.h>])
+
AC_MSG_CHECKING([whether struct dirent allocates space for d_name])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
@@ -1367,89 +1534,52 @@ else
AC_MSG_RESULT([no])
fi
-# Check whether user wants S/Key support
-SKEY_MSG="no"
-AC_ARG_WITH([skey],
- [ --with-skey[[=PATH]] Enable S/Key support (optionally in PATH)],
- [
- if test "x$withval" != "xno" ; then
-
- if test "x$withval" != "xyes" ; then
- CPPFLAGS="$CPPFLAGS -I${withval}/include"
- LDFLAGS="$LDFLAGS -L${withval}/lib"
- fi
-
- AC_DEFINE([SKEY], [1], [Define if you want S/Key support])
- LIBS="-lskey $LIBS"
- SKEY_MSG="yes"
-
- AC_MSG_CHECKING([for s/key support])
- AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([[
-#include <stdio.h>
-#include <skey.h>
- ]], [[
- char *ff = skey_keyinfo(""); ff="";
- exit(0);
- ]])],
- [AC_MSG_RESULT([yes])],
- [
- AC_MSG_RESULT([no])
- AC_MSG_ERROR([** Incomplete or missing s/key libraries.])
- ])
- AC_MSG_CHECKING([if skeychallenge takes 4 arguments])
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#include <stdio.h>
-#include <skey.h>
- ]], [[
- (void)skeychallenge(NULL,"name","",0);
- ]])],
- [
- AC_MSG_RESULT([yes])
- AC_DEFINE([SKEYCHALLENGE_4ARG], [1],
- [Define if your skeychallenge()
- function takes 4 arguments (NetBSD)])],
- [
- AC_MSG_RESULT([no])
- ])
- fi
- ]
-)
-
# Check whether user wants to use ldns
LDNS_MSG="no"
AC_ARG_WITH(ldns,
[ --with-ldns[[=PATH]] Use ldns for DNSSEC support (optionally in PATH)],
- [
- if test "x$withval" != "xno" ; then
-
- if test "x$withval" != "xyes" ; then
- CPPFLAGS="$CPPFLAGS -I${withval}/include"
- LDFLAGS="$LDFLAGS -L${withval}/lib"
- fi
-
- AC_DEFINE(HAVE_LDNS, 1, [Define if you want ldns support])
- LIBS="-lldns $LIBS"
- LDNS_MSG="yes"
+ [
+ ldns=""
+ if test "x$withval" = "xyes" ; then
+ AC_PATH_TOOL([LDNSCONFIG], [ldns-config], [no])
+ if test "x$LDNSCONFIG" = "xno"; then
+ LIBS="-lldns $LIBS"
+ ldns=yes
+ else
+ LIBS="$LIBS `$LDNSCONFIG --libs`"
+ CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`"
+ ldns=yes
+ fi
+ elif test "x$withval" != "xno" ; then
+ CPPFLAGS="$CPPFLAGS -I${withval}/include"
+ LDFLAGS="$LDFLAGS -L${withval}/lib"
+ LIBS="-lldns $LIBS"
+ ldns=yes
+ fi
- AC_MSG_CHECKING([for ldns support])
- AC_LINK_IFELSE(
- [AC_LANG_SOURCE([[
+ # Verify that it works.
+ if test "x$ldns" = "xyes" ; then
+ AC_DEFINE(HAVE_LDNS, 1, [Define if you want ldns support])
+ LDNS_MSG="yes"
+ AC_MSG_CHECKING([for ldns support])
+ AC_LINK_IFELSE(
+ [AC_LANG_SOURCE([[
#include <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
#include <ldns/ldns.h>
int main() { ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); status=LDNS_STATUS_OK; exit(0); }
- ]])
- ],
- [AC_MSG_RESULT(yes)],
+ ]])
+ ],
+ [AC_MSG_RESULT(yes)],
[
AC_MSG_RESULT(no)
AC_MSG_ERROR([** Incomplete or missing ldns libraries.])
])
- fi
- ]
-)
+ fi
+])
# Check whether user wants libedit support
LIBEDIT_MSG="no"
@@ -1460,7 +1590,7 @@ AC_ARG_WITH([libedit],
AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no])
if test "x$PKGCONFIG" != "xno"; then
AC_MSG_CHECKING([if $PKGCONFIG knows about libedit])
- if "$PKGCONFIG" libedit; then
+ if "$PKGCONFIG" libedit; then
AC_MSG_RESULT([yes])
use_pkgconfig_for_libedit=yes
else
@@ -1469,8 +1599,8 @@ AC_ARG_WITH([libedit],
fi
else
CPPFLAGS="$CPPFLAGS -I${withval}/include"
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}"
else
LDFLAGS="-L${withval}/lib ${LDFLAGS}"
fi
@@ -1531,9 +1661,9 @@ AC_ARG_WITH([audit],
AC_CHECK_FUNCS([getaudit_addr aug_get_machine])
AC_DEFINE([USE_BSM_AUDIT], [1], [Use BSM audit module])
if test "$sol2ver" -ge 11; then
- SSHDLIBS="$SSHDLIBS -lscf"
- AC_DEFINE([BROKEN_BSM_API], [1],
- [The system has incomplete BSM API])
+ SSHDLIBS="$SSHDLIBS -lscf"
+ AC_DEFINE([BROKEN_BSM_API], [1],
+ [The system has incomplete BSM API])
fi
;;
linux)
@@ -1605,12 +1735,27 @@ if test "x$use_pie" != "xno"; then
fi
fi
+AC_MSG_CHECKING([whether -fPIC is accepted])
+SAVED_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -fPIC"
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM( [[ #include <stdlib.h> ]], [[ exit(0); ]] )],
+ [AC_MSG_RESULT([yes])
+ PICFLAG="-fPIC"; ],
+ [AC_MSG_RESULT([no])
+ PICFLAG=""; ])
+CFLAGS="$SAVED_CFLAGS"
+AC_SUBST([PICFLAG])
+
dnl Checks for library functions. Please keep in alphabetical order
AC_CHECK_FUNCS([ \
Blowfish_initstate \
Blowfish_expandstate \
Blowfish_expand0state \
Blowfish_stream2word \
+ SHA256Update \
+ SHA384Update \
+ SHA512Update \
asprintf \
b64_ntop \
__b64_ntop \
@@ -1620,29 +1765,40 @@ AC_CHECK_FUNCS([ \
bcrypt_pbkdf \
bindresvport_sa \
blf_enc \
+ bzero \
cap_rights_limit \
clock \
closefrom \
dirfd \
endgrent \
+ err \
+ errx \
explicit_bzero \
fchmod \
+ fchmodat \
fchown \
+ fchownat \
+ flock \
+ fnmatch \
freeaddrinfo \
+ freezero \
fstatfs \
fstatvfs \
futimes \
getaddrinfo \
getcwd \
getgrouplist \
+ getline \
getnameinfo \
getopt \
+ getpagesize \
getpeereid \
getpeerucred \
getpgid \
- getpgrp \
_getpty \
getrlimit \
+ getrandom \
+ getsid \
getttyent \
glob \
group_from_gid \
@@ -1650,24 +1806,28 @@ AC_CHECK_FUNCS([ \
inet_ntoa \
inet_ntop \
innetgr \
+ llabs \
+ localtime_r \
login_getcapbool \
- mblen \
md5_crypt \
+ memmem \
memmove \
memset_s \
mkdtemp \
- mmap \
ngetaddrinfo \
nsleep \
ogetaddrinfo \
openlog_r \
+ pledge \
poll \
prctl \
pstat \
+ raise \
readpassphrase \
reallocarray \
realpath \
recvmsg \
+ recallocarray \
rresvport_af \
sendmsg \
setdtablesize \
@@ -1692,14 +1852,17 @@ AC_CHECK_FUNCS([ \
socketpair \
statfs \
statvfs \
+ strcasestr \
strdup \
strerror \
strlcat \
strlcpy \
strmode \
+ strndup \
strnlen \
strnvis \
strptime \
+ strsignal \
strtonum \
strtoll \
strtoul \
@@ -1711,13 +1874,38 @@ AC_CHECK_FUNCS([ \
truncate \
unsetenv \
updwtmpx \
+ utimensat \
user_from_uid \
usleep \
vasprintf \
vsnprintf \
waitpid \
+ warn \
])
+AC_CHECK_DECLS([bzero, memmem])
+
+dnl Wide character support.
+AC_CHECK_FUNCS([mblen mbtowc nl_langinfo wcwidth])
+
+TEST_SSH_UTF8=${TEST_SSH_UTF8:=yes}
+AC_MSG_CHECKING([for utf8 locale support])
+AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM([[
+#include <locale.h>
+#include <stdlib.h>
+ ]], [[
+ char *loc = setlocale(LC_CTYPE, "en_US.UTF-8");
+ if (loc != NULL)
+ exit(0);
+ exit(1);
+ ]])],
+ AC_MSG_RESULT(yes),
+ [AC_MSG_RESULT(no)
+ TEST_SSH_UTF8=no],
+ AC_MSG_WARN([cross compiling: assuming yes])
+)
+
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[ #include <ctype.h> ]],
@@ -1725,13 +1913,39 @@ AC_LINK_IFELSE(
[AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).])
])
-# PKCS11 depends on OpenSSL.
-if test "x$openssl" = "xyes" ; then
- # PKCS#11 support requires dlopen() and co
- AC_SEARCH_LIBS([dlopen], [dl],
- [AC_DEFINE([ENABLE_PKCS11], [], [Enable for PKCS#11 support])]
- )
-fi
+disable_pkcs11=
+AC_ARG_ENABLE([pkcs11],
+ [ --disable-pkcs11 disable PKCS#11 support code [no]],
+ [
+ if test "x$enableval" = "xno" ; then
+ disable_pkcs11=1
+ fi
+ ]
+)
+
+disable_sk=
+AC_ARG_ENABLE([security-key],
+ [ --disable-security-key disable U2F/FIDO support code [no]],
+ [
+ if test "x$enableval" = "xno" ; then
+ disable_sk=1
+ fi
+ ]
+)
+enable_sk_internal=
+AC_ARG_WITH([security-key-builtin],
+ [ --with-security-key-builtin include builtin U2F/FIDO support],
+ [
+ if test "x$withval" != "xno" ; then
+ enable_sk_internal=yes
+ fi
+ ]
+)
+test "x$disable_sk" != "x" && enable_sk_internal=""
+
+AC_SEARCH_LIBS([dlopen], [dl])
+AC_CHECK_FUNCS([dlopen])
+AC_CHECK_DECL([RTLD_NOW], [], [], [#include <dlfcn.h>])
# IRIX has a const char return value for gai_strerror()
AC_CHECK_FUNCS([gai_strerror], [
@@ -1755,8 +1969,20 @@ AC_SEARCH_LIBS([nanosleep], [rt posix4], [AC_DEFINE([HAVE_NANOSLEEP], [1],
AC_SEARCH_LIBS([clock_gettime], [rt],
[AC_DEFINE([HAVE_CLOCK_GETTIME], [1], [Have clock_gettime])])
+dnl check if we need -D_REENTRANT for localtime_r declaration.
+AC_CHECK_DECL([localtime_r], [],
+ [ saved_CPPFLAGS="$CFLAGS"
+ CPPFLAGS="$CPPFLAGS -D_REENTRANT"
+ unset ac_cv_have_decl_localtime_r
+ AC_CHECK_DECL([localtime_r], [],
+ [ CPPFLAGS="$saved_CPPFLAGS" ],
+ [ #include <time.h> ]
+ )
+ ],
+ [ #include <time.h> ]
+)
+
dnl Make sure prototypes are defined for these before using them.
-AC_CHECK_DECL([getrusage], [AC_CHECK_FUNCS([getrusage])])
AC_CHECK_DECL([strsep],
[AC_CHECK_FUNCS([strsep])],
[],
@@ -1775,10 +2001,11 @@ AC_CHECK_DECL([tcsendbreak],
AC_CHECK_DECLS([h_errno], , ,[#include <netdb.h>])
-AC_CHECK_DECLS([SHUT_RD], , ,
+AC_CHECK_DECLS([SHUT_RD, getpeereid], , ,
[
#include <sys/types.h>
#include <sys/socket.h>
+#include <unistd.h>
])
AC_CHECK_DECLS([O_NONBLOCK], , ,
@@ -1792,7 +2019,7 @@ AC_CHECK_DECLS([O_NONBLOCK], , ,
#endif
])
-AC_CHECK_DECLS([writev], , , [
+AC_CHECK_DECLS([readv, writev], , , [
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
@@ -1883,6 +2110,16 @@ 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_MSG_RESULT([yes]),
+ [AC_MSG_RESULT([no])
+ AC_DEFINE([FFLUSH_NULL_BUG], [1],
+ [define if fflush(NULL) does not work])],
+ AC_MSG_WARN([cross compiling: assuming working])
+)
+
dnl Checks for time functions
AC_CHECK_FUNCS([gettimeofday time])
dnl Checks for utmp functions
@@ -1915,7 +2152,7 @@ if test "x$ac_cv_func_snprintf" = "xyes" ; then
[[
char b[5];
snprintf(b,5,"123456789");
- exit(b[4]!='\0');
+ exit(b[4]!='\0');
]])],
[AC_MSG_RESULT([yes])],
[
@@ -1928,6 +2165,29 @@ if test "x$ac_cv_func_snprintf" = "xyes" ; then
)
fi
+if test "x$ac_cv_func_snprintf" = "xyes" ; then
+ AC_MSG_CHECKING([whether snprintf understands %zu])
+ AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <stdio.h>
+ ]],
+ [[
+ size_t a = 1, b = 2;
+ char z[128];
+ snprintf(z, sizeof z, "%zu%zu", a, b);
+ exit(strcmp(z, "12"));
+ ]])],
+ [AC_MSG_RESULT([yes])],
+ [
+ AC_MSG_RESULT([no])
+ AC_DEFINE([BROKEN_SNPRINTF], [1],
+ [snprintf does not understand %zu])
+ ],
+ [ AC_MSG_WARN([cross compiling: Assuming working snprintf()]) ]
+ )
+fi
+
# We depend on vsnprintf returning the right thing on overflow: the
# number of characters it tried to create (as per SUSv3)
if test "x$ac_cv_func_vsnprintf" = "xyes" ; then
@@ -2219,7 +2479,90 @@ if test "x$check_for_conflicting_getspnam" = "x1"; then
)
fi
-AC_FUNC_GETPGRP
+dnl NetBSD added an strnvis and unfortunately made it incompatible with the
+dnl existing one in OpenBSD and Linux's libbsd (the former having existed
+dnl for over ten years). Despite this incompatibility being reported during
+dnl development (see http://gnats.netbsd.org/44977) they still shipped it.
+dnl Even more unfortunately FreeBSD and later MacOS picked up this incompatible
+dnl implementation. Try to detect this mess, and assume the only safe option
+dnl if we're cross compiling.
+dnl
+dnl OpenBSD, 2001: strnvis(char *dst, const char *src, size_t dlen, int flag);
+dnl NetBSD: 2012, strnvis(char *dst, size_t dlen, const char *src, int flag);
+if test "x$ac_cv_func_strnvis" = "xyes"; then
+ AC_MSG_CHECKING([for working strnvis])
+ AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM([[
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vis.h>
+static void sighandler(int sig) { _exit(1); }
+ ]], [[
+ char dst[16];
+
+ signal(SIGSEGV, sighandler);
+ if (strnvis(dst, "src", 4, 0) && strcmp(dst, "src") == 0)
+ exit(0);
+ exit(1)
+ ]])],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_DEFINE([BROKEN_STRNVIS], [1], [strnvis detected broken])],
+ [AC_MSG_WARN([cross compiling: assuming broken])
+ AC_DEFINE([BROKEN_STRNVIS], [1], [strnvis assumed broken])]
+ )
+fi
+
+AC_MSG_CHECKING([if SA_RESTARTed signals interrupt select()])
+AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM([[
+#ifdef HAVE_SYS_SELECT
+# include <sys/select.h>
+#endif
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <signal.h>
+static void sighandler(int sig) { }
+ ]], [[
+ int r;
+ pid_t pid;
+ struct sigaction sa;
+
+ sa.sa_handler = sighandler;
+ sa.sa_flags = SA_RESTART;
+ (void)sigaction(SIGTERM, &sa, NULL);
+ if ((pid = fork()) == 0) { /* child */
+ pid = getppid();
+ sleep(1);
+ kill(pid, SIGTERM);
+ sleep(1);
+ if (getppid() == pid) /* if parent did not exit, shoot it */
+ kill(pid, SIGKILL);
+ exit(0);
+ } else { /* parent */
+ r = select(0, NULL, NULL, NULL, NULL);
+ }
+ exit(r == -1 ? 0 : 1);
+ ]])],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_DEFINE([NO_SA_RESTART], [1],
+ [SA_RESTARTed signals do no interrupt select])],
+ [AC_MSG_WARN([cross compiling: assuming yes])]
+)
+
+AC_CHECK_FUNCS([getpgrp],[
+ AC_MSG_CHECKING([if getpgrp accepts zero args])
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[$ac_includes_default]], [[ getpgrp(); ]])],
+ [ AC_MSG_RESULT([yes])
+ AC_DEFINE([GETPGRP_VOID], [1], [getpgrp takes zero args])],
+ [ AC_MSG_RESULT([no])
+ AC_DEFINE([GETPGRP_VOID], [0], [getpgrp takes one arg])]
+ )
+])
# Search for OpenSSL
saved_CPPFLAGS="$CPPFLAGS"
@@ -2236,20 +2579,20 @@ AC_ARG_WITH([ssl-dir],
./*|../*) withval="`pwd`/$withval"
esac
if test -d "$withval/lib"; then
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}"
else
LDFLAGS="-L${withval}/lib ${LDFLAGS}"
fi
elif test -d "$withval/lib64"; then
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib64 -R${withval}/lib64 ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval}/lib64 ${rpath_opt}${withval}/lib64 ${LDFLAGS}"
else
LDFLAGS="-L${withval}/lib64 ${LDFLAGS}"
fi
else
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval} ${rpath_opt}${withval} ${LDFLAGS}"
else
LDFLAGS="-L${withval} ${LDFLAGS}"
fi
@@ -2276,10 +2619,10 @@ openssl_engine=no
AC_ARG_WITH([ssl-engine],
[ --with-ssl-engine Enable OpenSSL (hardware) ENGINE support ],
[
- if test "x$openssl" = "xno" ; then
- AC_MSG_ERROR([cannot use --with-ssl-engine when OpenSSL disabled])
- fi
if test "x$withval" != "xno" ; then
+ if test "x$openssl" = "xno" ; then
+ AC_MSG_ERROR([cannot use --with-ssl-engine when OpenSSL disabled])
+ fi
openssl_engine=yes
fi
]
@@ -2287,31 +2630,16 @@ AC_ARG_WITH([ssl-engine],
if test "x$openssl" = "xyes" ; then
LIBS="-lcrypto $LIBS"
- AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL], [1],
- [Define if your ssl headers are included
- with #include <openssl/header.h>])],
- [
- dnl Check default openssl install dir
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib ${saved_LDFLAGS}"
- else
- LDFLAGS="-L/usr/local/ssl/lib ${saved_LDFLAGS}"
- fi
- CPPFLAGS="-I/usr/local/ssl/include ${saved_CPPFLAGS}"
- AC_CHECK_HEADER([openssl/opensslv.h], ,
- [AC_MSG_ERROR([*** OpenSSL headers missing - please install first or check config.log ***])])
- AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL])],
- [
- AC_MSG_ERROR([*** Can't find recent OpenSSL libcrypto (see config.log for details) ***])
- ]
- )
- ]
- )
+ AC_TRY_LINK_FUNC([RAND_add], ,
+ [AC_MSG_ERROR([*** working libcrypto not found, check config.log])])
+ AC_CHECK_HEADER([openssl/opensslv.h], ,
+ [AC_MSG_ERROR([*** OpenSSL headers missing - please install first or check config.log ***])])
# Determine OpenSSL header version
AC_MSG_CHECKING([OpenSSL header version])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
+ #include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <openssl/opensslv.h>
@@ -2324,7 +2652,9 @@ if test "x$openssl" = "xyes" ; then
if(fd == NULL)
exit(1);
- if ((rc = fprintf(fd ,"%08x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0)
+ if ((rc = fprintf(fd, "%08lx (%s)\n",
+ (unsigned long)OPENSSL_VERSION_NUMBER,
+ OPENSSL_VERSION_TEXT)) < 0)
exit(1);
exit(0);
@@ -2342,6 +2672,9 @@ if test "x$openssl" = "xyes" ; then
]
)
+ # Determining OpenSSL library version is version dependent.
+ AC_CHECK_FUNCS([OpenSSL_version OpenSSL_version_num])
+
# Determine OpenSSL library version
AC_MSG_CHECKING([OpenSSL library version])
AC_RUN_IFELSE(
@@ -2358,9 +2691,18 @@ if test "x$openssl" = "xyes" ; then
fd = fopen(DATA,"w");
if(fd == NULL)
exit(1);
-
- if ((rc = fprintf(fd ,"%08x (%s)\n", SSLeay(),
- SSLeay_version(SSLEAY_VERSION))) <0)
+#ifndef OPENSSL_VERSION
+# define OPENSSL_VERSION SSLEAY_VERSION
+#endif
+#ifndef HAVE_OPENSSL_VERSION
+# define OpenSSL_version SSLeay_version
+#endif
+#ifndef HAVE_OPENSSL_VERSION_NUM
+# define OpenSSL_version_num SSLeay
+#endif
+ if ((rc = fprintf(fd, "%08lx (%s)\n",
+ (unsigned long)OpenSSL_version_num(),
+ OpenSSL_version(OPENSSL_VERSION))) < 0)
exit(1);
exit(0);
@@ -2369,10 +2711,20 @@ if test "x$openssl" = "xyes" ; then
ssl_library_ver=`cat conftest.ssllibver`
# Check version is supported.
case "$ssl_library_ver" in
- 0090[[0-7]]*|009080[[0-5]]*)
- AC_MSG_ERROR([OpenSSL >= 0.9.8f required (have "$ssl_library_ver")])
- ;;
- *) ;;
+ 10000*|0*)
+ AC_MSG_ERROR([OpenSSL >= 1.0.1 required (have "$ssl_library_ver")])
+ ;;
+ 100*) ;; # 1.0.x
+ 101000[[0123456]]*)
+ # https://github.com/openssl/openssl/pull/4613
+ AC_MSG_ERROR([OpenSSL 1.1.x versions prior to 1.1.0g have a bug that breaks their use with OpenSSH (have "$ssl_library_ver")])
+ ;;
+ 101*) ;; # 1.1.x
+ 200*) ;; # LibreSSL
+ 300*) ;; # OpenSSL development branch.
+ *)
+ AC_MSG_ERROR([Unknown/unsupported OpenSSL version ("$ssl_library_ver")])
+ ;;
esac
AC_MSG_RESULT([$ssl_library_ver])
],
@@ -2391,8 +2743,12 @@ if test "x$openssl" = "xyes" ; then
[AC_LANG_PROGRAM([[
#include <string.h>
#include <openssl/opensslv.h>
+ #include <openssl/crypto.h>
]], [[
- exit(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1);
+#ifndef HAVE_OPENSSL_VERSION_NUM
+# define OpenSSL_version_num SSLeay
+#endif
+ exit(OpenSSL_version_num() == OPENSSL_VERSION_NUMBER ? 0 : 1);
]])],
[
AC_MSG_RESULT([yes])
@@ -2419,8 +2775,8 @@ if test "x$openssl" = "xyes" ; then
AC_MSG_CHECKING([if programs using OpenSSL functions will link])
AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([[ #include <openssl/evp.h> ]],
- [[ SSLeay_add_all_algorithms(); ]])],
+ [AC_LANG_PROGRAM([[ #include <openssl/err.h> ]],
+ [[ ERR_load_crypto_strings(); ]])],
[
AC_MSG_RESULT([yes])
],
@@ -2430,8 +2786,8 @@ if test "x$openssl" = "xyes" ; then
LIBS="$LIBS -ldl"
AC_MSG_CHECKING([if programs using OpenSSL need -ldl])
AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([[ #include <openssl/evp.h> ]],
- [[ SSLeay_add_all_algorithms(); ]])],
+ [AC_LANG_PROGRAM([[ #include <openssl/err.h> ]],
+ [[ ERR_load_crypto_strings(); ]])],
[
AC_MSG_RESULT([yes])
],
@@ -2446,16 +2802,65 @@ if test "x$openssl" = "xyes" ; then
AC_CHECK_FUNCS([ \
BN_is_prime_ex \
DSA_generate_parameters_ex \
- EVP_DigestInit_ex \
+ EVP_CIPHER_CTX_ctrl \
EVP_DigestFinal_ex \
- EVP_MD_CTX_init \
+ EVP_DigestInit_ex \
EVP_MD_CTX_cleanup \
EVP_MD_CTX_copy_ex \
+ EVP_MD_CTX_init \
HMAC_CTX_init \
RSA_generate_key_ex \
RSA_get_default_method \
])
+ # OpenSSL_add_all_algorithms may be a macro.
+ AC_CHECK_FUNC(OpenSSL_add_all_algorithms,
+ AC_DEFINE(HAVE_OPENSSL_ADD_ALL_ALGORITHMS, 1, [as a function]),
+ AC_CHECK_DECL(OpenSSL_add_all_algorithms,
+ AC_DEFINE(HAVE_OPENSSL_ADD_ALL_ALGORITHMS, 1, [as a macro]), ,
+ [[#include <openssl/evp.h>]]
+ )
+ )
+
+ # LibreSSL/OpenSSL 1.1x API
+ AC_CHECK_FUNCS([ \
+ OPENSSL_init_crypto \
+ DH_get0_key \
+ DH_get0_pqg \
+ DH_set0_key \
+ DH_set_length \
+ DH_set0_pqg \
+ DSA_get0_key \
+ DSA_get0_pqg \
+ DSA_set0_key \
+ DSA_set0_pqg \
+ DSA_SIG_get0 \
+ DSA_SIG_set0 \
+ ECDSA_SIG_get0 \
+ ECDSA_SIG_set0 \
+ EVP_CIPHER_CTX_iv \
+ EVP_CIPHER_CTX_iv_noconst \
+ EVP_CIPHER_CTX_get_iv \
+ EVP_CIPHER_CTX_set_iv \
+ RSA_get0_crt_params \
+ RSA_get0_factors \
+ RSA_get0_key \
+ RSA_set0_crt_params \
+ RSA_set0_factors \
+ RSA_set0_key \
+ RSA_meth_free \
+ RSA_meth_dup \
+ RSA_meth_set1_name \
+ RSA_meth_get_finish \
+ RSA_meth_set_priv_enc \
+ RSA_meth_set_priv_dec \
+ RSA_meth_set_finish \
+ EVP_PKEY_get0_RSA \
+ EVP_MD_CTX_new \
+ EVP_MD_CTX_free \
+ EVP_chacha20 \
+ ])
+
if test "x$openssl_engine" = "xyes" ; then
AC_MSG_CHECKING([for OpenSSL ENGINE support])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
@@ -2534,14 +2939,11 @@ if test "x$openssl" = "xyes" ; then
[
AC_MSG_RESULT([no])
unsupported_algorithms="$unsupported_cipers \
- aes128-gcm@openssh.com aes256-gcm@openssh.com"
+ aes128-gcm@openssh.com \
+ aes256-gcm@openssh.com"
]
)
- AC_SEARCH_LIBS([EVP_CIPHER_CTX_ctrl], [crypto],
- [AC_DEFINE([HAVE_EVP_CIPHER_CTX_CTRL], [1],
- [Define if libcrypto has EVP_CIPHER_CTX_ctrl])])
-
AC_MSG_CHECKING([if EVP_DigestUpdate returns an int])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
@@ -2574,22 +2976,8 @@ if test "x$openssl" = "xyes" ; then
fi
AC_CHECK_FUNCS([crypt DES_crypt])
- # Search for SHA256 support in libc and/or OpenSSL
- AC_CHECK_FUNCS([SHA256_Update EVP_sha256], ,
- [unsupported_algorithms="$unsupported_algorithms \
- hmac-sha2-256 hmac-sha2-512 \
- diffie-hellman-group-exchange-sha256 \
- hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com"
- ]
- )
- # Search for RIPE-MD support in OpenSSL
- AC_CHECK_FUNCS([EVP_ripemd160], ,
- [unsupported_algorithms="$unsupported_algorithms \
- hmac-ripemd160
- hmac-ripemd160@openssh.com
- hmac-ripemd160-etm@openssh.com"
- ]
- )
+ # Check for SHA256, SHA384 and SHA512 support in OpenSSL
+ AC_CHECK_FUNCS([EVP_sha256 EVP_sha384 EVP_sha512])
# Check complete ECC support in OpenSSL
AC_MSG_CHECKING([whether OpenSSL has NID_X9_62_prime256v1])
@@ -2601,9 +2989,6 @@ if test "x$openssl" = "xyes" ; then
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/opensslv.h>
- #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */
- # error "OpenSSL < 0.9.8g has unreliable ECC code"
- #endif
]], [[
EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
const EVP_MD *m = EVP_sha256(); /* We need this too */
@@ -2622,9 +3007,6 @@ if test "x$openssl" = "xyes" ; then
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/opensslv.h>
- #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */
- # error "OpenSSL < 0.9.8g has unreliable ECC code"
- #endif
]], [[
EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1);
const EVP_MD *m = EVP_sha384(); /* We need this too */
@@ -2643,9 +3025,6 @@ if test "x$openssl" = "xyes" ; then
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/opensslv.h>
- #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */
- # error "OpenSSL < 0.9.8g has unreliable ECC code"
- #endif
]], [[
EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1);
const EVP_MD *m = EVP_sha512(); /* We need this too */
@@ -2680,6 +3059,10 @@ if test "x$openssl" = "xyes" ; then
if test x$enable_nistp256 = x1 || test x$enable_nistp384 = x1 || \
test x$enable_nistp521 = x1; then
AC_DEFINE(OPENSSL_HAS_ECC, [1], [OpenSSL has ECC])
+ AC_CHECK_FUNCS([EC_KEY_METHOD_new])
+ openssl_ecc=yes
+ else
+ openssl_ecc=no
fi
if test x$enable_nistp256 = x1; then
AC_DEFINE([OPENSSL_HAS_NISTP256], [1],
@@ -2687,24 +3070,30 @@ if test "x$openssl" = "xyes" ; then
TEST_SSH_ECC=yes
COMMENT_OUT_ECC=""
else
- unsupported_algorithms="$unsupported_algorithms ecdsa-sha2-nistp256 \
- ecdh-sha2-nistp256 ecdsa-sha2-nistp256-cert-v01@openssh.com"
+ unsupported_algorithms="$unsupported_algorithms \
+ ecdsa-sha2-nistp256 \
+ ecdh-sha2-nistp256 \
+ ecdsa-sha2-nistp256-cert-v01@openssh.com"
fi
if test x$enable_nistp384 = x1; then
AC_DEFINE([OPENSSL_HAS_NISTP384], [1], [libcrypto has NID_secp384r1])
TEST_SSH_ECC=yes
COMMENT_OUT_ECC=""
else
- unsupported_algorithms="$unsupported_algorithms ecdsa-sha2-nistp384 \
- ecdh-sha2-nistp384 ecdsa-sha2-nistp384-cert-v01@openssh.com"
+ unsupported_algorithms="$unsupported_algorithms \
+ ecdsa-sha2-nistp384 \
+ ecdh-sha2-nistp384 \
+ ecdsa-sha2-nistp384-cert-v01@openssh.com"
fi
if test x$enable_nistp521 = x1; then
AC_DEFINE([OPENSSL_HAS_NISTP521], [1], [libcrypto has NID_secp521r1])
TEST_SSH_ECC=yes
COMMENT_OUT_ECC=""
else
- unsupported_algorithms="$unsupported_algorithms ecdh-sha2-nistp521 \
- ecdsa-sha2-nistp521 ecdsa-sha2-nistp521-cert-v01@openssh.com"
+ unsupported_algorithms="$unsupported_algorithms \
+ ecdh-sha2-nistp521 \
+ ecdsa-sha2-nistp521 \
+ ecdsa-sha2-nistp521-cert-v01@openssh.com"
fi
AC_SUBST([TEST_SSH_ECC])
@@ -2714,6 +3103,84 @@ else
AC_CHECK_FUNCS([crypt])
fi
+# PKCS11/U2F depend on OpenSSL and dlopen().
+enable_pkcs11=yes
+enable_sk=yes
+if test "x$openssl" != "xyes" ; then
+ enable_pkcs11="disabled; missing libcrypto"
+ enable_sk="disabled; missing libcrypto"
+fi
+if test "x$openssl_ecc" != "xyes" ; then
+ enable_sk="disabled; OpenSSL has no ECC support"
+fi
+if test "x$ac_cv_func_dlopen" != "xyes" ; then
+ enable_pkcs11="disabled; missing dlopen(3)"
+ enable_sk="disabled; missing dlopen(3)"
+fi
+if test "x$ac_cv_have_decl_RTLD_NOW" != "xyes" ; then
+ enable_pkcs11="disabled; missing RTLD_NOW"
+ enable_sk="disabled; missing RTLD_NOW"
+fi
+if test ! -z "$disable_pkcs11" ; then
+ enable_pkcs11="disabled by user"
+fi
+if test ! -z "$disable_sk" ; then
+ enable_sk="disabled by user"
+fi
+
+AC_MSG_CHECKING([whether to enable PKCS11])
+if test "x$enable_pkcs11" = "xyes" ; then
+ AC_DEFINE([ENABLE_PKCS11], [], [Enable for PKCS#11 support])
+fi
+AC_MSG_RESULT([$enable_pkcs11])
+
+AC_MSG_CHECKING([whether to enable U2F])
+if test "x$enable_sk" = "xyes" ; then
+ AC_DEFINE([ENABLE_SK], [], [Enable for U2F/FIDO support])
+ AC_SUBST(SK_DUMMY_LIBRARY, [regress/misc/sk-dummy/sk-dummy.so])
+else
+ # Do not try to build sk-dummy library.
+ AC_SUBST(SK_DUMMY_LIBRARY, [""])
+fi
+AC_MSG_RESULT([$enable_sk])
+
+# Now check for built-in security key support.
+if test "x$enable_sk" = "xyes" -a "x$enable_sk_internal" = "xyes" ; then
+ AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no])
+ use_pkgconfig_for_libfido2=
+ if test "x$PKGCONFIG" != "xno"; then
+ AC_MSG_CHECKING([if $PKGCONFIG knows about libfido2])
+ if "$PKGCONFIG" libfido2; then
+ AC_MSG_RESULT([yes])
+ use_pkgconfig_for_libfido2=yes
+ else
+ AC_MSG_RESULT([no])
+ fi
+ fi
+ if test "x$use_pkgconfig_for_libfido2" = "xyes"; then
+ LIBFIDO2=`$PKGCONFIG --libs libfido2`
+ CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libfido2`"
+ else
+ LIBFIDO2="-lfido2 -lcbor"
+ fi
+ OTHERLIBS=`echo $LIBFIDO2 | sed 's/-lfido2//'`
+ AC_CHECK_LIB([fido2], [fido_init],
+ [
+ AC_SUBST([LIBFIDO2])
+ AC_DEFINE([ENABLE_SK_INTERNAL], [],
+ [Enable for built-in U2F/FIDO support])
+ enable_sk="built-in"
+ ], [ AC_MSG_ERROR([no usable libfido2 found]) ],
+ [ $OTHERLIBS ]
+ )
+ AC_CHECK_HEADER([fido.h], [],
+ AC_MSG_ERROR([missing fido.h from libfido2]))
+ AC_CHECK_HEADER([fido/credman.h], [],
+ AC_MSG_ERROR([missing fido/credman.h from libfido2]),
+ [#include <fido.h>]
+ )
+fi
+
AC_CHECK_FUNCS([ \
arc4random \
arc4random_buf \
@@ -2726,14 +3193,14 @@ AC_CHECK_LIB([iaf], [ia_openinfo], [
LIBS="$LIBS -liaf"
AC_CHECK_FUNCS([set_id], [SSHDLIBS="$SSHDLIBS -liaf"
AC_DEFINE([HAVE_LIBIAF], [1],
- [Define if system has libiaf that supports set_id])
+ [Define if system has libiaf that supports set_id])
])
])
LIBS="$saved_LIBS"
### Configure cryptographic random number support
-# Check wheter OpenSSL seeds itself
+# Check whether OpenSSL seeds itself
if test "x$openssl" = "xyes" ; then
AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded])
AC_RUN_IFELSE(
@@ -2885,6 +3352,17 @@ AC_ARG_WITH([pam],
]
)
+AC_ARG_WITH([pam-service],
+ [ --with-pam-service=name Specify PAM service name ],
+ [
+ if test "x$withval" != "xno" && \
+ test "x$withval" != "xyes" ; then
+ AC_DEFINE_UNQUOTED([SSHD_PAM_SERVICE],
+ ["$withval"], [sshd PAM service name])
+ fi
+ ]
+)
+
# Check for older PAM
if test "x$PAM_MSG" = "xyes" ; then
# Check PAM strerror arguments (old PAM)
@@ -2965,7 +3443,7 @@ fi
# Decide which sandbox style to use
sandbox_arg=""
AC_ARG_WITH([sandbox],
- [ --with-sandbox=style Specify privilege separation sandbox (no, darwin, rlimit, systrace, seccomp_filter, capsicum)],
+ [ --with-sandbox=style Specify privilege separation sandbox (no, capsicum, darwin, rlimit, seccomp_filter, systrace, pledge)],
[
if test "x$withval" = "xyes" ; then
sandbox_arg=""
@@ -3013,7 +3491,8 @@ AC_RUN_IFELSE(
select_works_with_rlimit=yes],
[AC_MSG_RESULT([no])
select_works_with_rlimit=no],
- [AC_MSG_WARN([cross compiling: assuming yes])]
+ [AC_MSG_WARN([cross compiling: assuming yes])
+ select_works_with_rlimit=yes]
)
AC_MSG_CHECKING([if setrlimit(RLIMIT_NOFILE,{0,0}) works])
@@ -3028,8 +3507,7 @@ AC_RUN_IFELSE(
#include <stdlib.h>
]],[[
struct rlimit rl_zero;
- int fd, r;
- fd_set fds;
+ int r;
rl_zero.rlim_cur = rl_zero.rlim_max = 0;
r = setrlimit(RLIMIT_NOFILE, &rl_zero);
@@ -3039,7 +3517,8 @@ AC_RUN_IFELSE(
rlimit_nofile_zero_works=yes],
[AC_MSG_RESULT([no])
rlimit_nofile_zero_works=no],
- [AC_MSG_WARN([cross compiling: assuming yes])]
+ [AC_MSG_WARN([cross compiling: assuming yes])
+ rlimit_nofile_zero_works=yes]
)
AC_MSG_CHECKING([if setrlimit RLIMIT_FSIZE works])
@@ -3061,7 +3540,13 @@ AC_RUN_IFELSE(
[AC_MSG_WARN([cross compiling: assuming yes])]
)
-if test "x$sandbox_arg" = "xsystrace" || \
+if test "x$sandbox_arg" = "xpledge" || \
+ ( test -z "$sandbox_arg" && test "x$ac_cv_func_pledge" = "xyes" ) ; then
+ test "x$ac_cv_func_pledge" != "xyes" && \
+ AC_MSG_ERROR([pledge sandbox requires pledge(2) support])
+ SANDBOX_STYLE="pledge"
+ AC_DEFINE([SANDBOX_PLEDGE], [1], [Sandbox using pledge(2)])
+elif test "x$sandbox_arg" = "xsystrace" || \
( test -z "$sandbox_arg" && test "x$have_systr_policy_kill" = "x1" ) ; then
test "x$have_systr_policy_kill" != "x1" && \
AC_MSG_ERROR([systrace sandbox requires systrace headers and SYSTR_POLICY_KILL support])
@@ -3096,10 +3581,10 @@ elif test "x$sandbox_arg" = "xseccomp_filter" || \
AC_DEFINE([SANDBOX_SECCOMP_FILTER], [1], [Sandbox using seccomp filter])
elif test "x$sandbox_arg" = "xcapsicum" || \
( test -z "$sandbox_arg" && \
- test "x$ac_cv_header_sys_capability_h" = "xyes" && \
+ test "x$ac_cv_header_sys_capsicum_h" = "xyes" && \
test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then
- test "x$ac_cv_header_sys_capability_h" != "xyes" && \
- AC_MSG_ERROR([capsicum sandbox requires sys/capability.h header])
+ test "x$ac_cv_header_sys_capsicum_h" != "xyes" && \
+ AC_MSG_ERROR([capsicum sandbox requires sys/capsicum.h header])
test "x$ac_cv_func_cap_rights_limit" != "xyes" && \
AC_MSG_ERROR([capsicum sandbox requires cap_rights_limit function])
SANDBOX_STYLE="capsicum"
@@ -3114,6 +3599,10 @@ elif test "x$sandbox_arg" = "xrlimit" || \
AC_MSG_ERROR([rlimit sandbox requires select to work with rlimit])
SANDBOX_STYLE="rlimit"
AC_DEFINE([SANDBOX_RLIMIT], [1], [Sandbox using setrlimit(2)])
+elif test "x$sandbox_arg" = "xsolaris" || \
+ ( test -z "$sandbox_arg" && test "x$SOLARIS_PRIVS" = "xyes" ) ; then
+ SANDBOX_STYLE="solaris"
+ AC_DEFINE([SANDBOX_SOLARIS], [1], [Sandbox using Solaris/Illumos privileges])
elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \
test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then
SANDBOX_STYLE="none"
@@ -3131,10 +3620,10 @@ fi
AC_CHECK_TYPES([long long, unsigned long long, long double])
# Check datatype sizes
-AC_CHECK_SIZEOF([short int], [2])
-AC_CHECK_SIZEOF([int], [4])
-AC_CHECK_SIZEOF([long int], [4])
-AC_CHECK_SIZEOF([long long int], [8])
+AC_CHECK_SIZEOF([short int])
+AC_CHECK_SIZEOF([int])
+AC_CHECK_SIZEOF([long int])
+AC_CHECK_SIZEOF([long long int])
# Sanity check long long for some platforms (AIX)
if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then
@@ -3142,7 +3631,7 @@ if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then
fi
# compute LLONG_MIN and LLONG_MAX if we don't know them.
-if test -z "$have_llong_max"; then
+if test -z "$have_llong_max" && test -z "$have_long_long_max"; then
AC_MSG_CHECKING([for max value of long long])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
@@ -3237,12 +3726,23 @@ fprint_ll(FILE *f, long long n)
)
fi
+AC_CHECK_DECLS([UINT32_MAX], , , [[
+#ifdef HAVE_SYS_LIMITS_H
+# include <sys/limits.h>
+#endif
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+]])
# More checks for data types
AC_CACHE_CHECK([for u_int type], ac_cv_have_u_int, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ u_int a; a = 1;]])],
- [ ac_cv_have_u_int="yes" ], [ ac_cv_have_u_int="no"
+ [ ac_cv_have_u_int="yes" ], [ ac_cv_have_u_int="no"
])
])
if test "x$ac_cv_have_u_int" = "xyes" ; then
@@ -3253,7 +3753,7 @@ fi
AC_CACHE_CHECK([for intXX_t types], ac_cv_have_intxx_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ int8_t a; int16_t b; int32_t c; a = b = c = 1;]])],
- [ ac_cv_have_intxx_t="yes" ], [ ac_cv_have_intxx_t="no"
+ [ ac_cv_have_intxx_t="yes" ], [ ac_cv_have_intxx_t="no"
])
])
if test "x$ac_cv_have_intxx_t" = "xyes" ; then
@@ -3270,7 +3770,7 @@ then
[
AC_DEFINE([HAVE_INTXX_T])
AC_MSG_RESULT([yes])
- ], [ AC_MSG_RESULT([no])
+ ], [ AC_MSG_RESULT([no])
])
fi
@@ -3287,7 +3787,7 @@ AC_CACHE_CHECK([for int64_t type], ac_cv_have_int64_t, [
]], [[
int64_t a; a = 1;
]])],
- [ ac_cv_have_int64_t="yes" ], [ ac_cv_have_int64_t="no"
+ [ ac_cv_have_int64_t="yes" ], [ ac_cv_have_int64_t="no"
])
])
if test "x$ac_cv_have_int64_t" = "xyes" ; then
@@ -3297,7 +3797,7 @@ fi
AC_CACHE_CHECK([for u_intXX_t types], ac_cv_have_u_intxx_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;]])],
- [ ac_cv_have_u_intxx_t="yes" ], [ ac_cv_have_u_intxx_t="no"
+ [ ac_cv_have_u_intxx_t="yes" ], [ ac_cv_have_u_intxx_t="no"
])
])
if test "x$ac_cv_have_u_intxx_t" = "xyes" ; then
@@ -3312,14 +3812,14 @@ if test -z "$have_u_intxx_t" ; then
[
AC_DEFINE([HAVE_U_INTXX_T])
AC_MSG_RESULT([yes])
- ], [ AC_MSG_RESULT([no])
+ ], [ AC_MSG_RESULT([no])
])
fi
AC_CACHE_CHECK([for u_int64_t types], ac_cv_have_u_int64_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ u_int64_t a; a = 1;]])],
- [ ac_cv_have_u_int64_t="yes" ], [ ac_cv_have_u_int64_t="no"
+ [ ac_cv_have_u_int64_t="yes" ], [ ac_cv_have_u_int64_t="no"
])
])
if test "x$ac_cv_have_u_int64_t" = "xyes" ; then
@@ -3336,7 +3836,7 @@ then
[
AC_DEFINE([HAVE_U_INT64_T])
AC_MSG_RESULT([yes])
- ], [ AC_MSG_RESULT([no])
+ ], [ AC_MSG_RESULT([no])
])
fi
@@ -3350,7 +3850,7 @@ if test -z "$have_u_intxx_t" ; then
uint32_t c;
a = b = c = 1;
]])],
- [ ac_cv_have_uintxx_t="yes" ], [ ac_cv_have_uintxx_t="no"
+ [ ac_cv_have_uintxx_t="yes" ], [ ac_cv_have_uintxx_t="no"
])
])
if test "x$ac_cv_have_uintxx_t" = "xyes" ; then
@@ -3368,7 +3868,7 @@ then
[
AC_DEFINE([HAVE_UINTXX_T])
AC_MSG_RESULT([yes])
- ], [ AC_MSG_RESULT([no])
+ ], [ AC_MSG_RESULT([no])
])
fi
@@ -3381,7 +3881,7 @@ then
[
AC_DEFINE([HAVE_UINTXX_T])
AC_MSG_RESULT([yes])
- ], [ AC_MSG_RESULT([no])
+ ], [ AC_MSG_RESULT([no])
])
fi
@@ -3408,7 +3908,7 @@ fi
AC_CACHE_CHECK([for u_char], ac_cv_have_u_char, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ u_char foo; foo = 125; ]])],
- [ ac_cv_have_u_char="yes" ], [ ac_cv_have_u_char="no"
+ [ ac_cv_have_u_char="yes" ], [ ac_cv_have_u_char="no"
])
])
if test "x$ac_cv_have_u_char" = "xyes" ; then
@@ -3417,7 +3917,9 @@ fi
AC_CHECK_TYPES([intmax_t, uintmax_t], , , [
#include <sys/types.h>
-#include <stdint.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
])
TYPE_SOCKLEN_T
@@ -3436,6 +3938,27 @@ AC_CHECK_TYPES([fsblkcnt_t, fsfilcnt_t], , , [
#endif
])
+AC_CHECK_MEMBERS([struct statfs.f_files, struct statfs.f_flags], [], [], [[
+#include <sys/param.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#ifdef HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
+#endif
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+]])
+
+
AC_CHECK_TYPES([in_addr_t, in_port_t], , ,
[#include <sys/types.h>
#include <netinet/in.h>])
@@ -3443,7 +3966,7 @@ AC_CHECK_TYPES([in_addr_t, in_port_t], , ,
AC_CACHE_CHECK([for size_t], ac_cv_have_size_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ size_t foo; foo = 1235; ]])],
- [ ac_cv_have_size_t="yes" ], [ ac_cv_have_size_t="no"
+ [ ac_cv_have_size_t="yes" ], [ ac_cv_have_size_t="no"
])
])
if test "x$ac_cv_have_size_t" = "xyes" ; then
@@ -3453,7 +3976,7 @@ fi
AC_CACHE_CHECK([for ssize_t], ac_cv_have_ssize_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ ssize_t foo; foo = 1235; ]])],
- [ ac_cv_have_ssize_t="yes" ], [ ac_cv_have_ssize_t="no"
+ [ ac_cv_have_ssize_t="yes" ], [ ac_cv_have_ssize_t="no"
])
])
if test "x$ac_cv_have_ssize_t" = "xyes" ; then
@@ -3463,7 +3986,7 @@ fi
AC_CACHE_CHECK([for clock_t], ac_cv_have_clock_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <time.h> ]],
[[ clock_t foo; foo = 1235; ]])],
- [ ac_cv_have_clock_t="yes" ], [ ac_cv_have_clock_t="no"
+ [ ac_cv_have_clock_t="yes" ], [ ac_cv_have_clock_t="no"
])
])
if test "x$ac_cv_have_clock_t" = "xyes" ; then
@@ -3494,7 +4017,7 @@ fi
AC_CACHE_CHECK([for pid_t], ac_cv_have_pid_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ pid_t foo; foo = 1235; ]])],
- [ ac_cv_have_pid_t="yes" ], [ ac_cv_have_pid_t="no"
+ [ ac_cv_have_pid_t="yes" ], [ ac_cv_have_pid_t="no"
])
])
if test "x$ac_cv_have_pid_t" = "xyes" ; then
@@ -3504,7 +4027,7 @@ fi
AC_CACHE_CHECK([for mode_t], ac_cv_have_mode_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ mode_t foo; foo = 1235; ]])],
- [ ac_cv_have_mode_t="yes" ], [ ac_cv_have_mode_t="no"
+ [ ac_cv_have_mode_t="yes" ], [ ac_cv_have_mode_t="no"
])
])
if test "x$ac_cv_have_mode_t" = "xyes" ; then
@@ -3518,7 +4041,7 @@ AC_CACHE_CHECK([for struct sockaddr_storage], ac_cv_have_struct_sockaddr_storage
#include <sys/socket.h>
]], [[ struct sockaddr_storage s; ]])],
[ ac_cv_have_struct_sockaddr_storage="yes" ],
- [ ac_cv_have_struct_sockaddr_storage="no"
+ [ ac_cv_have_struct_sockaddr_storage="no"
])
])
if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then
@@ -3532,7 +4055,7 @@ AC_CACHE_CHECK([for struct sockaddr_in6], ac_cv_have_struct_sockaddr_in6, [
#include <netinet/in.h>
]], [[ struct sockaddr_in6 s; s.sin6_family = 0; ]])],
[ ac_cv_have_struct_sockaddr_in6="yes" ],
- [ ac_cv_have_struct_sockaddr_in6="no"
+ [ ac_cv_have_struct_sockaddr_in6="no"
])
])
if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then
@@ -3546,7 +4069,7 @@ AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [
#include <netinet/in.h>
]], [[ struct in6_addr s; s.s6_addr[0] = 0; ]])],
[ ac_cv_have_struct_in6_addr="yes" ],
- [ ac_cv_have_struct_in6_addr="no"
+ [ ac_cv_have_struct_in6_addr="no"
])
])
if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then
@@ -3570,7 +4093,7 @@ AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [
#include <netdb.h>
]], [[ struct addrinfo s; s.ai_flags = AI_PASSIVE; ]])],
[ ac_cv_have_struct_addrinfo="yes" ],
- [ ac_cv_have_struct_addrinfo="no"
+ [ ac_cv_have_struct_addrinfo="no"
])
])
if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
@@ -3578,11 +4101,13 @@ 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;]])],
[ ac_cv_have_struct_timeval="yes" ],
- [ ac_cv_have_struct_timeval="no"
+ [ ac_cv_have_struct_timeval="no"
])
])
if test "x$ac_cv_have_struct_timeval" = "xyes" ; then
@@ -3590,9 +4115,30 @@ if test "x$ac_cv_have_struct_timeval" = "xyes" ; then
have_struct_timeval=1
fi
-AC_CHECK_TYPES([struct timespec])
+AC_CACHE_CHECK([for struct timespec], ac_cv_have_struct_timespec, [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #ifdef TIME_WITH_SYS_TIME
+ # include <sys/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;]])],
+ [ ac_cv_have_struct_timespec="yes" ],
+ [ ac_cv_have_struct_timespec="no"
+ ])
+])
+if test "x$ac_cv_have_struct_timespec" = "xyes" ; then
+ AC_DEFINE([HAVE_STRUCT_TIMESPEC], [1], [define if you have struct timespec])
+ have_struct_timespec=1
+fi
-# We need int64_t or else certian parts of the compile will fail.
+# We need int64_t or else certain parts of the compile will fail.
if test "x$ac_cv_have_int64_t" = "xno" && \
test "x$ac_cv_sizeof_long_int" != "x8" && \
test "x$ac_cv_sizeof_long_long_int" = "x0" ; then
@@ -3651,6 +4197,8 @@ OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmpx.h], [HAVE_TIME_IN_UTMPX])
OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmpx.h], [HAVE_TV_IN_UTMPX])
AC_CHECK_MEMBERS([struct stat.st_blksize])
+AC_CHECK_MEMBERS([struct stat.st_mtim])
+AC_CHECK_MEMBERS([struct stat.st_mtime])
AC_CHECK_MEMBERS([struct passwd.pw_gecos, struct passwd.pw_class,
struct passwd.pw_change, struct passwd.pw_expire],
[], [], [[
@@ -3690,7 +4238,7 @@ AC_CACHE_CHECK([for __ss_family field in struct sockaddr_storage],
#include <sys/socket.h>
]], [[ struct sockaddr_storage s; s.__ss_family = 1; ]])],
[ ac_cv_have___ss_family_in_struct_ss="yes" ],
- [ ac_cv_have___ss_family_in_struct_ss="no"
+ [ ac_cv_have___ss_family_in_struct_ss="no"
])
])
if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then
@@ -3789,7 +4337,7 @@ AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
[[ extern char *__progname; printf("%s", __progname); ]])],
[ ac_cv_libc_defines___progname="yes" ],
- [ ac_cv_libc_defines___progname="no"
+ [ ac_cv_libc_defines___progname="no"
])
])
if test "x$ac_cv_libc_defines___progname" = "xyes" ; then
@@ -3800,7 +4348,7 @@ AC_CACHE_CHECK([whether $CC implements __FUNCTION__], ac_cv_cc_implements___FUNC
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]],
[[ printf("%s", __FUNCTION__); ]])],
[ ac_cv_cc_implements___FUNCTION__="yes" ],
- [ ac_cv_cc_implements___FUNCTION__="no"
+ [ ac_cv_cc_implements___FUNCTION__="no"
])
])
if test "x$ac_cv_cc_implements___FUNCTION__" = "xyes" ; then
@@ -3812,7 +4360,7 @@ AC_CACHE_CHECK([whether $CC implements __func__], ac_cv_cc_implements___func__,
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]],
[[ printf("%s", __func__); ]])],
[ ac_cv_cc_implements___func__="yes" ],
- [ ac_cv_cc_implements___func__="no"
+ [ ac_cv_cc_implements___func__="no"
])
])
if test "x$ac_cv_cc_implements___func__" = "xyes" ; then
@@ -3825,7 +4373,7 @@ AC_CACHE_CHECK([whether va_copy exists], ac_cv_have_va_copy, [
va_list x,y;
]], [[ va_copy(x,y); ]])],
[ ac_cv_have_va_copy="yes" ],
- [ ac_cv_have_va_copy="no"
+ [ ac_cv_have_va_copy="no"
])
])
if test "x$ac_cv_have_va_copy" = "xyes" ; then
@@ -3837,7 +4385,7 @@ AC_CACHE_CHECK([whether __va_copy exists], ac_cv_have___va_copy, [
#include <stdarg.h>
va_list x,y;
]], [[ __va_copy(x,y); ]])],
- [ ac_cv_have___va_copy="yes" ], [ ac_cv_have___va_copy="no"
+ [ ac_cv_have___va_copy="yes" ], [ ac_cv_have___va_copy="no"
])
])
if test "x$ac_cv_have___va_copy" = "xyes" ; then
@@ -3849,7 +4397,7 @@ AC_CACHE_CHECK([whether getopt has optreset support],
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <getopt.h> ]],
[[ extern int optreset; optreset = 0; ]])],
[ ac_cv_have_getopt_optreset="yes" ],
- [ ac_cv_have_getopt_optreset="no"
+ [ ac_cv_have_getopt_optreset="no"
])
])
if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then
@@ -3861,7 +4409,7 @@ AC_CACHE_CHECK([if libc defines sys_errlist], ac_cv_libc_defines_sys_errlist, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
[[ extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]);]])],
[ ac_cv_libc_defines_sys_errlist="yes" ],
- [ ac_cv_libc_defines_sys_errlist="no"
+ [ ac_cv_libc_defines_sys_errlist="no"
])
])
if test "x$ac_cv_libc_defines_sys_errlist" = "xyes" ; then
@@ -3874,7 +4422,7 @@ AC_CACHE_CHECK([if libc defines sys_nerr], ac_cv_libc_defines_sys_nerr, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
[[ extern int sys_nerr; printf("%i", sys_nerr);]])],
[ ac_cv_libc_defines_sys_nerr="yes" ],
- [ ac_cv_libc_defines_sys_nerr="no"
+ [ ac_cv_libc_defines_sys_nerr="no"
])
])
if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then
@@ -3937,7 +4485,10 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <arpa/nameser.h>
#include <resolv.h>
extern struct __res_state _res;
- ]], [[ ]])],
+ ]], [[
+struct __res_state *volatile p = &_res; /* force resolution of _res */
+return 0;
+ ]],)],
[AC_MSG_RESULT([yes])
AC_DEFINE([HAVE__RES_EXTERN], [1],
[Define if you have struct __res_state _res as an extern])
@@ -3985,7 +4536,7 @@ AC_ARG_WITH([kerberos5],
AC_DEFINE([KRB5], [1], [Define if you want Kerberos 5 support])
KRB5_MSG="yes"
- AC_PATH_PROG([KRB5CONF], [krb5-config],
+ AC_PATH_TOOL([KRB5CONF], [krb5-config],
[$KRB5ROOT/bin/krb5-config],
[$KRB5ROOT/bin:$PATH])
if test -x $KRB5CONF ; then
@@ -4030,7 +4581,6 @@ AC_ARG_WITH([kerberos5],
[K5LIBS="$K5LIBS -ldes"])
], [ AC_MSG_RESULT([no])
K5LIBS="-lkrb5 -lk5crypto -lcom_err"
-
])
AC_SEARCH_LIBS([dn_expand], [resolv])
@@ -4062,8 +4612,8 @@ AC_ARG_WITH([kerberos5],
[ CPPFLAGS="$oldCPP" ])
fi
- if test ! -z "$need_dash_r" ; then
- LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib"
+ if test -n "${rpath_opt}" ; then
+ LDFLAGS="$LDFLAGS ${rpath_opt}${KRB5ROOT}/lib"
fi
if test ! -z "$blibpath" ; then
blibpath="$blibpath:${KRB5ROOT}/lib"
@@ -4213,7 +4763,7 @@ AC_ARG_WITH([maildir],
exit(0);
]])],
[
- maildir_what=`awk -F: '{print $1}' conftest.maildir`
+ maildir_what=`awk -F: '{print $1}' conftest.maildir`
maildir=`awk -F: '{print $2}' conftest.maildir \
| sed 's|/$||'`
AC_MSG_RESULT([Using: $maildir from $maildir_what])
@@ -4281,9 +4831,9 @@ AC_ARG_WITH([mantype],
]
)
if test -z "$MANTYPE"; then
- TestPath="/usr/bin${PATH_SEPARATOR}/usr/ucb"
- AC_PATH_PROGS([NROFF], [nroff awf], [/bin/false], [$TestPath])
- if ${NROFF} -mdoc ${srcdir}/ssh.1 >/dev/null 2>&1; then
+ if ${MANDOC} ${srcdir}/ssh.1 >/dev/null 2>&1; then
+ MANTYPE=doc
+ elif ${NROFF} -mdoc ${srcdir}/ssh.1 >/dev/null 2>&1; then
MANTYPE=doc
elif ${NROFF} -man ${srcdir}/ssh.1 >/dev/null 2>&1; then
MANTYPE=man
@@ -4351,7 +4901,7 @@ if test ! -z "$IPADDR_IN_DISPLAY" ; then
else
DISPLAY_HACK_MSG="no"
AC_ARG_WITH([ipaddr-display],
- [ --with-ipaddr-display Use ip address instead of hostname in \$DISPLAY],
+ [ --with-ipaddr-display Use ip address instead of hostname in $DISPLAY],
[
if test "x$withval" != "xno" ; then
AC_DEFINE([IPADDR_IN_DISPLAY])
@@ -4397,7 +4947,7 @@ fi
# Whether to mess with the default path
SERVER_PATH_MSG="(default)"
AC_ARG_WITH([default-path],
- [ --with-default-path= Specify default \$PATH environment for server],
+ [ --with-default-path= Specify default $PATH environment for server],
[
if test "x$external_path_file" = "x/etc/login.conf" ; then
AC_MSG_WARN([
@@ -4546,7 +5096,7 @@ if test ! -d $piddir ; then
fi
AC_ARG_WITH([pid-dir],
- [ --with-pid-dir=PATH Specify location of ssh.pid file],
+ [ --with-pid-dir=PATH Specify location of sshd.pid file],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
@@ -4558,7 +5108,7 @@ AC_ARG_WITH([pid-dir],
]
)
-AC_DEFINE_UNQUOTED([_PATH_SSH_PIDDIR], ["$piddir"],
+AC_DEFINE_UNQUOTED([_PATH_SSH_PIDDIR], ["$piddir"],
[Specify location of ssh.pid])
AC_SUBST([piddir])
@@ -4716,7 +5266,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
]], [[ char *utmp = UTMP_FILE; ]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
- system_utmp_path=no
+ system_utmp_path=no
])
if test -z "$conf_utmp_location"; then
if test x"$system_utmp_path" = x"no" ; then
@@ -4746,7 +5296,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
]], [[ char *wtmp = WTMP_FILE; ]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
- system_wtmp_path=no
+ system_wtmp_path=no
])
if test -z "$conf_wtmp_location"; then
if test x"$system_wtmp_path" = x"no" ; then
@@ -4779,7 +5329,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
]], [[ char *wtmpx = WTMPX_FILE; ]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
- system_wtmpx_path=no
+ system_wtmpx_path=no
])
if test -z "$conf_wtmpx_location"; then
if test x"$system_wtmpx_path" = x"no" ; then
@@ -4844,8 +5394,19 @@ else
fi
AC_CHECK_DECL([BROKEN_GETADDRINFO], [TEST_SSH_IPV6=no])
AC_SUBST([TEST_SSH_IPV6], [$TEST_SSH_IPV6])
+AC_SUBST([TEST_SSH_UTF8], [$TEST_SSH_UTF8])
AC_SUBST([TEST_MALLOC_OPTIONS], [$TEST_MALLOC_OPTIONS])
AC_SUBST([UNSUPPORTED_ALGORITHMS], [$unsupported_algorithms])
+AC_SUBST([DEPEND], [$(cat $srcdir/.depend)])
+
+CFLAGS="${CFLAGS} ${CFLAGS_AFTER}"
+LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}"
+
+# Make a copy of CFLAGS/LDFLAGS without PIE options.
+LDFLAGS_NOPIE=`echo "$LDFLAGS" | sed 's/ -pie//'`
+CFLAGS_NOPIE=`echo "$CFLAGS" | sed 's/ -fPIE//'`
+AC_SUBST([LDFLAGS_NOPIE])
+AC_SUBST([CFLAGS_NOPIE])
AC_EXEEXT
AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \
@@ -4894,17 +5455,19 @@ echo " PAM support: $PAM_MSG"
echo " OSF SIA support: $SIA_MSG"
echo " KerberosV support: $KRB5_MSG"
echo " SELinux support: $SELINUX_MSG"
-echo " Smartcard support: $SCARD_MSG"
-echo " S/KEY support: $SKEY_MSG"
echo " MD5 password support: $MD5_MSG"
echo " libedit support: $LIBEDIT_MSG"
+echo " libldns support: $LDNS_MSG"
echo " Solaris process contract support: $SPC_MSG"
echo " Solaris project support: $SP_MSG"
+echo " Solaris privilege support: $SPP_MSG"
echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
echo " BSD Auth support: $BSD_AUTH_MSG"
echo " Random number source: $RAND_MSG"
echo " Privsep sandbox style: $SANDBOX_STYLE"
+echo " PKCS#11 support: $enable_pkcs11"
+echo " U2F/FIDO support: $enable_sk"
echo ""
diff --git a/contrib/Makefile b/contrib/Makefile
index eaf7fe2f..3a36387b 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -13,5 +13,10 @@ 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
+ $(CC) $(CFLAGS) `$(PKG_CONFIG) --cflags gtk+-3.0` \
+ gnome-ssh-askpass2.c -o gnome-ssh-askpass3 \
+ `$(PKG_CONFIG) --libs gtk+-3.0 x11`
+
clean:
- rm -f *.o gnome-ssh-askpass1 gnome-ssh-askpass2 gnome-ssh-askpass
+ rm -f *.o gnome-ssh-askpass gnome-ssh-askpass[123]
diff --git a/contrib/README b/contrib/README
index c0022386..60e19ba9 100644
--- a/contrib/README
+++ b/contrib/README
@@ -11,7 +11,7 @@ which allows the use of outbound SSH from behind a SOCKS4, SOCKS5 or
https CONNECT style proxy server. His page for connect.c has extensive
documentation on its use as well as compiled versions for Win32.
-http://www.taiyo.co.jp/~gotoh/ssh/connect.html
+https://bitbucket.org/gotoh/connect/wiki/Home
X11 SSH Askpass:
diff --git a/contrib/aix/README b/contrib/aix/README
index 2a299350..1aa59197 100644
--- a/contrib/aix/README
+++ b/contrib/aix/README
@@ -35,7 +35,7 @@ The script treats all packages as USR packages (not ROOT+USR when
appropriate). It seems to work, though......
If there are any patches to this that have not yet been integrated they
-may be found at http://www.zip.com.au/~dtucker/openssh/.
+may be found at http://www.dtucker.net/openssh/.
Disclaimer:
@@ -47,4 +47,3 @@ you get to keep both pieces.
- Darren Tucker (dtucker at zip dot com dot au)
2002/03/01
-$Id: README,v 1.4 2003/08/25 05:01:04 dtucker Exp $
diff --git a/contrib/aix/buildbff.sh b/contrib/aix/buildbff.sh
index 81d8cc30..55113d9d 100755
--- a/contrib/aix/buildbff.sh
+++ b/contrib/aix/buildbff.sh
@@ -1,7 +1,6 @@
#!/bin/sh
#
# buildbff.sh: Create AIX SMIT-installable OpenSSH packages
-# $Id: buildbff.sh,v 1.13 2011/05/05 03:48:41 djm Exp $
#
# Author: Darren Tucker (dtucker at zip dot com dot au)
# This file is placed in the public domain and comes with absolutely
@@ -241,21 +240,7 @@ echo
# Generate keys unless they already exist
echo Creating host keys if required.
-if [ -f "$sysconfdir/ssh_host_key" ] ; then
- echo "$sysconfdir/ssh_host_key already exists, skipping."
-else
- $bindir/ssh-keygen -t rsa1 -f $sysconfdir/ssh_host_key -N ""
-fi
-if [ -f $sysconfdir/ssh_host_dsa_key ] ; then
- echo "$sysconfdir/ssh_host_dsa_key already exists, skipping."
-else
- $bindir/ssh-keygen -t dsa -f $sysconfdir/ssh_host_dsa_key -N ""
-fi
-if [ -f $sysconfdir/ssh_host_rsa_key ] ; then
- echo "$sysconfdir/ssh_host_rsa_key already exists, skipping."
-else
- $bindir/ssh-keygen -t rsa -f $sysconfdir/ssh_host_rsa_key -N ""
-fi
+$bindir/ssh-keygen -A
echo
# Set startup command depending on SRC support
diff --git a/contrib/aix/inventory.sh b/contrib/aix/inventory.sh
index e2641e79..7d76f497 100755
--- a/contrib/aix/inventory.sh
+++ b/contrib/aix/inventory.sh
@@ -1,7 +1,6 @@
#!/bin/sh
#
# inventory.sh
-# $Id: inventory.sh,v 1.6 2003/11/21 12:48:56 djm Exp $
#
# Originally written by Ben Lindstrom, modified by Darren Tucker to use perl
# This file is placed into the public domain.
diff --git a/contrib/cygwin/Makefile b/contrib/cygwin/Makefile
index a0261f48..4b78cd95 100644
--- a/contrib/cygwin/Makefile
+++ b/contrib/cygwin/Makefile
@@ -13,6 +13,7 @@ defaultsdir=$(sysconfdir)/defaults/etc
inetdefdir=$(defaultsdir)/inetd.d
PRIVSEP_PATH=/var/empty
INSTALL=/usr/bin/install -c
+MKDIR_P=$(srcdir)/mkinstalldirs
DESTDIR=
@@ -23,7 +24,7 @@ all:
@echo
move-config-files: $(DESTDIR)$(sysconfdir)/ssh_config $(DESTDIR)$(sysconfdir)/sshd_config
- $(srcdir)/mkinstalldirs $(DESTDIR)$(defaultsdir)
+ $(MKDIR_P) $(DESTDIR)$(defaultsdir)
mv $(DESTDIR)$(sysconfdir)/ssh_config $(DESTDIR)$(defaultsdir)
mv $(DESTDIR)$(sysconfdir)/sshd_config $(DESTDIR)$(defaultsdir)
@@ -31,11 +32,11 @@ remove-empty-dir:
rm -rf $(DESTDIR)$(PRIVSEP_PATH)
install-inetd-config:
- $(srcdir)/mkinstalldirs $(DESTDIR)$(inetdefdir)
+ $(MKDIR_P) $(DESTDIR)$(inetdefdir)
$(INSTALL) -m 644 sshd-inetd $(DESTDIR)$(inetdefdir)/sshd-inetd
install-sshdoc:
- $(srcdir)/mkinstalldirs $(DESTDIR)$(sshdocdir)
+ $(MKDIR_P) $(DESTDIR)$(sshdocdir)
-$(INSTALL) -m 644 $(srcdir)/CREDITS $(DESTDIR)$(sshdocdir)/CREDITS
-$(INSTALL) -m 644 $(srcdir)/ChangeLog $(DESTDIR)$(sshdocdir)/ChangeLog
-$(INSTALL) -m 644 $(srcdir)/LICENCE $(DESTDIR)$(sshdocdir)/LICENCE
@@ -52,13 +53,13 @@ install-sshdoc:
-$(INSTALL) -m 644 $(srcdir)/TODO $(DESTDIR)$(sshdocdir)/TODO
install-cygwindoc: README
- $(srcdir)/mkinstalldirs $(DESTDIR)$(cygdocdir)
+ $(MKDIR_P) $(DESTDIR)$(cygdocdir)
$(INSTALL) -m 644 README $(DESTDIR)$(cygdocdir)/openssh.README
install-doc: install-sshdoc install-cygwindoc
install-scripts: ssh-host-config ssh-user-config
- $(srcdir)/mkinstalldirs $(DESTDIR)$(bindir)
+ $(MKDIR_P) $(DESTDIR)$(bindir)
$(INSTALL) -m 755 ssh-host-config $(DESTDIR)$(bindir)/ssh-host-config
$(INSTALL) -m 755 ssh-user-config $(DESTDIR)$(bindir)/ssh-user-config
diff --git a/contrib/cygwin/README b/contrib/cygwin/README
index 1396d99c..3745051f 100644
--- a/contrib/cygwin/README
+++ b/contrib/cygwin/README
@@ -25,6 +25,7 @@ Options:
--yes -y Answer all questions with "yes" automatically.
--no -n Answer all questions with "no" automatically.
--cygwin -c <options> Use "options" as value for CYGWIN environment var.
+ --name -N <name> sshd windows service name.
--port -p <n> sshd listens on port n.
--user -u <account> privileged user for service, default 'cyg_server'.
--pwd -w <passwd> Use "pwd" as password for privileged user.
@@ -59,7 +60,7 @@ Options:
Please note that OpenSSH does never use the value of $HOME to
search for the users configuration files! It always uses the
value of the pw_dir field in /etc/passwd as the home directory.
-If no home diretory is set in /etc/passwd, the root directory
+If no home directory is set in /etc/passwd, the root directory
is used instead!
================
@@ -76,7 +77,7 @@ with the aforementioned cygport script:
zlib
crypt
- openssl-devel
+ libssl-devel
libedit-devel
libkrb5-devel
diff --git a/contrib/cygwin/ssh-host-config b/contrib/cygwin/ssh-host-config
index d934d09b..a8572e2a 100644
--- a/contrib/cygwin/ssh-host-config
+++ b/contrib/cygwin/ssh-host-config
@@ -22,7 +22,7 @@
CSIH_SCRIPT=/usr/share/csih/cygwin-service-installation-helper.sh
-# List of apps used. This is checkad for existance in csih_sanity_check
+# List of apps used. This is checkad for existence in csih_sanity_check
# Don't use *any* transient commands before sourcing the csih helper script,
# otherwise the sanity checks are short-circuited.
declare -a csih_required_commands=(
@@ -61,9 +61,8 @@ LOCALSTATEDIR=/var
sshd_config_configured=no
port_number=22
-service_name=sshd
+service_name=cygsshd
strictmodes=yes
-privsep_used=yes
cygwin_value=""
user_account=
password_value=
@@ -140,33 +139,21 @@ sshd_strictmodes() {
# ======================================================================
# Routine: sshd_privsep
-# MODIFIES: privsep_used
+# Try to create ssshd user account
# ======================================================================
sshd_privsep() {
local ret=0
if [ "${sshd_config_configured}" != "yes" ]
then
- echo
- csih_inform "Privilege separation is set to 'sandbox' by default since"
- csih_inform "OpenSSH 6.1. This is unsupported by Cygwin and has to be set"
- csih_inform "to 'yes' or 'no'."
- csih_inform "However, using privilege separation requires a non-privileged account"
- csih_inform "called 'sshd'."
- csih_inform "For more info on privilege separation read /usr/share/doc/openssh/README.privsep."
- if csih_request "Should privilege separation be used?"
+ if ! csih_create_unprivileged_user sshd
then
- privsep_used=yes
- if ! csih_create_unprivileged_user sshd
- then
- csih_error_recoverable "Couldn't create user 'sshd'!"
- csih_error_recoverable "Privilege separation set to 'no' again!"
- csih_error_recoverable "Check your ${SYSCONFDIR}/sshd_config file!"
- let ++ret
- privsep_used=no
- fi
- else
- privsep_used=no
+ csih_error_recoverable "Could not create user 'sshd'!"
+ csih_error_recoverable "You will not be able to run an sshd service"
+ csih_error_recoverable "under a privileged account successfully."
+ csih_error_recoverable "Make sure to create a non-privileged user 'sshd'"
+ csih_error_recoverable "manually before trying to run the service!"
+ let ++ret
fi
fi
return $ret
@@ -202,18 +189,6 @@ sshd_config_tweak() {
let ++ret
fi
fi
- if [ "${sshd_config_configured}" != "yes" ]
- then
- /usr/bin/sed -i -e "
- s/^#\?UsePrivilegeSeparation .*/UsePrivilegeSeparation ${privsep_used}/" \
- ${SYSCONFDIR}/sshd_config
- if [ $? -ne 0 ]
- then
- csih_warning "Setting privilege separation failed!"
- csih_warning "Check your ${SYSCONFDIR}/sshd_config file!"
- let ++ret
- fi
- fi
return $ret
} # --- End of sshd_config_tweak --- #
@@ -332,7 +307,7 @@ check_service_files_ownership() {
if [ -z "${run_service_as}" ]
then
- accnt_name=$(/usr/bin/cygrunsrv -VQ sshd |
+ accnt_name=$(/usr/bin/cygrunsrv -VQ "${service_name}" |
/usr/bin/sed -ne 's/^Account *: *//gp')
if [ "${accnt_name}" = "LocalSystem" ]
then
@@ -354,9 +329,9 @@ check_service_files_ownership() {
fi
if [ -z "${run_service_as}" ]
then
- csih_warning "Couldn't determine name of user running sshd service from account database!"
+ csih_warning "Couldn't determine name of user running ${service_name} service from account database!"
csih_warning "As a result, this script cannot make sure that the files used"
- csih_warning "by the sshd service belong to the user running the service."
+ csih_warning "by the ${service_name} service belong to the user running the service."
return 1
fi
fi
@@ -392,8 +367,8 @@ check_service_files_ownership() {
if [ $ret -ne 0 ]
then
csih_warning "Couldn't change owner of important files to ${run_service_as}!"
- csih_warning "This may cause the sshd service to fail! Please make sure that"
- csih_warning "you have suufficient permissions to change the ownership of files"
+ csih_warning "This may cause the ${service_name} service to fail! Please make sure that"
+ csih_warning "you have sufficient permissions to change the ownership of files"
csih_warning "and try to run the ssh-host-config script again."
fi
return $ret
@@ -419,14 +394,24 @@ install_service() {
then
csih_get_cygenv "${cygwin_value}"
- if ( csih_is_nt2003 || [ "$csih_FORCE_PRIVILEGED_USER" = "yes" ] )
+ if ( [ "$csih_FORCE_PRIVILEGED_USER" != "yes" ] )
then
- csih_inform "On Windows Server 2003, Windows Vista, and above, the"
- csih_inform "SYSTEM account cannot setuid to other users -- a capability"
- csih_inform "sshd requires. You need to have or to create a privileged"
- csih_inform "account. This script will help you do so."
- echo
+ # Enforce using privileged user on 64 bit Vista or W7 under WOW64
+ is_wow64=$(/usr/bin/uname | /usr/bin/grep -q 'WOW' && echo 1 || echo 0)
+ if ( csih_is_nt2003 && ! csih_is_windows8 && [ "${is_wow64}" = "1" ] )
+ then
+ csih_inform "Running 32 bit Cygwin on 64 bit Windows Vista or Windows 7"
+ csih_inform "the SYSTEM account is not sufficient to setuid to a local"
+ csih_inform "user account. You need to have or to create a privileged"
+ csih_inform "account. This script will help you do so."
+ echo
+ csih_FORCE_PRIVILEGED_USER=yes
+ fi
+ fi
+
+ if ( [ "$csih_FORCE_PRIVILEGED_USER" = "yes" ] )
+ then
[ "${opt_force}" = "yes" ] && opt_f=-f
[ -n "${user_account}" ] && opt_u="-u ""${user_account}"""
csih_select_privileged_username ${opt_f} ${opt_u} sshd
@@ -437,11 +422,12 @@ install_service() {
csih_request "Do you want to proceed anyway?" || exit 1
let ++ret
fi
+ # Never returns empty if NT or above
+ run_service_as=$(csih_service_should_run_as)
+ else
+ run_service_as="SYSTEM"
fi
- # Never returns empty if NT or above
- run_service_as=$(csih_service_should_run_as)
-
if [ "${run_service_as}" = "${csih_PRIVILEGED_USERNAME}" ]
then
password="${csih_PRIVILEGED_PASSWORD}"
@@ -471,7 +457,7 @@ install_service() {
echo
csih_inform "The sshd service has been installed under the LocalSystem"
csih_inform "account (also known as SYSTEM). To start the service now, call"
- csih_inform "\`net start sshd' or \`cygrunsrv -S sshd'. Otherwise, it"
+ csih_inform "\`net start ${service_name}' or \`cygrunsrv -S ${service_name}'. Otherwise, it"
csih_inform "will start automatically after the next reboot."
fi
else
@@ -693,15 +679,25 @@ then
fi
fi
-# handle sshd_config (and privsep)
+# handle sshd_config
+# make sure not to change the existing file
+mod_before=""
+if [ -e "${SYSCONFDIR}/sshd_config" ]
+then
+ mod_before=$(stat "${SYSCONFDIR}/sshd_config" | grep '^Modify:')
+fi
csih_install_config "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt
+mod_now=$(stat "${SYSCONFDIR}/sshd_config" | grep '^Modify:')
if ! /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1
then
sshd_config_configured=yes
fi
-sshd_strictmodes || let warning_cnt+=$?
-sshd_privsep || let warning_cnt+=$?
-sshd_config_tweak || let warning_cnt+=$?
+if [ "${mod_before}" != "${mod_now}" ]
+then
+ sshd_strictmodes || let warning_cnt+=$?
+ sshd_config_tweak || let warning_cnt+=$?
+fi
+#sshd_privsep || let warning_cnt+=$?
update_services_file || let warning_cnt+=$?
update_inetd_conf || let warning_cnt+=$?
install_service || let warning_cnt+=$?
diff --git a/contrib/cygwin/ssh-user-config b/contrib/cygwin/ssh-user-config
index 33dc0cbe..6fa4bb3e 100644
--- a/contrib/cygwin/ssh-user-config
+++ b/contrib/cygwin/ssh-user-config
@@ -127,7 +127,7 @@ readonly -f check_user_homedir
check_user_dot_ssh_dir() {
if [ -e "${pwdhome}/.ssh" -a ! -d "${pwdhome}/.ssh" ]
then
- csih_error "${pwdhome}/.ssh is existant but not a directory. Cannot create user identity files."
+ csih_error "${pwdhome}/.ssh is existent but not a directory. Cannot create user identity files."
fi
if [ ! -e "${pwdhome}/.ssh" ]
diff --git a/contrib/findssl.sh b/contrib/findssl.sh
index 263fd264..95a0d66d 100644
--- a/contrib/findssl.sh
+++ b/contrib/findssl.sh
@@ -1,7 +1,5 @@
#!/bin/sh
#
-# $Id: findssl.sh,v 1.4 2007/02/19 11:44:25 dtucker Exp $
-#
# findssl.sh
# Search for all instances of OpenSSL headers and libraries
# and print their versions.
diff --git a/contrib/gnome-ssh-askpass2.c b/contrib/gnome-ssh-askpass2.c
index 9d97c30c..bc83a2d6 100644
--- a/contrib/gnome-ssh-askpass2.c
+++ b/contrib/gnome-ssh-askpass2.c
@@ -39,6 +39,10 @@
#define GRAB_TRIES 16
#define GRAB_WAIT 250 /* milliseconds */
+#define PROMPT_ENTRY 0
+#define PROMPT_CONFIRM 1
+#define PROMPT_NONE 2
+
/*
* Compile with:
*
@@ -57,19 +61,17 @@
#include <gdk/gdkx.h>
static void
-report_failed_grab (const char *what)
+report_failed_grab (GtkWidget *parent_window, const char *what)
{
GtkWidget *err;
- err = gtk_message_dialog_new(NULL, 0,
+ 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_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER);
- gtk_label_set_line_wrap(GTK_LABEL((GTK_MESSAGE_DIALOG(err))->label),
- TRUE);
gtk_dialog_run(GTK_DIALOG(err));
@@ -84,51 +86,67 @@ ok_dialog(GtkWidget *entry, gpointer dialog)
}
static int
-passphrase_dialog(char *message)
+passphrase_dialog(char *message, int prompt_type)
{
const char *failed;
char *passphrase, *local;
int result, grab_tries, grab_server, grab_pointer;
- GtkWidget *dialog, *entry;
+ int buttons, default_response;
+ GtkWidget *parent_window, *dialog, *entry;
GdkGrabStatus status;
grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL);
grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL);
grab_tries = 0;
- dialog = gtk_message_dialog_new(NULL, 0,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_OK_CANCEL,
- "%s",
- message);
+ /* 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;
+ }
- entry = gtk_entry_new();
- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), entry, FALSE,
- FALSE, 0);
- gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
- gtk_widget_grab_focus(entry);
- gtk_widget_show(entry);
+ dialog = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0,
+ GTK_MESSAGE_QUESTION, buttons, "%s", message);
gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH");
gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
- gtk_label_set_line_wrap(GTK_LABEL((GTK_MESSAGE_DIALOG(dialog))->label),
- TRUE);
-
- /* Make <enter> close dialog */
- gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
- g_signal_connect(G_OBJECT(entry), "activate",
- G_CALLBACK(ok_dialog), dialog);
-
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response);
gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
+ if (prompt_type == PROMPT_ENTRY) {
+ entry = gtk_entry_new();
+ gtk_box_pack_start(
+ GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
+ entry, FALSE, FALSE, 0);
+ gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
+ gtk_widget_grab_focus(entry);
+ gtk_widget_show(entry);
+ /* Make <enter> close dialog */
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(ok_dialog), dialog);
+ }
+
/* Grab focus */
gtk_widget_show_now(dialog);
if (grab_pointer) {
for(;;) {
status = gdk_pointer_grab(
- (GTK_WIDGET(dialog))->window, TRUE, 0, NULL,
- NULL, GDK_CURRENT_TIME);
+ (gtk_widget_get_window(GTK_WIDGET(dialog))), TRUE,
+ 0, NULL, NULL, GDK_CURRENT_TIME);
if (status == GDK_GRAB_SUCCESS)
break;
usleep(GRAB_WAIT * 1000);
@@ -139,8 +157,9 @@ passphrase_dialog(char *message)
}
}
for(;;) {
- status = gdk_keyboard_grab((GTK_WIDGET(dialog))->window,
- FALSE, GDK_CURRENT_TIME);
+ status = gdk_keyboard_grab(
+ gtk_widget_get_window(GTK_WIDGET(dialog)), FALSE,
+ GDK_CURRENT_TIME);
if (status == GDK_GRAB_SUCCESS)
break;
usleep(GRAB_WAIT * 1000);
@@ -157,46 +176,51 @@ passphrase_dialog(char *message)
/* Ungrab */
if (grab_server)
- XUngrabServer(GDK_DISPLAY());
+ XUngrabServer(gdk_x11_get_default_xdisplay());
if (grab_pointer)
gdk_pointer_ungrab(GDK_CURRENT_TIME);
gdk_keyboard_ungrab(GDK_CURRENT_TIME);
gdk_flush();
/* Report passphrase if user selected OK */
- passphrase = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
- if (result == GTK_RESPONSE_OK) {
- local = g_locale_from_utf8(passphrase, strlen(passphrase),
- NULL, NULL, NULL);
- if (local != NULL) {
- puts(local);
- memset(local, '\0', strlen(local));
- g_free(local);
- } else {
- puts(passphrase);
+ if (prompt_type == PROMPT_ENTRY) {
+ passphrase = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
+ if (result == GTK_RESPONSE_OK) {
+ local = g_locale_from_utf8(passphrase,
+ strlen(passphrase), NULL, NULL, NULL);
+ if (local != NULL) {
+ puts(local);
+ memset(local, '\0', strlen(local));
+ g_free(local);
+ } else {
+ puts(passphrase);
+ }
}
+ /* Zero passphrase in memory */
+ memset(passphrase, '\b', strlen(passphrase));
+ gtk_entry_set_text(GTK_ENTRY(entry), passphrase);
+ memset(passphrase, '\0', strlen(passphrase));
+ g_free(passphrase);
}
-
- /* Zero passphrase in memory */
- memset(passphrase, '\b', strlen(passphrase));
- gtk_entry_set_text(GTK_ENTRY(entry), passphrase);
- memset(passphrase, '\0', strlen(passphrase));
- g_free(passphrase);
-
+
gtk_widget_destroy(dialog);
- return (result == GTK_RESPONSE_OK ? 0 : -1);
+ if (result != GTK_RESPONSE_OK && result != GTK_RESPONSE_YES)
+ return -1;
+ return 0;
- /* At least one grab failed - ungrab what we got, and report
- the failure to the user. Note that XGrabServer() cannot
- fail. */
nograbkb:
+ /*
+ * At least one grab failed - ungrab what we got, and report
+ * the failure to the user. Note that XGrabServer() cannot
+ * fail.
+ */
gdk_pointer_ungrab(GDK_CURRENT_TIME);
nograb:
if (grab_server)
- XUngrabServer(GDK_DISPLAY());
+ XUngrabServer(gdk_x11_get_default_xdisplay());
gtk_widget_destroy(dialog);
- report_failed_grab(failed);
+ report_failed_grab(parent_window, failed);
return (-1);
}
@@ -204,8 +228,8 @@ passphrase_dialog(char *message)
int
main(int argc, char **argv)
{
- char *message;
- int result;
+ char *message, *prompt_mode;
+ int result, prompt_type = PROMPT_ENTRY;
gtk_init(&argc, &argv);
@@ -215,8 +239,15 @@ main(int argc, char **argv)
message = g_strdup("Enter your OpenSSH passphrase:");
}
+ if ((prompt_mode = getenv("SSH_ASKPASS_PROMPT")) != NULL) {
+ if (strcasecmp(prompt_mode, "confirm") == 0)
+ prompt_type = PROMPT_CONFIRM;
+ else if (strcasecmp(prompt_mode, "none") == 0)
+ prompt_type = PROMPT_NONE;
+ }
+
setvbuf(stdout, 0, _IONBF, 0);
- result = passphrase_dialog(message);
+ result = passphrase_dialog(message, prompt_type);
g_free(message);
return (result);
diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec
index 7ac4ed0a..dcd57aa1 100644
--- a/contrib/redhat/openssh.spec
+++ b/contrib/redhat/openssh.spec
@@ -1,70 +1,81 @@
-%define ver 6.8p1
-%define rel 1
+%global ver 8.3p1
+%global rel 1%{?dist}
# OpenSSH privilege separation requires a user & group ID
-%define sshd_uid 74
-%define sshd_gid 74
+%global sshd_uid 74
+%global sshd_gid 74
# Version of ssh-askpass
-%define aversion 1.2.4.1
+%global aversion 1.2.4.1
# Do we want to disable building of x11-askpass? (1=yes 0=no)
-%define no_x11_askpass 0
+%global no_x11_askpass 0
# Do we want to disable building of gnome-askpass? (1=yes 0=no)
-%define no_gnome_askpass 0
+%global no_gnome_askpass 0
# Do we want to link against a static libcrypto? (1=yes 0=no)
-%define static_libcrypto 0
+%global static_libcrypto 0
# Do we want smartcard support (1=yes 0=no)
-%define scard 0
+%global scard 0
# Use GTK2 instead of GNOME in gnome-ssh-askpass
-%define gtk2 1
+%global gtk2 1
-# Is this build for RHL 6.x?
-%define build6x 0
+# Use build6x options for older RHEL builds
+# RHEL 7 not yet supported
+%if 0%{?rhel} > 6
+%global build6x 0
+%else
+%global build6x 1
+%endif
+
+%if 0%{?fedora} >= 26
+%global compat_openssl 1
+%else
+%global compat_openssl 0
+%endif
# Do we want kerberos5 support (1=yes 0=no)
-%define kerberos5 1
+%global kerberos5 1
# Reserve options to override askpass settings with:
# rpm -ba|--rebuild --define 'skip_xxx 1'
-%{?skip_x11_askpass:%define no_x11_askpass 1}
-%{?skip_gnome_askpass:%define no_gnome_askpass 1}
+%{?skip_x11_askpass:%global no_x11_askpass 1}
+%{?skip_gnome_askpass:%global no_gnome_askpass 1}
# Add option to build without GTK2 for older platforms with only GTK+.
# RedHat <= 7.2 and Red Hat Advanced Server 2.1 are examples.
# rpm -ba|--rebuild --define 'no_gtk2 1'
-%{?no_gtk2:%define gtk2 0}
+%{?no_gtk2:%global gtk2 0}
# Is this a build for RHL 6.x or earlier?
-%{?build_6x:%define build6x 1}
+%{?build_6x:%global build6x 1}
# If this is RHL 6.x, the default configuration has sysconfdir in /usr/etc.
%if %{build6x}
-%define _sysconfdir /etc
+%global _sysconfdir /etc
%endif
# Options for static OpenSSL link:
# rpm -ba|--rebuild --define "static_openssl 1"
-%{?static_openssl:%define static_libcrypto 1}
+%{?static_openssl:%global static_libcrypto 1}
# Options for Smartcard support: (needs libsectok and openssl-engine)
# rpm -ba|--rebuild --define "smartcard 1"
-%{?smartcard:%define scard 1}
+%{?smartcard:%global scard 1}
# Is this a build for the rescue CD (without PAM, with MD5)? (1=yes 0=no)
-%define rescue 0
-%{?build_rescue:%define rescue 1}
+%global rescue 0
+%{?build_rescue:%global rescue 1}
# Turn off some stuff for resuce builds
%if %{rescue}
-%define kerberos5 0
+%global kerberos5 0
%endif
-Summary: The OpenSSH implementation of SSH protocol versions 1 and 2.
+Summary: The OpenSSH implementation of SSH protocol version 2.
Name: openssh
Version: %{ver}
%if %{rescue}
@@ -72,11 +83,9 @@ Release: %{rel}rescue
%else
Release: %{rel}
%endif
-URL: http://www.openssh.com/portable.html
-Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
-%if ! %{no_x11_askpass}
+URL: https://www.openssh.com/portable.html
+Source0: https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
Source1: http://www.jmknoble.net/software/x11-ssh-askpass/x11-ssh-askpass-%{aversion}.tar.gz
-%endif
License: BSD
Group: Applications/Internet
BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
@@ -86,15 +95,27 @@ PreReq: initscripts >= 5.00
%else
Requires: initscripts >= 5.20
%endif
-BuildRequires: perl, openssl-devel
+BuildRequires: perl
+%if %{compat_openssl}
+BuildRequires: compat-openssl10-devel
+%else
+BuildRequires: openssl-devel >= 1.0.1
+BuildRequires: openssl-devel < 1.1
+%endif
BuildRequires: /bin/login
%if ! %{build6x}
-BuildPreReq: glibc-devel, pam
+BuildRequires: glibc-devel, pam
%else
BuildRequires: /usr/include/security/pam_appl.h
%endif
%if ! %{no_x11_askpass}
BuildRequires: /usr/include/X11/Xlib.h
+# Xt development tools
+BuildRequires: libXt-devel
+# Provides xmkmf
+BuildRequires: imake
+# Rely on relatively recent gtk
+BuildRequires: gtk2-devel
%endif
%if ! %{no_gnome_askpass}
BuildRequires: pkgconfig
@@ -183,20 +204,17 @@ environment.
CFLAGS="$RPM_OPT_FLAGS -Os"; export CFLAGS
%endif
-%if %{kerberos5}
-K5DIR=`rpm -ql krb5-devel | grep include/krb5.h | sed 's,\/include\/krb5.h,,'`
-echo K5DIR=$K5DIR
-%endif
-
%configure \
--sysconfdir=%{_sysconfdir}/ssh \
--libexecdir=%{_libexecdir}/openssh \
--datadir=%{_datadir}/openssh \
- --with-rsh=%{_bindir}/rsh \
--with-default-path=/usr/local/bin:/bin:/usr/bin \
--with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \
--with-privsep-path=%{_var}/empty/sshd \
--with-md5-passwords \
+ --mandir=%{_mandir} \
+ --with-mantype=man \
+ --disable-strip \
%if %{scard}
--with-smartcard \
%endif
@@ -263,12 +281,12 @@ install -m644 contrib/redhat/sshd.pam $RPM_BUILD_ROOT/etc/pam.d/sshd
install -m755 contrib/redhat/sshd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/sshd
%if ! %{no_x11_askpass}
-install -s x11-ssh-askpass-%{aversion}/x11-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/x11-ssh-askpass
+install x11-ssh-askpass-%{aversion}/x11-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/x11-ssh-askpass
ln -s x11-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/ssh-askpass
%endif
%if ! %{no_gnome_askpass}
-install -s contrib/gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/gnome-ssh-askpass
+install contrib/gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/gnome-ssh-askpass
%endif
%if ! %{scard}
@@ -359,8 +377,6 @@ fi
%attr(0644,root,root) %{_mandir}/man1/ssh.1*
%attr(0644,root,root) %{_mandir}/man5/ssh_config.5*
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config
-%attr(-,root,root) %{_bindir}/slogin
-%attr(-,root,root) %{_mandir}/man1/slogin.1*
%if ! %{rescue}
%attr(2755,root,nobody) %{_bindir}/ssh-agent
%attr(0755,root,root) %{_bindir}/ssh-add
@@ -394,7 +410,7 @@ fi
%doc x11-ssh-askpass-%{aversion}/README
%doc x11-ssh-askpass-%{aversion}/ChangeLog
%doc x11-ssh-askpass-%{aversion}/SshAskpass*.ad
-%attr(0755,root,root) %{_libexecdir}/openssh/ssh-askpass
+%{_libexecdir}/openssh/ssh-askpass
%attr(0755,root,root) %{_libexecdir}/openssh/x11-ssh-askpass
%endif
@@ -406,6 +422,22 @@ fi
%endif
%changelog
+* Sat Feb 10 2018 Darren Tucker <dtucker@dtucker.net>
+- Update openssl-devel dependency to match current requirements.
+- Handle Fedora >=6 openssl 1.0 compat libs.
+- Remove SSH1 from description.
+- Don't strip binaries at build time so that debuginfo package can be
+ created.
+
+* Sun Nov 16 2014 Nico Kadel-Garcia <nakdel@gmail.com>
+- Add '--mandir' and '--with-mantype' for RHEL 5 compatibility
+- Add 'dist' option to 'ver' so package names reflect OS at build time
+- Always include x11-ssh-askpass tarball in SRPM
+- Add openssh-x11-aspass BuildRequires for libXT-devel, imake, gtk2-devel
+- Discard 'K5DIR' reporting, not usable inside 'mock' for RHEL 5 compatibility
+- Discard obsolete '--with-rsh' configure option
+- Update openssl-devel dependency to 0.9.8f, as found in autoconf
+
* Wed Jul 14 2010 Tim Rice <tim@multitalents.net>
- test for skip_x11_askpass (line 77) should have been for no_x11_askpass
@@ -417,7 +449,7 @@ fi
- Don't install profile.d scripts when not building with GNOME/GTK askpass
(patch from bet@rahul.net)
-* Wed Oct 01 2002 Damien Miller <djm@mindrot.org>
+* Tue Oct 01 2002 Damien Miller <djm@mindrot.org>
- Install ssh-agent setgid nobody to prevent ptrace() key theft attacks
* Mon Sep 30 2002 Damien Miller <djm@mindrot.org>
@@ -463,7 +495,7 @@ fi
- remove dependency on db1-devel, which has just been swallowed up whole
by gnome-libs-devel
-* Sun Dec 29 2001 Nalin Dahyabhai <nalin@redhat.com>
+* Sat Dec 29 2001 Nalin Dahyabhai <nalin@redhat.com>
- adjust build dependencies so that build6x actually works right (fix
from Hugo van der Kooij)
diff --git a/contrib/redhat/sshd.init b/contrib/redhat/sshd.init
index 40c8dfd9..8ee5fcd3 100755
--- a/contrib/redhat/sshd.init
+++ b/contrib/redhat/sshd.init
@@ -40,7 +40,6 @@ start()
# Create keys if necessary
/usr/bin/ssh-keygen -A
if [ -x /sbin/restorecon ]; then
- /sbin/restorecon /etc/ssh/ssh_host_key.pub
/sbin/restorecon /etc/ssh/ssh_host_rsa_key.pub
/sbin/restorecon /etc/ssh/ssh_host_dsa_key.pub
/sbin/restorecon /etc/ssh/ssh_host_ecdsa_key.pub
diff --git a/contrib/redhat/sshd.init.old b/contrib/redhat/sshd.init.old
index 0deb6080..8a30f7da 100755
--- a/contrib/redhat/sshd.init.old
+++ b/contrib/redhat/sshd.init.old
@@ -24,7 +24,6 @@ prog="sshd"
# Some functions to make the below more readable
KEYGEN=/usr/bin/ssh-keygen
SSHD=/usr/sbin/sshd
-RSA1_KEY=/etc/ssh/ssh_host_key
RSA_KEY=/etc/ssh/ssh_host_rsa_key
DSA_KEY=/etc/ssh/ssh_host_dsa_key
PID_FILE=/var/run/sshd.pid
@@ -61,21 +60,6 @@ my_failure() {
;;
esac
}
-do_rsa1_keygen() {
- if [ ! -s $RSA1_KEY ]; then
- echo -n "Generating SSH1 RSA host key: "
- if $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N '' >&/dev/null; then
- chmod 600 $RSA1_KEY
- chmod 644 $RSA1_KEY.pub
- my_success "RSA1 key generation"
- echo
- else
- my_failure "RSA1 key generation"
- echo
- exit 1
- fi
- fi
-}
do_rsa_keygen() {
if [ ! -s $RSA_KEY ]; then
echo -n "Generating SSH2 RSA host key: "
@@ -119,7 +103,6 @@ do_restart_sanity_check() {
case "$1" in
start)
# Create keys if necessary
- do_rsa1_keygen;
do_rsa_keygen;
do_dsa_keygen;
diff --git a/contrib/solaris/README b/contrib/solaris/README
index fefdd4b5..cabecaa1 100644
--- a/contrib/solaris/README
+++ b/contrib/solaris/README
@@ -5,7 +5,7 @@ SVR4 style package tools.
The build process is called a 'dummy install'.. Which means the software does
a "make install-nokeys DESTDIR=[fakeroot]". This way all manpages should
-be handled correctly and key are defered until the first time the sshd
+be handled correctly and key are deferred until the first time the sshd
is started.
Directions:
diff --git a/contrib/ssh-copy-id b/contrib/ssh-copy-id
index ae88e995..b83b8361 100644
--- a/contrib/ssh-copy-id
+++ b/contrib/ssh-copy-id
@@ -1,6 +1,6 @@
#!/bin/sh
-# Copyright (c) 1999-2013 Philip Hands <phil@hands.com>
+# Copyright (c) 1999-2016 Philip Hands <phil@hands.com>
# 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>
@@ -56,10 +56,14 @@ then
fi
fi
-DEFAULT_PUB_ID_FILE=$(ls -t ${HOME}/.ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1)
+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"
usage () {
- printf 'Usage: %s [-h|-?|-n] [-i [identity_file]] [-p port] [[-o <ssh -o options>] ...] [user@]hostname\n' "$0" >&2
+ printf 'Usage: %s [-h|-?|-f|-n] [-i [identity_file]] [-p port] [[-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-h|-?: print this help\n' >&2
exit 1
}
@@ -71,21 +75,29 @@ quote() {
use_id_file() {
local L_ID_FILE="$1"
+ if [ -z "$L_ID_FILE" ] ; then
+ printf "%s: ERROR: no ID file found\n" "$0"
+ exit 1
+ fi
+
if expr "$L_ID_FILE" : ".*\.pub$" >/dev/null ; then
PUB_ID_FILE="$L_ID_FILE"
else
PUB_ID_FILE="$L_ID_FILE.pub"
fi
- PRIV_ID_FILE=$(dirname "$PUB_ID_FILE")/$(basename "$PUB_ID_FILE" .pub)
+ [ "$FORCED" ] || PRIV_ID_FILE=$(dirname "$PUB_ID_FILE")/$(basename "$PUB_ID_FILE" .pub)
# check that the files are readable
- for f in $PUB_ID_FILE $PRIV_ID_FILE ; do
- ErrMSG=$( { : < $f ; } 2>&1 ) || {
- printf "\n%s: ERROR: failed to open ID file '%s': %s\n\n" "$0" "$f" "$(printf "%s\n" "$ErrMSG" | sed -e 's/.*: *//')"
+ for f in "$PUB_ID_FILE" ${PRIV_ID_FILE:+"$PRIV_ID_FILE"} ; do
+ ErrMSG=$( { : < "$f" ; } 2>&1 ) || {
+ local 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/.*: *//')"
exit 1
}
done
+ printf '%s: INFO: Source of key(s) to be installed: "%s"\n' "$0" "$PUB_ID_FILE" >&2
GET_ID="cat \"$PUB_ID_FILE\""
}
@@ -121,7 +133,7 @@ do
}
shift
;;
- -n|-h|-\?)
+ -f|-n|-h|-\?)
OPT="$1"
OPTARG=
shift
@@ -154,6 +166,9 @@ do
-o|-p)
SSH_OPTS="${SSH_OPTS:+$SSH_OPTS }$OPT '$(quote "$OPTARG")'"
;;
+ -f)
+ FORCED=1
+ ;;
-n)
DRY_RUN=1
;;
@@ -194,56 +209,65 @@ fi
populate_new_ids() {
local L_SUCCESS="$1"
+ if [ "$FORCED" ] ; then
+ 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
- echo "mktemp failed" 1>&2
+ printf '%s: ERROR: mktemp failed\n' "$0" >&2
exit 1
fi
- trap "rm -f $L_TMP_ID_FILE ${L_TMP_ID_FILE}.pub" EXIT TERM INT QUIT
+ 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 ; do
- printf '%s\n' "$ID" > $L_TMP_ID_FILE
+ 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
+ -o IdentitiesOnly=yes "$@" exit 2>"$L_TMP_ID_FILE.stderr" </dev/null
if [ "$?" = "$L_SUCCESS" ] ; then
- : > $L_TMP_ID_FILE
+ : > "$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
+ 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
+ cat "$L_TMP_ID_FILE"
done
}
)
- rm -f $L_TMP_ID_FILE* && trap - EXIT TERM INT QUIT
+ eval "$L_CLEANUP" && trap - EXIT TERM INT QUIT
if expr "$NEW_IDS" : "^ERROR: " >/dev/null ; then
printf '\n%s: %s\n\n' "$0" "$NEW_IDS" >&2
exit 1
fi
if [ -z "$NEW_IDS" ] ; then
- printf '\n%s: WARNING: All keys were skipped because they already exist on the remote system.\n\n' "$0" >&2
+ 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
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=',' "$@" 2>&1 |
+REMOTE_VERSION=$(ssh -v -o PreferredAuthentications=',' -o ControlPath=none "$@" 2>&1 |
sed -ne 's/.*remote software version //p')
case "$REMOTE_VERSION" in
@@ -269,10 +293,10 @@ case "$REMOTE_VERSION" in
*)
# Assuming that the remote host treats ~/.ssh/authorized_keys as one might expect
populate_new_ids 0
- [ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | ssh "$@" "
- umask 077 ;
- mkdir -p .ssh && cat >> .ssh/authorized_keys || exit 1 ;
- if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi" \
+ # in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX;
+ # 'cd' to be at $HOME; add a newline if it's missing; and all on one line, because tcsh.
+ [ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | \
+ ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys ; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \
|| exit 1
ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l)
;;
diff --git a/contrib/ssh-copy-id.1 b/contrib/ssh-copy-id.1
index 67a59e49..ae75c79a 100644
--- a/contrib/ssh-copy-id.1
+++ b/contrib/ssh-copy-id.1
@@ -29,6 +29,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.Nd use locally available keys to authorise logins on a remote machine
.Sh SYNOPSIS
.Nm
+.Op Fl f
.Op Fl n
.Op Fl i Op Ar identity_file
.Op Fl p Ar port
@@ -76,6 +77,10 @@ is used.
Note that this can be used to ensure that the keys copied have the
comment one prefers and/or extra options applied, by ensuring that the
key file has these set as preferred before the copy is attempted.
+.It Fl f
+Forced mode: doesn't check if the keys are present on the remote server.
+This means that it does not need the private key. Of course, this can result
+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.
@@ -153,7 +158,7 @@ asked for confirmation, which is your cue to log back out and run
The reason you might want to specify the -i option in this case is to
ensure that the comment on the installed key is the one from the
.Pa .pub
-file, rather than just the filename that was loaded into you agent.
+file, rather than just the filename that was loaded into your agent.
It also ensures that only the id you intended is installed, rather than
all the keys that you have in your
.Xr ssh-agent 1 .
diff --git a/contrib/suse/openssh.spec b/contrib/suse/openssh.spec
index 0eb779c9..a2789052 100644
--- a/contrib/suse/openssh.spec
+++ b/contrib/suse/openssh.spec
@@ -13,8 +13,8 @@
Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation
Name: openssh
-Version: 6.8p1
-URL: http://www.openssh.com/
+Version: 8.3p1
+URL: https://www.openssh.com/
Release: 1
Source0: openssh-%{version}.tar.gz
Source1: x11-ssh-askpass-%{xversion}.tar.gz
@@ -56,7 +56,7 @@ arbitrary TCP/IP ports can also be forwarded over the secure channel.
OpenSSH is OpenBSD's rework of the last free version of SSH, bringing it
up to date in terms of security and features, as well as removing all
-patented algorithms to seperate libraries (OpenSSL).
+patented algorithms to separate libraries (OpenSSL).
This package includes all files necessary for both the OpenSSH
client and server.
@@ -70,7 +70,7 @@ arbitrary TCP/IP ports can also be forwarded over the secure channel.
OpenSSH is OpenBSD's rework of the last free version of SSH, bringing it
up to date in terms of security and features, as well as removing all
-patented algorithms to seperate libraries (OpenSSL).
+patented algorithms to separate libraries (OpenSSL).
This package contains an X Window System passphrase dialog for OpenSSH.
@@ -202,7 +202,6 @@ rm -rf $RPM_BUILD_ROOT
%attr(0755,root,root) %{_bindir}/ssh-keygen
%attr(0755,root,root) %{_bindir}/scp
%attr(0755,root,root) %{_bindir}/ssh
-%attr(-,root,root) %{_bindir}/slogin
%attr(0755,root,root) %{_bindir}/ssh-agent
%attr(0755,root,root) %{_bindir}/ssh-add
%attr(0755,root,root) %{_bindir}/ssh-keyscan
@@ -214,7 +213,6 @@ rm -rf $RPM_BUILD_ROOT
%attr(0755,root,root) %{_libdir}/ssh/ssh-pkcs11-helper
%attr(0644,root,root) %doc %{_mandir}/man1/scp.1*
%attr(0644,root,root) %doc %{_mandir}/man1/sftp.1*
-%attr(-,root,root) %doc %{_mandir}/man1/slogin.1*
%attr(0644,root,root) %doc %{_mandir}/man1/ssh.1*
%attr(0644,root,root) %doc %{_mandir}/man1/ssh-add.1*
%attr(0644,root,root) %doc %{_mandir}/man1/ssh-agent.1*
diff --git a/crc32.c b/crc32.c
deleted file mode 100644
index c192eb4d..00000000
--- a/crc32.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* $OpenBSD: crc32.c,v 1.11 2006/04/22 18:29:33 stevesk Exp $ */
-
-/*
- * Copyright (c) 2003 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "includes.h"
-#include "crc32.h"
-
-static const u_int32_t crc32tab[] = {
- 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
- 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
- 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
- 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
- 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
- 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
- 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
- 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
- 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
- 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
- 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
- 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
- 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
- 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
- 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
- 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
- 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
- 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
- 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
- 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
- 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
- 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
- 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
- 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
- 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
- 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
- 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
- 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
- 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
- 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
- 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
- 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
- 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
- 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
- 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
- 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
- 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
- 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
- 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
- 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
- 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
- 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
- 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
- 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
- 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
- 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
- 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
- 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
- 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
- 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
- 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
- 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
- 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
- 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
- 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
- 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
- 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
- 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
- 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
- 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
- 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
- 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
- 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
- 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
-};
-
-u_int32_t
-ssh_crc32(const u_char *buf, u_int32_t size)
-{
- u_int32_t i, crc;
-
- crc = 0;
- for (i = 0; i < size; i++)
- crc = crc32tab[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
- return crc;
-}
diff --git a/crc32.h b/crc32.h
deleted file mode 100644
index 5d7131af..00000000
--- a/crc32.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* $OpenBSD: crc32.h,v 1.15 2006/03/25 22:22:43 djm Exp $ */
-
-/*
- * Copyright (c) 2003 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef SSH_CRC32_H
-#define SSH_CRC32_H
-u_int32_t ssh_crc32(const u_char *, u_int32_t);
-#endif
diff --git a/crypto_api.h b/crypto_api.h
index 5820ce8f..eb05251f 100644
--- a/crypto_api.h
+++ b/crypto_api.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: crypto_api.h,v 1.3 2013/12/17 10:36:38 markus Exp $ */
+/* $OpenBSD: crypto_api.h,v 1.5 2019/01/21 10:20:12 djm Exp $ */
/*
* Assembled from generated headers and source files by Markus Friedl.
@@ -8,21 +8,22 @@
#ifndef crypto_api_h
#define crypto_api_h
+#include "includes.h"
+
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <stdlib.h>
+typedef int8_t crypto_int8;
+typedef uint8_t crypto_uint8;
+typedef int16_t crypto_int16;
+typedef uint16_t crypto_uint16;
typedef int32_t crypto_int32;
typedef uint32_t crypto_uint32;
#define randombytes(buf, buf_len) arc4random_buf((buf), (buf_len))
-
-#define crypto_hashblocks_sha512_STATEBYTES 64U
-#define crypto_hashblocks_sha512_BLOCKBYTES 128U
-
-int crypto_hashblocks_sha512(unsigned char *, const unsigned char *,
- unsigned long long);
+#define small_random32() arc4random()
#define crypto_hash_sha512_BYTES 64U
@@ -41,4 +42,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
+
+int crypto_kem_sntrup4591761_enc(unsigned char *cstr, unsigned char *k,
+ const unsigned char *pk);
+int crypto_kem_sntrup4591761_dec(unsigned char *k,
+ const unsigned char *cstr, const unsigned char *sk);
+int crypto_kem_sntrup4591761_keypair(unsigned char *pk, unsigned char *sk);
+
#endif /* crypto_api_h */
diff --git a/deattack.c b/deattack.c
deleted file mode 100644
index e76481a6..00000000
--- a/deattack.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/* $OpenBSD: deattack.c,v 1.32 2015/01/20 23:14:00 deraadt Exp $ */
-/*
- * Cryptographic attack detector for ssh - source code
- *
- * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
- *
- * All rights reserved. Redistribution and use in source and binary
- * forms, with or without modification, are permitted provided that
- * this copyright notice is retained.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
- * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
- * SOFTWARE.
- *
- * Ariel Futoransky <futo@core-sdi.com>
- * <http://www.core-sdi.com>
- */
-
-#include "includes.h"
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "deattack.h"
-#include "crc32.h"
-#include "sshbuf.h"
-#include "misc.h"
-
-/*
- * CRC attack detection has a worst-case behaviour that is O(N^3) over
- * the number of identical blocks in a packet. This behaviour can be
- * exploited to create a limited denial of service attack.
- *
- * However, because we are dealing with encrypted data, identical
- * blocks should only occur every 2^35 maximally-sized packets or so.
- * Consequently, we can detect this DoS by looking for identical blocks
- * in a packet.
- *
- * The parameter below determines how many identical blocks we will
- * accept in a single packet, trading off between attack detection and
- * likelihood of terminating a legitimate connection. A value of 32
- * corresponds to an average of 2^40 messages before an attack is
- * misdetected
- */
-#define MAX_IDENTICAL 32
-
-/* SSH Constants */
-#define SSH_MAXBLOCKS (32 * 1024)
-#define SSH_BLOCKSIZE (8)
-
-/* Hashing constants */
-#define HASH_MINSIZE (8 * 1024)
-#define HASH_ENTRYSIZE (2)
-#define HASH_FACTOR(x) ((x)*3/2)
-#define HASH_UNUSEDCHAR (0xff)
-#define HASH_UNUSED (0xffff)
-#define HASH_IV (0xfffe)
-
-#define HASH_MINBLOCKS (7*SSH_BLOCKSIZE)
-
-
-/* Hash function (Input keys are cipher results) */
-#define HASH(x) PEEK_U32(x)
-
-#define CMP(a, b) (memcmp(a, b, SSH_BLOCKSIZE))
-
-static void
-crc_update(u_int32_t *a, u_int32_t b)
-{
- b ^= *a;
- *a = ssh_crc32((u_char *)&b, sizeof(b));
-}
-
-/* detect if a block is used in a particular pattern */
-static int
-check_crc(const u_char *S, const u_char *buf, u_int32_t len)
-{
- u_int32_t crc;
- const u_char *c;
-
- crc = 0;
- for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
- if (!CMP(S, c)) {
- crc_update(&crc, 1);
- crc_update(&crc, 0);
- } else {
- crc_update(&crc, 0);
- crc_update(&crc, 0);
- }
- }
- return crc == 0;
-}
-
-void
-deattack_init(struct deattack_ctx *dctx)
-{
- bzero(dctx, sizeof(*dctx));
- dctx->n = HASH_MINSIZE / HASH_ENTRYSIZE;
-}
-
-/* Detect a crc32 compensation attack on a packet */
-int
-detect_attack(struct deattack_ctx *dctx, const u_char *buf, u_int32_t len)
-{
- u_int32_t i, j, l, same;
- u_int16_t *tmp;
- const u_char *c, *d;
-
- if (len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) ||
- len % SSH_BLOCKSIZE != 0)
- return DEATTACK_ERROR;
- for (l = dctx->n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2)
- ;
-
- if (dctx->h == NULL) {
- if ((dctx->h = calloc(l, HASH_ENTRYSIZE)) == NULL)
- return DEATTACK_ERROR;
- dctx->n = l;
- } else {
- if (l > dctx->n) {
- if ((tmp = reallocarray(dctx->h, l, HASH_ENTRYSIZE))
- == NULL) {
- free(dctx->h);
- dctx->h = NULL;
- return DEATTACK_ERROR;
- }
- dctx->h = tmp;
- dctx->n = l;
- }
- }
-
- if (len <= HASH_MINBLOCKS) {
- for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
- for (d = buf; d < c; d += SSH_BLOCKSIZE) {
- if (!CMP(c, d)) {
- if ((check_crc(c, buf, len)))
- return DEATTACK_DETECTED;
- else
- break;
- }
- }
- }
- return DEATTACK_OK;
- }
- memset(dctx->h, HASH_UNUSEDCHAR, dctx->n * HASH_ENTRYSIZE);
-
- for (c = buf, same = j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) {
- for (i = HASH(c) & (dctx->n - 1); dctx->h[i] != HASH_UNUSED;
- i = (i + 1) & (dctx->n - 1)) {
- if (!CMP(c, buf + dctx->h[i] * SSH_BLOCKSIZE)) {
- if (++same > MAX_IDENTICAL)
- return DEATTACK_DOS_DETECTED;
- if (check_crc(c, buf, len))
- return DEATTACK_DETECTED;
- else
- break;
- }
- }
- dctx->h[i] = j;
- }
- return DEATTACK_OK;
-}
diff --git a/deattack.h b/deattack.h
deleted file mode 100644
index ce67a30f..00000000
--- a/deattack.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* $OpenBSD: deattack.h,v 1.11 2015/01/19 19:52:16 markus Exp $ */
-
-/*
- * Cryptographic attack detector for ssh - Header file
- *
- * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
- *
- * All rights reserved. Redistribution and use in source and binary
- * forms, with or without modification, are permitted provided that
- * this copyright notice is retained.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
- * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
- * SOFTWARE.
- *
- * Ariel Futoransky <futo@core-sdi.com>
- * <http://www.core-sdi.com>
- */
-
-#ifndef _DEATTACK_H
-#define _DEATTACK_H
-
-/* Return codes */
-#define DEATTACK_OK 0
-#define DEATTACK_DETECTED 1
-#define DEATTACK_DOS_DETECTED 2
-#define DEATTACK_ERROR 3
-
-struct deattack_ctx {
- u_int16_t *h;
- u_int32_t n;
-};
-
-void deattack_init(struct deattack_ctx *);
-int detect_attack(struct deattack_ctx *, const u_char *, u_int32_t);
-#endif
diff --git a/defines.h b/defines.h
index fa0ccba7..b8ea88b2 100644
--- a/defines.h
+++ b/defines.h
@@ -25,9 +25,6 @@
#ifndef _DEFINES_H
#define _DEFINES_H
-/* $Id: defines.h,v 1.183 2014/09/02 19:33:26 djm Exp $ */
-
-
/* Constants */
#if defined(HAVE_DECL_SHUT_RD) && HAVE_DECL_SHUT_RD == 0
@@ -43,6 +40,19 @@ enum
#endif
/*
+ * Cygwin doesn't really have a notion of reserved ports. It is still
+ * is useful on the client side so for compatibility it defines as 1024 via
+ * netinet/in.h inside an enum. We * don't actually want that restriction
+ * so we want to set that to zero, but we can't do it direct in config.h
+ * because it'll cause a conflicting definition the first time we include
+ * netinet/in.h.
+ */
+
+#ifdef HAVE_CYGWIN
+#define IPPORT_RESERVED 0
+#endif
+
+/*
* Definitions for IP type of service (ip_tos)
*/
#include <netinet/in_systm.h>
@@ -86,6 +96,18 @@ enum
#ifndef IPTOS_DSCP_EF
# define IPTOS_DSCP_EF 0xb8
#endif /* IPTOS_DSCP_EF */
+#ifndef IPTOS_DSCP_LE
+# define IPTOS_DSCP_LE 0x01
+#endif /* IPTOS_DSCP_LE */
+#ifndef IPTOS_PREC_CRITIC_ECP
+# define IPTOS_PREC_CRITIC_ECP 0xa0
+#endif
+#ifndef IPTOS_PREC_INTERNETCONTROL
+# define IPTOS_PREC_INTERNETCONTROL 0xc0
+#endif
+#ifndef IPTOS_PREC_NETCONTROL
+# define IPTOS_PREC_NETCONTROL 0xe0
+#endif
#ifndef PATH_MAX
# ifdef _POSIX_PATH_MAX
@@ -98,10 +120,6 @@ enum
# define MAXPATHLEN PATH_MAX
# else /* PATH_MAX */
# define MAXPATHLEN 64
-/* realpath uses a fixed buffer of size MAXPATHLEN, so force use of ours */
-# ifndef BROKEN_REALPATH
-# define BROKEN_REALPATH 1
-# endif /* BROKEN_REALPATH */
# endif /* PATH_MAX */
#endif /* MAXPATHLEN */
@@ -204,24 +222,12 @@ typedef signed char int8_t;
# if (SIZEOF_SHORT_INT == 2)
typedef short int int16_t;
# else
-# ifdef _UNICOS
-# if (SIZEOF_SHORT_INT == 4)
-typedef short int16_t;
-# else
-typedef long int16_t;
-# endif
-# else
# error "16 bit int type not found."
-# endif /* _UNICOS */
# endif
# if (SIZEOF_INT == 4)
typedef int int32_t;
# else
-# ifdef _UNICOS
-typedef long int32_t;
-# else
# error "32 bit int type not found."
-# endif /* _UNICOS */
# endif
#endif
@@ -237,29 +243,32 @@ typedef unsigned char u_int8_t;
# if (SIZEOF_SHORT_INT == 2)
typedef unsigned short int u_int16_t;
# else
-# ifdef _UNICOS
-# if (SIZEOF_SHORT_INT == 4)
-typedef unsigned short u_int16_t;
-# else
-typedef unsigned long u_int16_t;
-# endif
-# else
# error "16 bit int type not found."
-# endif
# endif
# if (SIZEOF_INT == 4)
typedef unsigned int u_int32_t;
# else
-# ifdef _UNICOS
-typedef unsigned long u_int32_t;
-# else
# error "32 bit int type not found."
-# endif
# endif
# endif
#define __BIT_TYPES_DEFINED__
#endif
+#if !defined(LLONG_MIN) && defined(LONG_LONG_MIN)
+#define LLONG_MIN LONG_LONG_MIN
+#endif
+#if !defined(LLONG_MAX) && defined(LONG_LONG_MAX)
+#define LLONG_MAX LONG_LONG_MAX
+#endif
+
+#ifndef UINT32_MAX
+# if defined(HAVE_DECL_UINT32_MAX) && (HAVE_DECL_UINT32_MAX == 0)
+# if (SIZEOF_INT == 4)
+# define UINT32_MAX UINT_MAX
+# endif
+# endif
+#endif
+
/* 64-bit types */
#ifndef HAVE_INT64_T
# if (SIZEOF_LONG_INT == 8)
@@ -318,8 +327,31 @@ typedef unsigned int size_t;
#define SIZE_MAX SIZE_T_MAX
#endif
+#ifndef INT32_MAX
+# if (SIZEOF_INT == 4)
+# define INT32_MAX INT_MAX
+# elif (SIZEOF_LONG == 4)
+# define INT32_MAX LONG_MAX
+# else
+# error "need INT32_MAX"
+# endif
+#endif
+
+#ifndef INT64_MAX
+# if (SIZEOF_INT == 8)
+# define INT64_MAX INT_MAX
+# elif (SIZEOF_LONG == 8)
+# define INT64_MAX LONG_MAX
+# elif (SIZEOF_LONG_LONG_INT == 8)
+# define INT64_MAX LLONG_MAX
+# else
+# error "need INT64_MAX"
+# endif
+#endif
+
#ifndef HAVE_SSIZE_T
typedef int ssize_t;
+#define SSIZE_MAX INT_MAX
# define HAVE_SSIZE_T
#endif /* HAVE_SSIZE_T */
@@ -487,6 +519,13 @@ struct winsize {
}
#endif
+#ifndef timespeccmp
+#define timespeccmp(tsp, usp, cmp) \
+ (((tsp)->tv_sec == (usp)->tv_sec) ? \
+ ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
+ ((tsp)->tv_sec cmp (usp)->tv_sec))
+#endif
+
#ifndef __P
# define __P(x) x
#endif
@@ -645,12 +684,6 @@ struct winsize {
# define krb5_get_err_text(context,code) error_message(code)
#endif
-#if defined(SKEYCHALLENGE_4ARG)
-# define _compat_skeychallenge(a,b,c,d) skeychallenge(a,b,c,d)
-#else
-# define _compat_skeychallenge(a,b,c,d) skeychallenge(a,b,c)
-#endif
-
/* Maximum number of file descriptors available */
#ifdef HAVE_SYSCONF
# define SSH_SYSFDMAX sysconf(_SC_OPEN_MAX)
@@ -823,6 +856,14 @@ struct winsize {
#endif
/*
+ * We want functions in openbsd-compat, if enabled, to override system ones.
+ * We no-op out the weak symbol definition rather than remove it to reduce
+ * future sync problems. Some compilers (eg Unixware) do not allow an
+ * empty statement, so we use a bogus function declaration.
+ */
+#define DEF_WEAK(x) void __ssh_compat_weak_##x(void)
+
+/*
* Platforms that have arc4random_uniform() and not arc4random_stir()
* shouldn't need the latter.
*/
@@ -850,4 +891,11 @@ struct winsize {
# endif /* gcc version */
#endif /* __predict_true */
+#if defined(HAVE_GLOB_H) && defined(GLOB_HAS_ALTDIRFUNC) && \
+ defined(GLOB_HAS_GL_MATCHC) && defined(GLOB_HAS_GL_STATV) && \
+ defined(HAVE_DECL_GLOB_NOMATCH) && HAVE_DECL_GLOB_NOMATCH != 0 && \
+ !defined(BROKEN_GLOB)
+# define USE_SYSTEM_GLOB
+#endif
+
#endif /* _DEFINES_H */
diff --git a/dh.c b/dh.c
index 91f8ac05..7cb135d7 100644
--- a/dh.c
+++ b/dh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dh.c,v 1.55 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: dh.c,v 1.71 2019/09/06 06:08:11 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
*
@@ -25,23 +25,26 @@
#include "includes.h"
-#include <sys/param.h> /* MIN */
-
-#include <openssl/bn.h>
-#include <openssl/dh.h>
+#ifdef WITH_OPENSSL
+#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include <openssl/bn.h>
+#include <openssl/dh.h>
+
#include "dh.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "ssherr.h"
+#include "openbsd-compat/openssl-compat.h"
+
static int
parse_prime(int linenum, char *line, struct dhgroup *dhg)
{
@@ -134,10 +137,8 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg)
return 1;
fail:
- if (dhg->g != NULL)
- BN_clear_free(dhg->g);
- if (dhg->p != NULL)
- BN_clear_free(dhg->p);
+ BN_clear_free(dhg->g);
+ BN_clear_free(dhg->p);
dhg->g = dhg->p = NULL;
return 0;
}
@@ -146,21 +147,20 @@ DH *
choose_dh(int min, int wantbits, int max)
{
FILE *f;
- char line[4096];
- int best, bestcount, which;
- int linenum;
+ char *line = NULL;
+ size_t linesize = 0;
+ int best, bestcount, which, linenum;
struct dhgroup dhg;
- if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL &&
- (f = fopen(_PATH_DH_PRIMES, "r")) == NULL) {
- logit("WARNING: %s does not exist, using fixed modulus",
- _PATH_DH_MODULI);
- return (dh_new_group14());
+ if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL) {
+ logit("WARNING: could not open %s (%s), using fixed modulus",
+ _PATH_DH_MODULI, strerror(errno));
+ return (dh_new_group_fallback(max));
}
linenum = 0;
best = bestcount = 0;
- while (fgets(line, sizeof(line), f)) {
+ while (getline(&line, &linesize, f) != -1) {
linenum++;
if (!parse_prime(linenum, line, &dhg))
continue;
@@ -178,33 +178,40 @@ choose_dh(int min, int wantbits, int max)
if (dhg.size == best)
bestcount++;
}
+ free(line);
+ line = NULL;
+ linesize = 0;
rewind(f);
if (bestcount == 0) {
fclose(f);
- logit("WARNING: no suitable primes in %s", _PATH_DH_PRIMES);
- return (dh_new_group14());
+ logit("WARNING: no suitable primes in %s", _PATH_DH_MODULI);
+ return (dh_new_group_fallback(max));
}
+ which = arc4random_uniform(bestcount);
linenum = 0;
- which = arc4random_uniform(bestcount);
- while (fgets(line, sizeof(line), f)) {
+ bestcount = 0;
+ while (getline(&line, &linesize, f) != -1) {
+ linenum++;
if (!parse_prime(linenum, line, &dhg))
continue;
if ((dhg.size > max || dhg.size < min) ||
dhg.size != best ||
- linenum++ != which) {
+ bestcount++ != which) {
BN_clear_free(dhg.g);
BN_clear_free(dhg.p);
continue;
}
break;
}
+ free(line);
+ line = NULL;
fclose(f);
- if (linenum != which+1) {
- logit("WARNING: line %d disappeared in %s, giving up",
- which, _PATH_DH_PRIMES);
- return (dh_new_group14());
+ if (bestcount != which + 1) {
+ logit("WARNING: selected prime disappeared in %s, giving up",
+ _PATH_DH_MODULI);
+ return (dh_new_group_fallback(max));
}
return (dh_new_group(dhg.g, dhg.p));
@@ -213,14 +220,17 @@ choose_dh(int min, int wantbits, int max)
/* diffie-hellman-groupN-sha1 */
int
-dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
+dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub)
{
int i;
int n = BN_num_bits(dh_pub);
int bits_set = 0;
BIGNUM *tmp;
+ const BIGNUM *dh_p;
- if (dh_pub->neg) {
+ DH_get0_pqg(dh, &dh_p, NULL, NULL);
+
+ if (BN_is_negative(dh_pub)) {
logit("invalid public DH value: negative");
return 0;
}
@@ -233,7 +243,7 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
error("%s: BN_new failed", __func__);
return 0;
}
- if (!BN_sub(tmp, dh->p, BN_value_one()) ||
+ if (!BN_sub(tmp, dh_p, BN_value_one()) ||
BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */
BN_clear_free(tmp);
logit("invalid public DH value: >= p-1");
@@ -244,36 +254,45 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
for (i = 0; i <= n; i++)
if (BN_is_bit_set(dh_pub, i))
bits_set++;
- debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
-
- /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
- if (bits_set > 1)
- return 1;
-
- logit("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
- return 0;
+ debug2("bits set: %d/%d", bits_set, BN_num_bits(dh_p));
+
+ /*
+ * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial
+ */
+ if (bits_set < 4) {
+ logit("invalid public DH value (%d/%d)",
+ bits_set, BN_num_bits(dh_p));
+ return 0;
+ }
+ return 1;
}
int
dh_gen_key(DH *dh, int need)
{
int pbits;
+ const BIGNUM *dh_p, *pub_key;
+
+ DH_get0_pqg(dh, &dh_p, NULL, NULL);
- if (need < 0 || dh->p == NULL ||
- (pbits = BN_num_bits(dh->p)) <= 0 ||
- need > INT_MAX / 2 || 2 * need >= pbits)
+ if (need < 0 || dh_p == NULL ||
+ (pbits = BN_num_bits(dh_p)) <= 0 ||
+ need > INT_MAX / 2 || 2 * need > pbits)
return SSH_ERR_INVALID_ARGUMENT;
-#if !defined(OPENSSL_IS_BORINGSSL)
- /* BoringSSL renamed |length| to |priv_length| to better reflect its
- * actual use. Also, BoringSSL recognises common groups and chooses the
- * length of the private exponent accoringly. */
- dh->length = MIN(need * 2, pbits - 1);
-#endif
- if (DH_generate_key(dh) == 0 ||
- !dh_pub_is_valid(dh, dh->pub_key)) {
- BN_clear_free(dh->priv_key);
+ if (need < 256)
+ need = 256;
+ /*
+ * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)),
+ * so double requested need here.
+ */
+ if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1)))
return SSH_ERR_LIBCRYPTO_ERROR;
- }
+
+ if (DH_generate_key(dh) == 0)
+ return SSH_ERR_LIBCRYPTO_ERROR;
+ DH_get0_key(dh, &pub_key, NULL);
+ if (!dh_pub_is_valid(dh, pub_key))
+ return SSH_ERR_INVALID_FORMAT;
return 0;
}
@@ -281,22 +300,27 @@ DH *
dh_new_group_asc(const char *gen, const char *modulus)
{
DH *dh;
+ BIGNUM *dh_p = NULL, *dh_g = NULL;
if ((dh = DH_new()) == NULL)
return NULL;
- if (BN_hex2bn(&dh->p, modulus) == 0 ||
- BN_hex2bn(&dh->g, gen) == 0) {
- DH_free(dh);
- return NULL;
- }
- return (dh);
+ if (BN_hex2bn(&dh_p, modulus) == 0 ||
+ BN_hex2bn(&dh_g, gen) == 0)
+ goto fail;
+ if (!DH_set0_pqg(dh, dh_p, NULL, dh_g))
+ goto fail;
+ return dh;
+ fail:
+ DH_free(dh);
+ BN_clear_free(dh_p);
+ BN_clear_free(dh_g);
+ return NULL;
}
/*
* This just returns the group, we still need to generate the exchange
* value.
*/
-
DH *
dh_new_group(BIGNUM *gen, BIGNUM *modulus)
{
@@ -304,12 +328,15 @@ dh_new_group(BIGNUM *gen, BIGNUM *modulus)
if ((dh = DH_new()) == NULL)
return NULL;
- dh->p = modulus;
- dh->g = gen;
+ if (!DH_set0_pqg(dh, modulus, NULL, gen)) {
+ DH_free(dh);
+ return NULL;
+ }
- return (dh);
+ return dh;
}
+/* rfc2409 "Second Oakley Group" (1024 bits) */
DH *
dh_new_group1(void)
{
@@ -324,6 +351,7 @@ dh_new_group1(void)
return (dh_new_group_asc(gen, group1));
}
+/* rfc3526 group 14 "2048-bit MODP Group" */
DH *
dh_new_group14(void)
{
@@ -343,6 +371,105 @@ dh_new_group14(void)
return (dh_new_group_asc(gen, group14));
}
+/* rfc3526 group 16 "4096-bit MODP Group" */
+DH *
+dh_new_group16(void)
+{
+ static char *gen = "2", *group16 =
+ "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
+ "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
+ "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
+ "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
+ "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
+ "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
+ "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
+ "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
+ "15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64"
+ "ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7"
+ "ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B"
+ "F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C"
+ "BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31"
+ "43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7"
+ "88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA"
+ "2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6"
+ "287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED"
+ "1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9"
+ "93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34063199"
+ "FFFFFFFF" "FFFFFFFF";
+
+ return (dh_new_group_asc(gen, group16));
+}
+
+/* rfc3526 group 18 "8192-bit MODP Group" */
+DH *
+dh_new_group18(void)
+{
+ static char *gen = "2", *group18 =
+ "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
+ "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
+ "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
+ "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
+ "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
+ "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
+ "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
+ "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
+ "15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64"
+ "ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7"
+ "ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B"
+ "F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C"
+ "BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31"
+ "43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7"
+ "88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA"
+ "2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6"
+ "287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED"
+ "1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9"
+ "93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34028492"
+ "36C3FAB4" "D27C7026" "C1D4DCB2" "602646DE" "C9751E76" "3DBA37BD"
+ "F8FF9406" "AD9E530E" "E5DB382F" "413001AE" "B06A53ED" "9027D831"
+ "179727B0" "865A8918" "DA3EDBEB" "CF9B14ED" "44CE6CBA" "CED4BB1B"
+ "DB7F1447" "E6CC254B" "33205151" "2BD7AF42" "6FB8F401" "378CD2BF"
+ "5983CA01" "C64B92EC" "F032EA15" "D1721D03" "F482D7CE" "6E74FEF6"
+ "D55E702F" "46980C82" "B5A84031" "900B1C9E" "59E7C97F" "BEC7E8F3"
+ "23A97A7E" "36CC88BE" "0F1D45B7" "FF585AC5" "4BD407B2" "2B4154AA"
+ "CC8F6D7E" "BF48E1D8" "14CC5ED2" "0F8037E0" "A79715EE" "F29BE328"
+ "06A1D58B" "B7C5DA76" "F550AA3D" "8A1FBFF0" "EB19CCB1" "A313D55C"
+ "DA56C9EC" "2EF29632" "387FE8D7" "6E3C0468" "043E8F66" "3F4860EE"
+ "12BF2D5B" "0B7474D6" "E694F91E" "6DBE1159" "74A3926F" "12FEE5E4"
+ "38777CB6" "A932DF8C" "D8BEC4D0" "73B931BA" "3BC832B6" "8D9DD300"
+ "741FA7BF" "8AFC47ED" "2576F693" "6BA42466" "3AAB639C" "5AE4F568"
+ "3423B474" "2BF1C978" "238F16CB" "E39D652D" "E3FDB8BE" "FC848AD9"
+ "22222E04" "A4037C07" "13EB57A8" "1A23F0C7" "3473FC64" "6CEA306B"
+ "4BCBC886" "2F8385DD" "FA9D4B7F" "A2C087E8" "79683303" "ED5BDD3A"
+ "062B3CF5" "B3A278A6" "6D2A13F8" "3F44F82D" "DF310EE0" "74AB6A36"
+ "4597E899" "A0255DC1" "64F31CC5" "0846851D" "F9AB4819" "5DED7EA1"
+ "B1D510BD" "7EE74D73" "FAF36BC3" "1ECFA268" "359046F4" "EB879F92"
+ "4009438B" "481C6CD7" "889A002E" "D5EE382B" "C9190DA6" "FC026E47"
+ "9558E447" "5677E9AA" "9E3050E2" "765694DF" "C81F56E8" "80B96E71"
+ "60C980DD" "98EDD3DF" "FFFFFFFF" "FFFFFFFF";
+
+ return (dh_new_group_asc(gen, group18));
+}
+
+/* Select fallback group used by DH-GEX if moduli file cannot be read. */
+DH *
+dh_new_group_fallback(int max)
+{
+ debug3("%s: requested max size %d", __func__, max);
+ if (max < 3072) {
+ debug3("using 2k bit group 14");
+ return dh_new_group14();
+ } else if (max < 6144) {
+ debug3("using 4k bit group 16");
+ return dh_new_group16();
+ }
+ debug3("using 8k bit group 18");
+ return dh_new_group18();
+}
+
/*
* Estimates the group order for a Diffie-Hellman group that has an
* attack complexity approximately the same as O(2**bits).
@@ -350,7 +477,6 @@ dh_new_group14(void)
* Management Part 1 (rev 3) limited by the recommended maximum value
* from RFC4419 section 3.
*/
-
u_int
dh_estimate(int bits)
{
@@ -362,3 +488,5 @@ dh_estimate(int bits)
return 7680;
return 8192;
}
+
+#endif /* WITH_OPENSSL */
diff --git a/dh.h b/dh.h
index 63a1b147..5d6df629 100644
--- a/dh.h
+++ b/dh.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dh.h,v 1.12 2015/01/19 20:16:15 markus Exp $ */
+/* $OpenBSD: dh.h,v 1.18 2019/09/06 05:23:55 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
@@ -26,6 +26,8 @@
#ifndef DH_H
#define DH_H
+#ifdef WITH_OPENSSL
+
struct dhgroup {
int size;
BIGNUM *g;
@@ -37,14 +39,20 @@ DH *dh_new_group_asc(const char *, const char *);
DH *dh_new_group(BIGNUM *, BIGNUM *);
DH *dh_new_group1(void);
DH *dh_new_group14(void);
+DH *dh_new_group16(void);
+DH *dh_new_group18(void);
+DH *dh_new_group_fallback(int);
int dh_gen_key(DH *, int);
-int dh_pub_is_valid(DH *, BIGNUM *);
+int dh_pub_is_valid(const DH *, const BIGNUM *);
u_int dh_estimate(int);
-/* Min and max values from RFC4419. */
-#define DH_GRP_MIN 1024
+/*
+ * Max value from RFC4419.
+ * Min value from RFC8270.
+ */
+#define DH_GRP_MIN 2048
#define DH_GRP_MAX 8192
/*
@@ -70,5 +78,6 @@ u_int dh_estimate(int);
#define MODULI_TESTS_JACOBI (0x08)
#define MODULI_TESTS_ELLIPTIC (0x10)
+#endif /* WITH_OPENSSL */
-#endif
+#endif /* DH_H */
diff --git a/digest-libc.c b/digest-libc.c
index a216e784..86a1dbf2 100644
--- a/digest-libc.c
+++ b/digest-libc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: digest-libc.c,v 1.4 2014/12/21 22:27:56 djm Exp $ */
+/* $OpenBSD: digest-libc.c,v 1.7 2020/02/26 13:40:09 jsg Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
* Copyright (c) 2014 Markus Friedl. All rights reserved.
@@ -28,7 +28,11 @@
#if 0
#include <md5.h>
#include <rmd160.h>
+#endif
+#ifdef HAVE_SHA1_H
#include <sha1.h>
+#endif
+#ifdef HAVE_SHA2_H
#include <sha2.h>
#endif
@@ -69,16 +73,6 @@ const struct ssh_digest digests[SSH_DIGEST_MAX] = {
(md_final_fn *) MD5Final
},
{
- SSH_DIGEST_RIPEMD160,
- "RIPEMD160",
- RMD160_BLOCK_LENGTH,
- RMD160_DIGEST_LENGTH,
- sizeof(RMD160_CTX),
- (md_init_fn *) RMD160Init,
- (md_update_fn *) RMD160Update,
- (md_final_fn *) RMD160Final
- },
- {
SSH_DIGEST_SHA1,
"SHA1",
SHA1_BLOCK_LENGTH,
@@ -93,30 +87,30 @@ const struct ssh_digest digests[SSH_DIGEST_MAX] = {
"SHA256",
SHA256_BLOCK_LENGTH,
SHA256_DIGEST_LENGTH,
- sizeof(SHA256_CTX),
- (md_init_fn *) SHA256_Init,
- (md_update_fn *) SHA256_Update,
- (md_final_fn *) SHA256_Final
+ sizeof(SHA2_CTX),
+ (md_init_fn *) SHA256Init,
+ (md_update_fn *) SHA256Update,
+ (md_final_fn *) SHA256Final
},
{
SSH_DIGEST_SHA384,
"SHA384",
SHA384_BLOCK_LENGTH,
SHA384_DIGEST_LENGTH,
- sizeof(SHA384_CTX),
- (md_init_fn *) SHA384_Init,
- (md_update_fn *) SHA384_Update,
- (md_final_fn *) SHA384_Final
+ sizeof(SHA2_CTX),
+ (md_init_fn *) SHA384Init,
+ (md_update_fn *) SHA384Update,
+ (md_final_fn *) SHA384Final
},
{
SSH_DIGEST_SHA512,
"SHA512",
SHA512_BLOCK_LENGTH,
SHA512_DIGEST_LENGTH,
- sizeof(SHA512_CTX),
- (md_init_fn *) SHA512_Init,
- (md_update_fn *) SHA512_Update,
- (md_final_fn *) SHA512_Final
+ sizeof(SHA2_CTX),
+ (md_init_fn *) SHA512Init,
+ (md_update_fn *) SHA512Update,
+ (md_final_fn *) SHA512Final
}
};
@@ -172,7 +166,7 @@ ssh_digest_start(int alg)
const struct ssh_digest *digest = ssh_digest_by_alg(alg);
struct ssh_digest_ctx *ret;
- if (digest == NULL || (ret = calloc(1, sizeof(ret))) == NULL)
+ if (digest == NULL || (ret = calloc(1, sizeof(*ret))) == NULL)
return NULL;
if ((ret->mdctx = calloc(1, digest->ctx_len)) == NULL) {
free(ret);
@@ -236,8 +230,7 @@ ssh_digest_free(struct ssh_digest_ctx *ctx)
if (digest) {
explicit_bzero(ctx->mdctx, digest->ctx_len);
free(ctx->mdctx);
- explicit_bzero(ctx, sizeof(*ctx));
- free(ctx);
+ freezero(ctx, sizeof(*ctx));
}
}
}
diff --git a/digest-openssl.c b/digest-openssl.c
index 13b63c2f..dbbea425 100644
--- a/digest-openssl.c
+++ b/digest-openssl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: digest-openssl.c,v 1.5 2014/12/21 22:27:56 djm Exp $ */
+/* $OpenBSD: digest-openssl.c,v 1.7 2017/05/08 22:57:38 djm Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
*
@@ -32,18 +32,19 @@
#include "digest.h"
#include "ssherr.h"
-#ifndef HAVE_EVP_RIPEMD160
-# define EVP_ripemd160 NULL
-#endif /* HAVE_EVP_RIPEMD160 */
#ifndef HAVE_EVP_SHA256
# define EVP_sha256 NULL
+#endif
+#ifndef HAVE_EVP_SHA384
# define EVP_sha384 NULL
+#endif
+#ifndef HAVE_EVP_SHA512
# define EVP_sha512 NULL
-#endif /* HAVE_EVP_SHA256 */
+#endif
struct ssh_digest_ctx {
int alg;
- EVP_MD_CTX mdctx;
+ EVP_MD_CTX *mdctx;
};
struct ssh_digest {
@@ -56,7 +57,6 @@ struct ssh_digest {
/* NB. Indexed directly by algorithm number */
const struct ssh_digest digests[] = {
{ SSH_DIGEST_MD5, "MD5", 16, EVP_md5 },
- { SSH_DIGEST_RIPEMD160, "RIPEMD160", 20, EVP_ripemd160 },
{ SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 },
{ SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 },
{ SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 },
@@ -107,7 +107,7 @@ ssh_digest_bytes(int alg)
size_t
ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
{
- return EVP_MD_CTX_block_size(&ctx->mdctx);
+ return EVP_MD_CTX_block_size(ctx->mdctx);
}
struct ssh_digest_ctx *
@@ -119,11 +119,14 @@ ssh_digest_start(int alg)
if (digest == NULL || ((ret = calloc(1, sizeof(*ret))) == NULL))
return NULL;
ret->alg = alg;
- EVP_MD_CTX_init(&ret->mdctx);
- if (EVP_DigestInit_ex(&ret->mdctx, digest->mdfunc(), NULL) != 1) {
+ if ((ret->mdctx = EVP_MD_CTX_new()) == NULL) {
free(ret);
return NULL;
}
+ if (EVP_DigestInit_ex(ret->mdctx, digest->mdfunc(), NULL) != 1) {
+ ssh_digest_free(ret);
+ return NULL;
+ }
return ret;
}
@@ -133,7 +136,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
if (from->alg != to->alg)
return SSH_ERR_INVALID_ARGUMENT;
/* we have bcopy-style order while openssl has memcpy-style */
- if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx))
+ if (!EVP_MD_CTX_copy_ex(to->mdctx, from->mdctx))
return SSH_ERR_LIBCRYPTO_ERROR;
return 0;
}
@@ -141,7 +144,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
int
ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
{
- if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1)
+ if (EVP_DigestUpdate(ctx->mdctx, m, mlen) != 1)
return SSH_ERR_LIBCRYPTO_ERROR;
return 0;
}
@@ -158,11 +161,11 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
u_int l = dlen;
- if (dlen > UINT_MAX)
+ if (digest == NULL || dlen > UINT_MAX)
return SSH_ERR_INVALID_ARGUMENT;
if (dlen < digest->digest_len) /* No truncation allowed */
return SSH_ERR_INVALID_ARGUMENT;
- if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1)
+ if (EVP_DigestFinal_ex(ctx->mdctx, d, &l) != 1)
return SSH_ERR_LIBCRYPTO_ERROR;
if (l != digest->digest_len) /* sanity */
return SSH_ERR_INTERNAL_ERROR;
@@ -172,11 +175,10 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
void
ssh_digest_free(struct ssh_digest_ctx *ctx)
{
- if (ctx != NULL) {
- EVP_MD_CTX_cleanup(&ctx->mdctx);
- explicit_bzero(ctx, sizeof(*ctx));
- free(ctx);
- }
+ if (ctx == NULL)
+ return;
+ EVP_MD_CTX_free(ctx->mdctx);
+ freezero(ctx, sizeof(*ctx));
}
int
diff --git a/digest.h b/digest.h
index 3fe07346..274574d0 100644
--- a/digest.h
+++ b/digest.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: digest.h,v 1.7 2014/12/21 22:27:56 djm Exp $ */
+/* $OpenBSD: digest.h,v 1.8 2017/05/08 22:57:38 djm Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
*
@@ -23,12 +23,11 @@
/* Digest algorithms */
#define SSH_DIGEST_MD5 0
-#define SSH_DIGEST_RIPEMD160 1
-#define SSH_DIGEST_SHA1 2
-#define SSH_DIGEST_SHA256 3
-#define SSH_DIGEST_SHA384 4
-#define SSH_DIGEST_SHA512 5
-#define SSH_DIGEST_MAX 6
+#define SSH_DIGEST_SHA1 1
+#define SSH_DIGEST_SHA256 2
+#define SSH_DIGEST_SHA384 3
+#define SSH_DIGEST_SHA512 4
+#define SSH_DIGEST_MAX 5
struct sshbuf;
struct ssh_digest_ctx;
diff --git a/dispatch.c b/dispatch.c
index afe61822..6e4c501e 100644
--- a/dispatch.c
+++ b/dispatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dispatch.c,v 1.26 2015/02/12 20:34:19 dtucker Exp $ */
+/* $OpenBSD: dispatch.c,v 1.32 2019/01/19 21:33:13 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -30,7 +30,6 @@
#include <signal.h>
#include <stdarg.h>
-#include "ssh1.h"
#include "ssh2.h"
#include "log.h"
#include "dispatch.h"
@@ -39,24 +38,21 @@
#include "ssherr.h"
int
-dispatch_protocol_error(int type, u_int32_t seq, void *ctx)
+dispatch_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
{
- struct ssh *ssh = active_state; /* XXX */
int r;
logit("dispatch_protocol_error: type %d seq %u", type, seq);
- if (!compat20)
- fatal("protocol error");
if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
(r = sshpkt_put_u32(ssh, seq)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
- sshpkt_fatal(ssh, __func__, r);
+ sshpkt_fatal(ssh, r, "%s", __func__);
return 0;
}
int
-dispatch_protocol_ignore(int type, u_int32_t seq, void *ssh)
+dispatch_protocol_ignore(int type, u_int32_t seq, struct ssh *ssh)
{
logit("dispatch_protocol_ignore: type %d seq %u", type, seq);
return 0;
@@ -89,8 +85,7 @@ ssh_dispatch_set(struct ssh *ssh, int type, dispatch_fn *fn)
}
int
-ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done,
- void *ctxt)
+ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done)
{
int r;
u_char type;
@@ -115,8 +110,7 @@ ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done,
ssh->dispatch_skip_packets--;
continue;
}
- /* XXX 'ssh' will replace 'ctxt' later */
- r = (*ssh->dispatch[type])(type, seqnr, ctxt);
+ r = (*ssh->dispatch[type])(type, seqnr, ssh);
if (r != 0)
return r;
} else {
@@ -132,27 +126,10 @@ ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done,
}
void
-ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done,
- void *ctxt)
+ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done)
{
int r;
- if ((r = ssh_dispatch_run(ssh, mode, done, ctxt)) != 0) {
- switch (r) {
- case SSH_ERR_CONN_CLOSED:
- logit("Connection closed by %.200s",
- ssh_remote_ipaddr(ssh));
- cleanup_exit(255);
- case SSH_ERR_CONN_TIMEOUT:
- logit("Connection to %.200s timed out while "
- "waiting to read", ssh_remote_ipaddr(ssh));
- cleanup_exit(255);
- case SSH_ERR_DISCONNECTED:
- logit("Disconnected from %.200s",
- ssh_remote_ipaddr(ssh));
- cleanup_exit(255);
- default:
- fatal("%s: %s", __func__, ssh_err(r));
- }
- }
+ if ((r = ssh_dispatch_run(ssh, mode, done)) != 0)
+ sshpkt_fatal(ssh, r, "%s", __func__);
}
diff --git a/dispatch.h b/dispatch.h
index cd51dbc0..a22d7749 100644
--- a/dispatch.h
+++ b/dispatch.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dispatch.h,v 1.12 2015/01/19 20:07:45 markus Exp $ */
+/* $OpenBSD: dispatch.h,v 1.15 2019/01/19 21:45:31 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -36,23 +36,14 @@ enum {
struct ssh;
-typedef int dispatch_fn(int, u_int32_t, void *);
+typedef int dispatch_fn(int, u_int32_t, struct ssh *);
-int dispatch_protocol_error(int, u_int32_t, void *);
-int dispatch_protocol_ignore(int, u_int32_t, void *);
+int dispatch_protocol_error(int, u_int32_t, struct ssh *);
+int dispatch_protocol_ignore(int, u_int32_t, struct ssh *);
void ssh_dispatch_init(struct ssh *, dispatch_fn *);
void ssh_dispatch_set(struct ssh *, int, dispatch_fn *);
void ssh_dispatch_range(struct ssh *, u_int, u_int, dispatch_fn *);
-int ssh_dispatch_run(struct ssh *, int, volatile sig_atomic_t *, void *);
-void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *, void *);
-
-#define dispatch_init(dflt) \
- ssh_dispatch_init(active_state, (dflt))
-#define dispatch_range(from, to, fn) \
- ssh_dispatch_range(active_state, (from), (to), (fn))
-#define dispatch_set(type, fn) \
- ssh_dispatch_set(active_state, (type), (fn))
-#define dispatch_run(mode, done, ctxt) \
- ssh_dispatch_run_fatal(active_state, (mode), (done), (ctxt))
+int ssh_dispatch_run(struct ssh *, int, volatile sig_atomic_t *);
+void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *);
#endif
diff --git a/dns.c b/dns.c
index 827f853e..cb375c85 100644
--- a/dns.c
+++ b/dns.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.c,v 1.34 2015/01/28 22:36:00 djm Exp $ */
+/* $OpenBSD: dns.c,v 1.38 2018/02/23 15:58:37 markus Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -34,7 +34,6 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
-#include <stdarg.h>
#include <stdlib.h>
#include "xmalloc.h"
@@ -105,6 +104,11 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
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 */
@@ -154,7 +158,7 @@ dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type,
*digest_len = rdata_len - 2;
if (*digest_len > 0) {
- *digest = (u_char *) xmalloc(*digest_len);
+ *digest = xmalloc(*digest_len);
memcpy(*digest, rdata + 2, *digest_len);
} else {
*digest = (u_char *)xstrdup("");
diff --git a/dns.h b/dns.h
index 815f073a..91f3c632 100644
--- a/dns.h
+++ b/dns.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.h,v 1.14 2015/01/15 09:40:00 djm Exp $ */
+/* $OpenBSD: dns.h,v 1.18 2018/02/23 15:58:37 markus Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -33,7 +33,8 @@ enum sshfp_types {
SSHFP_KEY_RSA = 1,
SSHFP_KEY_DSA = 2,
SSHFP_KEY_ECDSA = 3,
- SSHFP_KEY_ED25519 = 4
+ SSHFP_KEY_ED25519 = 4,
+ SSHFP_KEY_XMSS = 5
};
enum sshfp_hashes {
diff --git a/entropy.c b/entropy.c
index 9305f89a..19ddeeaf 100644
--- a/entropy.c
+++ b/entropy.c
@@ -24,6 +24,8 @@
#include "includes.h"
+#define RANDOM_SEED_SIZE 48
+
#ifdef WITH_OPENSSL
#include <sys/types.h>
@@ -37,6 +39,7 @@
#include <errno.h>
#include <signal.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stddef.h> /* for offsetof */
@@ -53,7 +56,8 @@
#include "atomicio.h"
#include "pathnames.h"
#include "log.h"
-#include "buffer.h"
+#include "sshbuf.h"
+#include "ssherr.h"
/*
* Portable OpenSSH PRNG seeding:
@@ -63,8 +67,6 @@
*/
#ifndef OPENSSL_PRNG_ONLY
-#define RANDOM_SEED_SIZE 48
-
/*
* Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon
* listening either on 'tcp_port', or via Unix domain socket at *
@@ -82,7 +84,7 @@ get_random_bytes_prngd(unsigned char *buf, int len,
struct sockaddr_storage addr;
struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
struct sockaddr_un *addr_un = (struct sockaddr_un *)&addr;
- mysig_t old_sigpipe;
+ sshsig_t old_sigpipe;
/* Sanity checks */
if (socket_path == NULL && tcp_port == 0)
@@ -108,7 +110,7 @@ get_random_bytes_prngd(unsigned char *buf, int len,
strlen(socket_path) + 1;
}
- old_sigpipe = mysignal(SIGPIPE, SIG_IGN);
+ old_sigpipe = ssh_signal(SIGPIPE, SIG_IGN);
errors = 0;
rval = -1;
@@ -158,7 +160,7 @@ reopen:
rval = 0;
done:
- mysignal(SIGPIPE, old_sigpipe);
+ ssh_signal(SIGPIPE, old_sigpipe);
if (fd != -1)
close(fd);
return rval;
@@ -181,64 +183,84 @@ seed_from_prngd(unsigned char *buf, size_t bytes)
}
void
-rexec_send_rng_seed(Buffer *m)
+rexec_send_rng_seed(struct sshbuf *m)
{
u_char buf[RANDOM_SEED_SIZE];
+ size_t len = sizeof(buf);
+ int r;
if (RAND_bytes(buf, sizeof(buf)) <= 0) {
error("Couldn't obtain random bytes (error %ld)",
ERR_get_error());
- buffer_put_string(m, "", 0);
- } else
- buffer_put_string(m, buf, sizeof(buf));
+ len = 0;
+ }
+ if ((r = sshbuf_put_string(m, buf, len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ explicit_bzero(buf, sizeof(buf));
}
void
-rexec_recv_rng_seed(Buffer *m)
+rexec_recv_rng_seed(struct sshbuf *m)
{
- u_char *buf;
- u_int len;
+ const u_char *buf = NULL;
+ size_t len = 0;
+ int r;
- buf = buffer_get_string_ret(m, &len);
- if (buf != NULL) {
- debug3("rexec_recv_rng_seed: seeding rng with %u bytes", len);
- RAND_add(buf, len, len);
- }
+ if ((r = sshbuf_get_string_direct(m, &buf, &len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
+ debug3("rexec_recv_rng_seed: seeding rng with %lu bytes",
+ (unsigned long)len);
+ RAND_add(buf, len, len);
}
#endif /* OPENSSL_PRNG_ONLY */
void
seed_rng(void)
{
-#ifndef OPENSSL_PRNG_ONLY
unsigned char buf[RANDOM_SEED_SIZE];
-#endif
- if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER, SSLeay()))
+
+ /* Initialise libcrypto */
+ ssh_libcrypto_init();
+
+ if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER,
+ OpenSSL_version_num()))
fatal("OpenSSL version mismatch. Built against %lx, you "
- "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
+ "have %lx", (u_long)OPENSSL_VERSION_NUMBER,
+ OpenSSL_version_num());
#ifndef OPENSSL_PRNG_ONLY
- if (RAND_status() == 1) {
+ if (RAND_status() == 1)
debug3("RNG is ready, skipping seeding");
- return;
+ else {
+ if (seed_from_prngd(buf, sizeof(buf)) == -1)
+ fatal("Could not obtain seed from PRNGd");
+ RAND_add(buf, sizeof(buf), sizeof(buf));
}
-
- if (seed_from_prngd(buf, sizeof(buf)) == -1)
- fatal("Could not obtain seed from PRNGd");
- RAND_add(buf, sizeof(buf), sizeof(buf));
- memset(buf, '\0', sizeof(buf));
-
#endif /* OPENSSL_PRNG_ONLY */
+
if (RAND_status() != 1)
fatal("PRNG is not seeded");
+
+ /* Ensure arc4random() is primed */
+ arc4random_buf(buf, sizeof(buf));
+ explicit_bzero(buf, sizeof(buf));
}
#else /* WITH_OPENSSL */
-/* Handled in arc4random() */
+#include <stdlib.h>
+#include <string.h>
+
+/* Actual initialisation is handled in arc4random() */
void
seed_rng(void)
{
+ unsigned char buf[RANDOM_SEED_SIZE];
+
+ /* Ensure arc4random() is primed */
+ arc4random_buf(buf, sizeof(buf));
+ explicit_bzero(buf, sizeof(buf));
}
#endif /* WITH_OPENSSL */
diff --git a/entropy.h b/entropy.h
index c3d78dba..870164d3 100644
--- a/entropy.h
+++ b/entropy.h
@@ -22,16 +22,13 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $Id: entropy.h,v 1.6 2011/09/09 01:29:41 dtucker Exp $ */
-
#ifndef _RANDOMS_H
#define _RANDOMS_H
-#include "buffer.h"
+struct sshbuf;
void seed_rng(void);
-
-void rexec_send_rng_seed(Buffer *);
-void rexec_recv_rng_seed(Buffer *);
+void rexec_send_rng_seed(struct sshbuf *);
+void rexec_recv_rng_seed(struct sshbuf *);
#endif /* _RANDOMS_H */
diff --git a/fixprogs b/fixprogs
deleted file mode 100755
index af76ee39..00000000
--- a/fixprogs
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/perl
-#
-# fixprogs - run through the list of entropy commands and
-# score out the losers
-#
-
-$entscale = 50; # divisor for optional entropy measurement
-
-sub usage {
- return("Usage: $0 <command file>\n");
-}
-
-if (($#ARGV == -1) || ($#ARGV>1)) {
- die(&usage);
-}
-
-# 'undocumented' option - run ent (in second param) on the output
-if ($#ARGV==1) {
- $entcmd=$ARGV[1]
-} else {
- $entcmd = ""
-};
-
-$infilename = $ARGV[0];
-
-if (!open(IN, "<".$infilename)) {
- die("Couldn't open input file");
-}
-$outfilename=$infilename.".out";
-if (!open(OUT, ">$outfilename")) {
- die("Couldn't open output file $outfilename");
-}
-@infile=<IN>;
-
-select(OUT); $|=1; select(STDOUT);
-
-foreach (@infile) {
- if (/^\s*\#/ || /^\s*$/) {
- print OUT;
- next;
- }
- ($cmd, $path, $est) = /^\"([^\"]+)\"\s+([\w\/_-]+)\s+([\d\.\-]+)/o;
- @args = split(/ /, $cmd);
- if (! ($pid = fork())) {
- # child
- close STDIN; close STDOUT; close STDERR;
- open (STDIN, "</dev/null");
- open (STDOUT, ">/dev/null");
- open (STDERR, ">/dev/null");
- exec $path @args;
- exit 1; # shouldn't be here
- }
- # parent
- waitpid ($pid, 0); $ret=$? >> 8;
-
- if ($ret != 0) {
- $path = "undef";
- } else {
- if ($entcmd ne "") {
- # now try to run ent on the command
- $mostargs=join(" ", splice(@args,1));
- print "Evaluating '$path $mostargs'\n";
- @ent = qx{$path $mostargs | $entcmd -b -t};
- @ent = grep(/^1,/, @ent);
- ($null, $null, $rate) = split(/,/, $ent[0]);
- $est = $rate / $entscale; # scale the estimate back
- }
- }
- print OUT "\"$cmd\" $path $est\n";
-}
-
-close(IN);
diff --git a/groupaccess.c b/groupaccess.c
index 87ce4e40..80d30191 100644
--- a/groupaccess.c
+++ b/groupaccess.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: groupaccess.c,v 1.15 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: groupaccess.c,v 1.17 2019/03/06 22:14:23 dtucker Exp $ */
/*
* Copyright (c) 2001 Kevin Steves. All rights reserved.
*
@@ -49,12 +49,8 @@ static char **groups_byname;
int
ga_init(const char *user, gid_t base)
{
-#if defined(ANDROID)
- return 0;
-#else
-
gid_t *groups_bygid;
- int i, j;
+ int i, j, retry = 0;
struct group *gr;
if (ngroups > 0)
@@ -66,16 +62,19 @@ ga_init(const char *user, gid_t base)
#endif
groups_bygid = xcalloc(ngroups, sizeof(*groups_bygid));
+ while (getgrouplist(user, base, groups_bygid, &ngroups) == -1) {
+ if (retry++ > 0)
+ fatal("getgrouplist: groups list too small");
+ groups_bygid = xreallocarray(groups_bygid, ngroups,
+ sizeof(*groups_bygid));
+ }
groups_byname = xcalloc(ngroups, sizeof(*groups_byname));
- if (getgrouplist(user, base, groups_bygid, &ngroups) == -1)
- logit("getgrouplist: groups list too small");
for (i = 0, j = 0; i < ngroups; i++)
if ((gr = getgrgid(groups_bygid[i])) != NULL)
groups_byname[j++] = xstrdup(gr->gr_name);
free(groups_bygid);
return (ngroups = j);
-#endif
}
/*
@@ -102,11 +101,10 @@ int
ga_match_pattern_list(const char *group_pattern)
{
int i, found = 0;
- size_t len = strlen(group_pattern);
for (i = 0; i < ngroups; i++) {
- switch (match_pattern_list(groups_byname[i],
- group_pattern, len, 0)) {
+ switch (match_usergroup_pattern_list(groups_byname[i],
+ group_pattern)) {
case -1:
return 0; /* Negated match wins */
case 0:
@@ -131,5 +129,6 @@ ga_free(void)
free(groups_byname[i]);
ngroups = 0;
free(groups_byname);
+ groups_byname = NULL;
}
}
diff --git a/gss-genr.c b/gss-genr.c
index 60ac65f8..d56257b4 100644
--- a/gss-genr.c
+++ b/gss-genr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gss-genr.c,v 1.23 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: gss-genr.c,v 1.26 2018/07/10 09:13:30 djm Exp $ */
/*
* Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
@@ -29,15 +29,16 @@
#ifdef GSSAPI
#include <sys/types.h>
-#include <sys/param.h>
#include <limits.h>
#include <stdarg.h>
#include <string.h>
+#include <signal.h>
#include <unistd.h>
#include "xmalloc.h"
-#include "buffer.h"
+#include "ssherr.h"
+#include "sshbuf.h"
#include "log.h"
#include "ssh2.h"
@@ -46,6 +47,21 @@
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)
+{
+ int r;
+ u_char *p;
+ size_t len;
+
+ if ((r = sshbuf_get_string(b, &p, &len)) != 0)
+ return r;
+ g->value = p;
+ g->length = len;
+ return 0;
+}
+
/* Check that the OID in a data stream matches that in the context */
int
ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
@@ -94,10 +110,12 @@ ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status,
OM_uint32 lmin;
gss_buffer_desc msg = GSS_C_EMPTY_BUFFER;
OM_uint32 ctx;
- Buffer b;
+ struct sshbuf *b;
char *ret;
+ int r;
- buffer_init(&b);
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
if (major_status != NULL)
*major_status = ctxt->major;
@@ -110,8 +128,9 @@ ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status,
gss_display_status(&lmin, ctxt->major,
GSS_C_GSS_CODE, ctxt->oid, &ctx, &msg);
- buffer_append(&b, msg.value, msg.length);
- buffer_put_char(&b, '\n');
+ 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));
gss_release_buffer(&lmin, &msg);
} while (ctx != 0);
@@ -121,16 +140,17 @@ ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status,
gss_display_status(&lmin, ctxt->minor,
GSS_C_MECH_CODE, ctxt->oid, &ctx, &msg);
- buffer_append(&b, msg.value, msg.length);
- buffer_put_char(&b, '\n');
+ 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));
gss_release_buffer(&lmin, &msg);
} while (ctx != 0);
- buffer_put_char(&b, '\0');
- ret = xmalloc(buffer_len(&b));
- buffer_get(&b, ret, buffer_len(&b));
- buffer_free(&b);
+ if ((r = sshbuf_put_u8(b, '\n')) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ ret = xstrdup((const char *)sshbuf_ptr(b));
+ sshbuf_free(b);
return (ret);
}
@@ -238,15 +258,18 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
}
void
-ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
+ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service,
const char *context)
{
- buffer_init(b);
- buffer_put_string(b, session_id2, session_id2_len);
- buffer_put_char(b, SSH2_MSG_USERAUTH_REQUEST);
- buffer_put_cstring(b, user);
- buffer_put_cstring(b, service);
- buffer_put_cstring(b, context);
+ int r;
+
+ sshbuf_reset(b);
+ if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 ||
+ (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
+ (r = sshbuf_put_cstring(b, 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));
}
int
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
index 795992d9..a151bc1e 100644
--- a/gss-serv-krb5.c
+++ b/gss-serv-krb5.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gss-serv-krb5.c,v 1.8 2013/07/20 01:55:13 djm Exp $ */
+/* $OpenBSD: gss-serv-krb5.c,v 1.9 2018/07/09 21:37:55 markus Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@@ -35,14 +35,13 @@
#include <string.h>
#include "xmalloc.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
-#include "buffer.h"
#include "ssh-gss.h"
extern ServerOptions options;
diff --git a/gss-serv.c b/gss-serv.c
index e7b8c522..b5d4bb2d 100644
--- a/gss-serv.c
+++ b/gss-serv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gss-serv.c,v 1.28 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: gss-serv.c,v 1.32 2020/03/13 03:17:07 djm Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@@ -36,17 +36,19 @@
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
-#include "buffer.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "log.h"
#include "channels.h"
#include "session.h"
#include "misc.h"
+#include "servconf.h"
#include "ssh-gss.h"
+extern ServerOptions options;
+
static ssh_gssapi_client gssapi_client =
{ GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}};
@@ -99,25 +101,32 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx)
char lname[NI_MAXHOST];
gss_OID_set oidset;
- gss_create_empty_oid_set(&status, &oidset);
- gss_add_oid_set_member(&status, ctx->oid, &oidset);
+ if (options.gss_strict_acceptor) {
+ gss_create_empty_oid_set(&status, &oidset);
+ gss_add_oid_set_member(&status, ctx->oid, &oidset);
- if (gethostname(lname, sizeof(lname))) {
- gss_release_oid_set(&status, &oidset);
- return (-1);
- }
+ if (gethostname(lname, MAXHOSTNAMELEN)) {
+ gss_release_oid_set(&status, &oidset);
+ return (-1);
+ }
+
+ if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
+ gss_release_oid_set(&status, &oidset);
+ return (ctx->major);
+ }
+
+ if ((ctx->major = gss_acquire_cred(&ctx->minor,
+ ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds,
+ NULL, NULL)))
+ ssh_gssapi_error(ctx);
- if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
gss_release_oid_set(&status, &oidset);
return (ctx->major);
+ } else {
+ ctx->name = GSS_C_NO_NAME;
+ ctx->creds = GSS_C_NO_CREDENTIAL;
}
-
- if ((ctx->major = gss_acquire_cred(&ctx->minor,
- ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL)))
- ssh_gssapi_error(ctx);
-
- gss_release_oid_set(&status, &oidset);
- return (ctx->major);
+ return GSS_S_COMPLETE;
}
/* Privileged */
@@ -328,7 +337,7 @@ ssh_gssapi_storecreds(void)
debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism");
}
-/* This allows GSSAPI methods to do things to the childs environment based
+/* This allows GSSAPI methods to do things to the child's environment based
* on the passed authentication process and credentials.
*/
/* As user */
@@ -383,4 +392,13 @@ ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
return (ctx->major);
}
+/* Privileged */
+const char *ssh_gssapi_displayname(void)
+{
+ if (gssapi_client.displayname.length == 0 ||
+ gssapi_client.displayname.value == NULL)
+ return NULL;
+ return (char *)gssapi_client.displayname.value;
+}
+
#endif
diff --git a/hash.c b/hash.c
index 734c6bee..fb81e478 100644
--- a/hash.c
+++ b/hash.c
@@ -1,76 +1,45 @@
-/* $OpenBSD: hash.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
-
-/* Copied from nacl-20110221/crypto_hash/sha512/ref/hash.c */
+/* $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 $ */
/*
-20080913
-D. J. Bernstein
-Public domain.
-*/
+ * Public domain. Author: Christian Weisgerber <naddy@openbsd.org>
+ * API compatible reimplementation of function from nacl
+ */
#include "includes.h"
#include "crypto_api.h"
-#define blocks crypto_hashblocks_sha512
-
-static const unsigned char iv[64] = {
- 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08,
- 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b,
- 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b,
- 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1,
- 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1,
- 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f,
- 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b,
- 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79
-} ;
+#include <stdarg.h>
-typedef unsigned long long uint64;
+#ifdef WITH_OPENSSL
+#include <openssl/evp.h>
-int crypto_hash_sha512(unsigned char *out,const unsigned char *in,unsigned long long inlen)
+int
+crypto_hash_sha512(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen)
{
- unsigned char h[64];
- unsigned char padded[256];
- unsigned int i;
- unsigned long long bytes = inlen;
-
- for (i = 0;i < 64;++i) h[i] = iv[i];
- blocks(h,in,inlen);
- in += inlen;
- inlen &= 127;
- in -= inlen;
+ if (!EVP_Digest(in, inlen, out, NULL, EVP_sha512(), NULL))
+ return -1;
+ return 0;
+}
- for (i = 0;i < inlen;++i) padded[i] = in[i];
- padded[inlen] = 0x80;
+#else
+# ifdef HAVE_SHA2_H
+# include <sha2.h>
+# endif
- if (inlen < 112) {
- for (i = inlen + 1;i < 119;++i) padded[i] = 0;
- padded[119] = bytes >> 61;
- padded[120] = bytes >> 53;
- padded[121] = bytes >> 45;
- padded[122] = bytes >> 37;
- padded[123] = bytes >> 29;
- padded[124] = bytes >> 21;
- padded[125] = bytes >> 13;
- padded[126] = bytes >> 5;
- padded[127] = bytes << 3;
- blocks(h,padded,128);
- } else {
- for (i = inlen + 1;i < 247;++i) padded[i] = 0;
- padded[247] = bytes >> 61;
- padded[248] = bytes >> 53;
- padded[249] = bytes >> 45;
- padded[250] = bytes >> 37;
- padded[251] = bytes >> 29;
- padded[252] = bytes >> 21;
- padded[253] = bytes >> 13;
- padded[254] = bytes >> 5;
- padded[255] = bytes << 3;
- blocks(h,padded,256);
- }
+int
+crypto_hash_sha512(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen)
+{
- for (i = 0;i < 64;++i) out[i] = h[i];
+ SHA2_CTX ctx;
- return 0;
+ SHA512Init(&ctx);
+ SHA512Update(&ctx, in, inlen);
+ SHA512Final(out, &ctx);
+ return 0;
}
+#endif /* WITH_OPENSSL */
diff --git a/hmac.c b/hmac.c
index d1c12417..7b588019 100644
--- a/hmac.c
+++ b/hmac.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hmac.c,v 1.11 2015/01/15 21:37:14 markus Exp $ */
+/* $OpenBSD: hmac.c,v 1.14 2020/02/26 13:40:09 jsg Exp $ */
/*
* Copyright (c) 2014 Markus Friedl. All rights reserved.
*
@@ -18,6 +18,8 @@
#include "includes.h"
#include <sys/types.h>
+
+#include <stdlib.h>
#include <string.h>
#include "sshbuf.h"
@@ -129,8 +131,7 @@ ssh_hmac_free(struct ssh_hmac_ctx *ctx)
explicit_bzero(ctx->buf, ctx->buf_len);
free(ctx->buf);
}
- explicit_bzero(ctx, sizeof(*ctx));
- free(ctx);
+ freezero(ctx, sizeof(*ctx));
}
}
@@ -154,7 +155,7 @@ hmac_test(void *key, size_t klen, void *m, size_t mlen, u_char *e, size_t elen)
if (memcmp(e, digest, elen)) {
for (i = 0; i < elen; i++)
- printf("[%zd] %2.2x %2.2x\n", i, e[i], digest[i]);
+ printf("[%zu] %2.2x %2.2x\n", i, e[i], digest[i]);
printf("mismatch\n");
} else
printf("ok\n");
diff --git a/hostfile.c b/hostfile.c
index b235795e..a4a35597 100644
--- a/hostfile.c
+++ b/hostfile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostfile.c,v 1.64 2015/02/16 22:08:57 djm Exp $ */
+/* $OpenBSD: hostfile.c,v 1.79 2020/03/06 18:25:12 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -49,7 +49,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdarg.h>
#include <unistd.h>
#include "xmalloc.h"
@@ -123,14 +122,13 @@ host_hash(const char *host, const char *name_from_hostfile, u_int src_len)
u_char salt[256], result[256];
char uu_salt[512], uu_result[512];
static char encoded[1024];
- u_int i, len;
+ u_int len;
len = ssh_digest_bytes(SSH_DIGEST_SHA1);
if (name_from_hostfile == NULL) {
/* Create new salt */
- for (i = 0; i < len; i++)
- salt[i] = arc4random();
+ arc4random_buf(salt, len);
} else {
/* Extract salt from known host entry */
if (extract_salt(name_from_hostfile, src_len, salt,
@@ -164,13 +162,12 @@ int
hostfile_read_key(char **cpp, u_int *bitsp, struct sshkey *ret)
{
char *cp;
- int r;
/* Skip leading whitespace. */
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
;
- if ((r = sshkey_read(ret, &cp)) != 0)
+ if (sshkey_read(ret, &cp) != 0)
return 0;
/* Skip trailing whitespace. */
@@ -242,7 +239,8 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx)
struct hostkey_entry *tmp;
if (l->status == HKF_STATUS_INVALID) {
- error("%s:%ld: parse error in hostkeys file",
+ /* XXX make this verbose() in the future */
+ debug("%s:%ld: parse error in hostkeys file",
l->path, l->linenum);
return 0;
}
@@ -251,7 +249,7 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx)
l->marker == MRK_NONE ? "" :
(l->marker == MRK_CA ? "ca " : "revoked "),
sshkey_type(l->key), l->path, l->linenum);
- if ((tmp = reallocarray(hostkeys->entries,
+ if ((tmp = recallocarray(hostkeys->entries, hostkeys->num_entries,
hostkeys->num_entries + 1, sizeof(*hostkeys->entries))) == NULL)
return SSH_ERR_ALLOC_FAIL;
hostkeys->entries = tmp;
@@ -300,8 +298,7 @@ free_hostkeys(struct hostkeys *hostkeys)
explicit_bzero(hostkeys->entries + i, sizeof(*hostkeys->entries));
}
free(hostkeys->entries);
- explicit_bzero(hostkeys, sizeof(*hostkeys));
- free(hostkeys);
+ freezero(hostkeys, sizeof(*hostkeys));
}
static int
@@ -315,7 +312,7 @@ check_key_not_revoked(struct hostkeys *hostkeys, struct sshkey *k)
continue;
if (sshkey_equal_public(k, hostkeys->entries[i].key))
return -1;
- if (is_cert &&
+ if (is_cert && k != NULL &&
sshkey_equal_public(k->cert->signature_key,
hostkeys->entries[i].key))
return -1;
@@ -346,16 +343,11 @@ check_hostkeys_by_key_or_type(struct hostkeys *hostkeys,
HostStatus end_return = HOST_NEW;
int want_cert = sshkey_is_cert(k);
HostkeyMarker want_marker = want_cert ? MRK_CA : MRK_NONE;
- int proto = (k ? k->type : keytype) == KEY_RSA1 ? 1 : 2;
if (found != NULL)
*found = NULL;
for (i = 0; i < hostkeys->num_entries; i++) {
- if (proto == 1 && hostkeys->entries[i].key->type != KEY_RSA1)
- continue;
- if (proto == 2 && hostkeys->entries[i].key->type == KEY_RSA1)
- continue;
if (hostkeys->entries[i].marker != want_marker)
continue;
if (k == NULL) {
@@ -419,19 +411,24 @@ write_host_entry(FILE *f, const char *host, const char *ip,
const struct sshkey *key, int store_hash)
{
int r, success = 0;
- char *hashed_host = NULL;
+ char *hashed_host = NULL, *lhost;
+
+ lhost = xstrdup(host);
+ lowercase(lhost);
if (store_hash) {
- if ((hashed_host = host_hash(host, NULL, 0)) == NULL) {
+ if ((hashed_host = host_hash(lhost, NULL, 0)) == NULL) {
error("%s: host_hash failed", __func__);
+ free(lhost);
return 0;
}
fprintf(f, "%s ", hashed_host);
} else if (ip != NULL)
- fprintf(f, "%s,%s ", host, ip);
- else
- fprintf(f, "%s ", host);
-
+ fprintf(f, "%s,%s ", lhost, ip);
+ else {
+ fprintf(f, "%s ", lhost);
+ }
+ free(lhost);
if ((r = sshkey_write(key, f)) == 0)
success = 1;
else
@@ -485,13 +482,6 @@ host_delete(struct hostkey_foreach_line *l, void *_ctx)
return 0;
}
- /* XXX might need a knob for this later */
- /* Don't remove RSA1 keys */
- if (l->key->type == KEY_RSA1) {
- fprintf(ctx->out, "%s\n", l->line);
- return 0;
- }
-
/*
* If this line contains one of the keys that we will be
* adding later, then don't change it and mark the key for
@@ -552,8 +542,8 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip,
/*
* Prepare temporary file for in-place deletion.
*/
- if ((r = asprintf(&temp, "%s.XXXXXXXXXXX", filename)) < 0 ||
- (r = asprintf(&back, "%s.old", filename)) < 0) {
+ if ((r = asprintf(&temp, "%s.XXXXXXXXXXX", filename)) == -1 ||
+ (r = asprintf(&back, "%s.old", filename)) == -1) {
r = SSH_ERR_ALLOC_FAIL;
goto fail;
}
@@ -575,6 +565,7 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip,
/* Remove all entries for the specified host from the file */
if ((r = hostkeys_foreach(filename, host_delete, &ctx, host, ip,
HKF_WANT_PARSE_KEY)) != 0) {
+ oerrno = errno;
error("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
goto fail;
}
@@ -662,7 +653,7 @@ match_maybe_hashed(const char *host, const char *names, int *was_hashed)
return nlen == strlen(hashed_host) &&
strncmp(hashed_host, names, nlen) == 0;
}
- return match_hostname(host, names, nlen) == 1;
+ return match_hostname(host, names) == 1;
}
int
@@ -670,14 +661,14 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
const char *host, const char *ip, u_int options)
{
FILE *f;
- char line[8192], oline[8192], ktype[128];
+ char *line = NULL, ktype[128];
u_long linenum = 0;
char *cp, *cp2;
u_int kbits;
int hashed;
int s, r = 0;
struct hostkey_foreach_line lineinfo;
- size_t l;
+ size_t linesize = 0, l;
memset(&lineinfo, 0, sizeof(lineinfo));
if (host == NULL && (options & HKF_WANT_MATCH) != 0)
@@ -686,15 +677,16 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
return SSH_ERR_SYSTEM_ERROR;
debug3("%s: reading file \"%s\"", __func__, path);
- while (read_keyfile_line(f, path, line, sizeof(line), &linenum) == 0) {
+ while (getline(&line, &linesize, f) != -1) {
+ linenum++;
line[strcspn(line, "\n")] = '\0';
- strlcpy(oline, line, sizeof(oline));
+ free(lineinfo.line);
sshkey_free(lineinfo.key);
memset(&lineinfo, 0, sizeof(lineinfo));
lineinfo.path = path;
lineinfo.linenum = linenum;
- lineinfo.line = oline;
+ lineinfo.line = xstrdup(line);
lineinfo.marker = MRK_NONE;
lineinfo.status = HKF_STATUS_OK;
lineinfo.keytype = KEY_UNSPEC;
@@ -784,20 +776,7 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
break;
}
if (!hostfile_read_key(&cp, &kbits, lineinfo.key)) {
-#ifdef WITH_SSH1
- sshkey_free(lineinfo.key);
- lineinfo.key = sshkey_new(KEY_RSA1);
- if (lineinfo.key == NULL) {
- error("%s: sshkey_new fail", __func__);
- r = SSH_ERR_ALLOC_FAIL;
- break;
- }
- if (!hostfile_read_key(&cp, &kbits,
- lineinfo.key))
- goto bad;
-#else
goto bad;
-#endif
}
lineinfo.keytype = lineinfo.key->type;
lineinfo.comment = cp;
@@ -810,15 +789,15 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
memcpy(ktype, lineinfo.rawkey, l);
ktype[l] = '\0';
lineinfo.keytype = sshkey_type_from_name(ktype);
-#ifdef WITH_SSH1
+
/*
- * Assume RSA1 if the first component is a short
+ * Assume legacy RSA1 if the first component is a short
* decimal number.
*/
if (lineinfo.keytype == KEY_UNSPEC && l < 8 &&
strspn(ktype, "0123456789") == l)
- lineinfo.keytype = KEY_RSA1;
-#endif
+ goto bad;
+
/*
* Check that something other than whitespace follows
* the key type. This won't catch all corruption, but
@@ -846,6 +825,8 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
break;
}
sshkey_free(lineinfo.key);
+ free(lineinfo.line);
+ free(line);
fclose(f);
return r;
}
diff --git a/includes.h b/includes.h
index 2893a54c..0fd71792 100644
--- a/includes.h
+++ b/includes.h
@@ -32,12 +32,6 @@
#ifdef HAVE_BSTRING_H
# include <bstring.h>
#endif
-#if defined(HAVE_GLOB_H) && defined(GLOB_HAS_ALTDIRFUNC) && \
- defined(GLOB_HAS_GL_MATCHC) && defined(GLOB_HAS_GL_STATV) && \
- defined(HAVE_DECL_GLOB_NOMATCH) && HAVE_DECL_GLOB_NOMATCH != 0 && \
- !defined(BROKEN_GLOB)
-# include <glob.h>
-#endif
#ifdef HAVE_ENDIAN_H
# include <endian.h>
#endif
@@ -99,6 +93,9 @@
#ifdef HAVE_SYS_SYSMACROS_H
# include <sys/sysmacros.h> /* For MIN, MAX, etc */
#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h> /* for timespeccmp if present */
+#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h> /* for MAP_ANONYMOUS */
#endif
diff --git a/install-sh b/install-sh
index 220abbf6..377bb868 100755
--- a/install-sh
+++ b/install-sh
@@ -1,251 +1,527 @@
#!/bin/sh
-#
# install - install a program, script, or datafile
-# This comes from X11R5 (mit/util/scripts/install.sh).
+
+scriptversion=2011-11-20.07; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# 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:
+#
+# 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
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-# Copyright 1991 by the Massachusetts Institute of Technology
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
#
-# Permission to use, copy, modify, distribute, and sell this software and its
-# documentation for any purpose is hereby granted without fee, provided that
-# the above copyright notice appear in all copies and that both that
-# copyright notice and this permission notice appear in supporting
-# documentation, and that the name of M.I.T. not be used in advertising or
-# publicity pertaining to distribution of the software without specific,
-# written prior permission. M.I.T. makes no representations about the
-# suitability of this software for any purpose. It is provided "as is"
-# without express or implied warranty.
+#
+# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
+# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
-# from scratch. It can only install one file at a time, a restriction
-# shared with many OS's install programs.
+# from scratch.
+nl='
+'
+IFS=" "" $nl"
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
-
-transformbasename=""
-transform_arg=""
-instcmd="$mvprog"
-chmodcmd="$chmodprog 0755"
-chowncmd=""
-chgrpcmd=""
-stripcmd=""
-rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=""
-dst=""
-dir_arg=""
-
-while [ x"$1" != x ]; do
- case $1 in
- -c) instcmd="$cpprog"
- shift
- continue;;
-
- -d) dir_arg=true
- shift
- continue;;
-
- -m) chmodcmd="$chmodprog $2"
- shift
- shift
- continue;;
-
- -o) chowncmd="$chownprog $2"
- shift
- shift
- continue;;
-
- -g) chgrpcmd="$chgrpprog $2"
- shift
- shift
- continue;;
-
- -s) stripcmd="$stripprog"
- shift
- continue;;
-
- -t=*) transformarg=`echo $1 | sed 's/-t=//'`
- shift
- continue;;
-
- -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
- shift
- continue;;
-
- *) if [ x"$src" = x ]
- then
- src=$1
- else
- # this colon is to work around a 386BSD /bin/sh bug
- :
- dst=$1
- fi
- shift
- continue;;
- esac
-done
-
-if [ x"$src" = x ]
-then
- echo "install: no input file specified"
- exit 1
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
else
- true
+ doit_exec=$doit
fi
-if [ x"$dir_arg" != x ]; then
- dst=$src
- src=""
-
- if [ -d $dst ]; then
- instcmd=:
- chmodcmd=""
- else
- instcmd=mkdir
- fi
-else
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
-# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad
-# if $src (and thus $dsttmp) contains '*'.
+posix_mkdir=
- if [ -f $src -o -d $src ]
- then
- true
- else
- echo "install: $src does not exist"
- exit 1
- fi
-
- if [ x"$dst" = x ]
- then
- echo "install: no destination specified"
- exit 1
- else
- true
- fi
+# Desired mode of installed file.
+mode=0755
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
- if [ -d $dst ]
- then
- dst="$dst"/`basename $src`
- else
- true
- fi
-fi
+src=
+dst=
+dir_arg=
+dst_arg=
-## this sed command emulates the dirname command
-dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+copy_on_change=false
+no_target_directory=
-# Make sure that the destination directory exists.
-# this part is taken from Noah Friedman's mkinstalldirs script
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
-# Skip lots of stat calls in the usual case.
-if [ ! -d "$dstdir" ]; then
-defaultIFS='
-'
-IFS="${IFS-${defaultIFS}}"
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
-oIFS="${IFS}"
-# Some sh's can't handle IFS=/ for some reason.
-IFS='%'
-set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
-IFS="${oIFS}"
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
-pathcomp=''
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
-while [ $# -ne 0 ] ; do
- pathcomp="${pathcomp}${1}"
- shift
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
- if [ ! -d "${pathcomp}" ] ;
- then
- $mkdirprog "${pathcomp}"
- else
- true
- fi
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
- pathcomp="${pathcomp}/"
-done
-fi
+ -C) copy_on_change=true;;
-if [ x"$dir_arg" != x ]
-then
- $doit $instcmd $dst &&
+ -d) dir_arg=true;;
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
-else
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
-# If we're going to rename the final executable, determine the name now.
+ --help) echo "$usage"; exit $?;;
- if [ x"$transformarg" = x ]
- then
- dstfile=`basename $dst`
- else
- dstfile=`basename $dst $transformbasename |
- sed $transformarg`$transformbasename
- fi
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
-# don't allow the sed command to completely eliminate the filename
+ -o) chowncmd="$chownprog $2"
+ shift;;
- if [ x"$dstfile" = x ]
- then
- dstfile=`basename $dst`
- else
- true
- fi
+ -s) stripcmd=$stripprog;;
-# Make a temp file name in the proper directory.
+ -t) dst_arg=$2
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ shift;;
- dsttmp=$dstdir/#inst.$$#
+ -T) no_target_directory=true;;
-# Move or copy the file name to the temp name
+ --version) echo "$0 $scriptversion"; exit $?;;
- $doit $instcmd $src $dsttmp &&
+ --) shift
+ break;;
- trap "rm -f ${dsttmp}" 0 &&
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
-# and set any options; do chmod last to preserve setuid bits
+ *) break;;
+ esac
+ shift
+done
-# If any of these fail, we abort the whole thing. If we want to
-# ignore errors from any of these, just make sure not to ignore
-# errors from the above "$doit $instcmd $src $dsttmp" command.
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ done
+fi
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call 'install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
-# Now rename the file to the real destination.
+if test -z "$dir_arg"; then
+ do_exit='(exit $ret); exit $ret'
+ trap "ret=129; $do_exit" 1
+ trap "ret=130; $do_exit" 2
+ trap "ret=141; $do_exit" 13
+ trap "ret=143; $do_exit" 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
- $doit $rmcmd -f $dstdir/$dstfile &&
- $doit $mvcmd $dsttmp $dstdir/$dstfile
+for src
+do
+ # Protect names problematic for 'test' and other utilities.
+ case $src in
+ -* | [=\(\)!]) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+ dst=$dst_arg
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
-fi &&
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ [-=\(\)!]*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test X"$d" = X && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
-exit 0
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/kex.c b/kex.c
index 2a00d284..09c7258e 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.105 2015/01/30 00:22:25 djm Exp $ */
+/* $OpenBSD: kex.c,v 1.158 2020/03/13 04:01:56 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@@ -25,20 +25,27 @@
#include "includes.h"
-#include <sys/param.h> /* MAX roundup */
-
+#include <sys/types.h>
+#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
#ifdef WITH_OPENSSL
#include <openssl/crypto.h>
#include <openssl/dh.h>
#endif
+#include "ssh.h"
#include "ssh2.h"
+#include "atomicio.h"
+#include "version.h"
#include "packet.h"
#include "compat.h"
#include "cipher.h"
@@ -50,23 +57,27 @@
#include "misc.h"
#include "dispatch.h"
#include "monitor.h"
-#include "roaming.h"
#include "ssherr.h"
#include "sshbuf.h"
#include "digest.h"
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L
-# if defined(HAVE_EVP_SHA256)
-# define evp_ssh_sha256 EVP_sha256
-# else
-extern const EVP_MD *evp_ssh_sha256(void);
-# endif
-#endif
-
/* prototype */
static int kex_choose_conf(struct ssh *);
-static int kex_input_newkeys(int, u_int32_t, void *);
+static int kex_input_newkeys(int, u_int32_t, struct ssh *);
+
+static const char *proposal_names[PROPOSAL_MAX] = {
+ "KEX algorithms",
+ "host key algorithms",
+ "ciphers ctos",
+ "ciphers stoc",
+ "MACs ctos",
+ "MACs stoc",
+ "compression ctos",
+ "compression stoc",
+ "languages ctos",
+ "languages stoc",
+};
struct kexalg {
char *name;
@@ -77,7 +88,10 @@ struct kexalg {
static const struct kexalg kexalgs[] = {
#ifdef WITH_OPENSSL
{ KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
- { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
+ { KEX_DH14_SHA1, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
+ { KEX_DH14_SHA256, KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },
+ { KEX_DH16_SHA512, KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },
+ { KEX_DH18_SHA512, KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512 },
{ KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 },
#ifdef HAVE_EVP_SHA256
{ KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 },
@@ -95,8 +109,11 @@ static const struct kexalg kexalgs[] = {
#endif /* WITH_OPENSSL */
#if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL)
{ KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
+ { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
+ { KEX_SNTRUP4591761X25519_SHA512, KEX_KEM_SNTRUP4591761X25519_SHA512, 0,
+ SSH_DIGEST_SHA512 },
#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
- { NULL, -1, -1, -1},
+ { NULL, 0, -1, -1},
};
char *
@@ -156,6 +173,148 @@ kex_names_valid(const char *names)
return 1;
}
+/*
+ * Concatenate algorithm names, avoiding duplicates in the process.
+ * Caller must free returned string.
+ */
+char *
+kex_names_cat(const char *a, const char *b)
+{
+ char *ret = NULL, *tmp = NULL, *cp, *p, *m;
+ size_t len;
+
+ if (a == NULL || *a == '\0')
+ return strdup(b);
+ if (b == NULL || *b == '\0')
+ return strdup(a);
+ if (strlen(b) > 1024*1024)
+ return NULL;
+ len = strlen(a) + strlen(b) + 2;
+ if ((tmp = cp = strdup(b)) == NULL ||
+ (ret = calloc(1, len)) == NULL) {
+ free(tmp);
+ return NULL;
+ }
+ strlcpy(ret, a, len);
+ for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) {
+ if ((m = match_list(ret, p, NULL)) != NULL) {
+ free(m);
+ continue; /* Algorithm already present */
+ }
+ if (strlcat(ret, ",", len) >= len ||
+ strlcat(ret, p, len) >= len) {
+ free(tmp);
+ free(ret);
+ return NULL; /* Shouldn't happen */
+ }
+ }
+ free(tmp);
+ return ret;
+}
+
+/*
+ * Assemble a list of algorithms from a default list and a string from a
+ * configuration file. The user-provided string may begin with '+' to
+ * indicate that it should be appended to the default, '-' that the
+ * specified names should be removed, or '^' that they should be placed
+ * at the head.
+ */
+int
+kex_assemble_names(char **listp, const char *def, const char *all)
+{
+ char *cp, *tmp, *patterns;
+ char *list = NULL, *ret = NULL, *matching = NULL, *opatterns = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if (listp == NULL || def == NULL || all == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+
+ if (*listp == NULL || **listp == '\0') {
+ if ((*listp = strdup(def)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ return 0;
+ }
+
+ list = *listp;
+ *listp = NULL;
+ if (*list == '+') {
+ /* Append names to default list */
+ if ((tmp = kex_names_cat(def, list + 1)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto fail;
+ }
+ free(list);
+ list = tmp;
+ } else if (*list == '-') {
+ /* Remove names from default list */
+ if ((*listp = match_filter_blacklist(def, list + 1)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto fail;
+ }
+ free(list);
+ /* filtering has already been done */
+ return 0;
+ } else if (*list == '^') {
+ /* Place names at head of default list */
+ if ((tmp = kex_names_cat(list + 1, def)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto fail;
+ }
+ free(list);
+ list = tmp;
+ } else {
+ /* Explicit list, overrides default - just use "list" as is */
+ }
+
+ /*
+ * The supplied names may be a pattern-list. For the -list case,
+ * the patterns are applied above. For the +list and explicit list
+ * cases we need to do it now.
+ */
+ ret = NULL;
+ if ((patterns = opatterns = strdup(list)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto fail;
+ }
+ /* Apply positive (i.e. non-negated) patterns from the list */
+ while ((cp = strsep(&patterns, ",")) != NULL) {
+ if (*cp == '!') {
+ /* negated matches are not supported here */
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto fail;
+ }
+ free(matching);
+ if ((matching = match_filter_whitelist(all, cp)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto fail;
+ }
+ if ((tmp = kex_names_cat(ret, matching)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto fail;
+ }
+ free(ret);
+ ret = tmp;
+ }
+ if (ret == NULL || *ret == '\0') {
+ /* An empty name-list is an error */
+ /* XXX better error code? */
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto fail;
+ }
+
+ /* success */
+ *listp = ret;
+ ret = NULL;
+ r = 0;
+
+ fail:
+ free(matching);
+ free(opatterns);
+ free(list);
+ free(ret);
+ return r;
+}
+
/* put algorithm proposal into buffer */
int
kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
@@ -200,22 +359,29 @@ kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) /* skip cookie */
+ if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) { /* skip cookie */
+ error("%s: consume cookie: %s", __func__, ssh_err(r));
goto out;
+ }
/* extract kex init proposal strings */
for (i = 0; i < PROPOSAL_MAX; i++) {
- if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0)
+ if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) {
+ error("%s: parse proposal %u: %s", __func__,
+ i, ssh_err(r));
goto out;
- debug2("kex_parse_kexinit: %s", proposal[i]);
+ }
+ debug2("%s: %s", proposal_names[i], proposal[i]);
}
/* first kex follows / reserved */
- if ((r = sshbuf_get_u8(b, &v)) != 0 ||
- (r = sshbuf_get_u32(b, &i)) != 0)
+ 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));
goto out;
+ }
if (first_kex_follows != NULL)
- *first_kex_follows = i;
- debug2("kex_parse_kexinit: first_kex_follows %d ", v);
- debug2("kex_parse_kexinit: reserved %u ", i);
+ *first_kex_follows = v;
+ debug2("first_kex_follows %d ", v);
+ debug2("reserved %u ", i);
r = 0;
*propp = proposal;
out:
@@ -230,6 +396,8 @@ kex_prop_free(char **proposal)
{
u_int i;
+ if (proposal == NULL)
+ return;
for (i = 0; i < PROPOSAL_MAX; i++)
free(proposal[i]);
free(proposal);
@@ -237,9 +405,15 @@ kex_prop_free(char **proposal)
/* ARGSUSED */
static int
-kex_protocol_error(int type, u_int32_t seq, void *ctxt)
+kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
{
- error("Hm, kex protocol error: type %d seq %u", type, seq);
+ int r;
+
+ error("kex protocol error: type %d seq %u", type, seq);
+ if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
+ (r = sshpkt_put_u32(ssh, seq)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ return r;
return 0;
}
@@ -248,7 +422,31 @@ kex_reset_dispatch(struct ssh *ssh)
{
ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
- ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
+}
+
+static int
+kex_send_ext_info(struct ssh *ssh)
+{
+ int r;
+ char *algs;
+
+ debug("Sending SSH2_MSG_EXT_INFO");
+ if ((algs = sshkey_alg_list(0, 1, 1, ',')) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ /* XXX filter algs list by allowed pubkey/hostbased types */
+ if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
+ (r = sshpkt_put_u32(ssh, 1)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
+ (r = sshpkt_put_cstring(ssh, algs)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ error("%s: compose: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ /* success */
+ r = 0;
+ out:
+ free(algs);
+ return r;
}
int
@@ -261,23 +459,67 @@ kex_send_newkeys(struct ssh *ssh)
(r = sshpkt_send(ssh)) != 0)
return r;
debug("SSH2_MSG_NEWKEYS sent");
- debug("expecting SSH2_MSG_NEWKEYS");
ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys);
+ if (ssh->kex->ext_info_c && (ssh->kex->flags & KEX_INITIAL) != 0)
+ if ((r = kex_send_ext_info(ssh)) != 0)
+ return r;
+ debug("expecting SSH2_MSG_NEWKEYS");
return 0;
}
+int
+kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
+{
+ struct kex *kex = ssh->kex;
+ u_int32_t i, ninfo;
+ char *name;
+ u_char *val;
+ size_t vlen;
+ int r;
+
+ debug("SSH2_MSG_EXT_INFO received");
+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
+ if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
+ return r;
+ for (i = 0; i < ninfo; i++) {
+ if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
+ return r;
+ if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) {
+ free(name);
+ return r;
+ }
+ if (strcmp(name, "server-sig-algs") == 0) {
+ /* Ensure no \0 lurking in value */
+ if (memchr(val, '\0', vlen) != NULL) {
+ error("%s: nul byte in %s", __func__, name);
+ return SSH_ERR_INVALID_FORMAT;
+ }
+ debug("%s: %s=<%s>", __func__, name, val);
+ kex->server_sig_algs = val;
+ val = NULL;
+ } else
+ debug("%s: %s (unrecognised)", __func__, name);
+ free(name);
+ free(val);
+ }
+ return sshpkt_get_end(ssh);
+}
+
static int
-kex_input_newkeys(int type, u_int32_t seq, void *ctxt)
+kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh)
{
- struct ssh *ssh = ctxt;
struct kex *kex = ssh->kex;
int r;
debug("SSH2_MSG_NEWKEYS received");
ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error);
+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
if ((r = sshpkt_get_end(ssh)) != 0)
return r;
+ if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0)
+ return r;
kex->done = 1;
+ kex->flags &= ~KEX_INITIAL;
sshbuf_reset(kex->peer);
/* sshbuf_reset(kex->my); */
kex->flags &= ~KEX_INIT_SENT;
@@ -293,23 +535,32 @@ kex_send_kexinit(struct ssh *ssh)
struct kex *kex = ssh->kex;
int r;
- if (kex == NULL)
+ if (kex == NULL) {
+ error("%s: no hex", __func__);
return SSH_ERR_INTERNAL_ERROR;
+ }
if (kex->flags & KEX_INIT_SENT)
return 0;
kex->done = 0;
/* generate a random cookie */
- if (sshbuf_len(kex->my) < KEX_COOKIE_LEN)
+ if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) {
+ error("%s: bad kex length: %zu < %d", __func__,
+ sshbuf_len(kex->my), KEX_COOKIE_LEN);
return SSH_ERR_INVALID_FORMAT;
- if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL)
+ }
+ if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) {
+ error("%s: buffer error", __func__);
return SSH_ERR_INTERNAL_ERROR;
+ }
arc4random_buf(cookie, KEX_COOKIE_LEN);
if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
(r = sshpkt_putb(ssh, kex->my)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
+ (r = sshpkt_send(ssh)) != 0) {
+ error("%s: compose reply: %s", __func__, ssh_err(r));
return r;
+ }
debug("SSH2_MSG_KEXINIT sent");
kex->flags |= KEX_INIT_SENT;
return 0;
@@ -317,9 +568,8 @@ kex_send_kexinit(struct ssh *ssh)
/* ARGSUSED */
int
-kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
+kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
{
- struct ssh *ssh = ctxt;
struct kex *kex = ssh->kex;
const u_char *ptr;
u_int i;
@@ -327,20 +577,28 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
int r;
debug("SSH2_MSG_KEXINIT received");
- if (kex == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
-
+ if (kex == NULL) {
+ error("%s: no hex", __func__);
+ return SSH_ERR_INTERNAL_ERROR;
+ }
+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
ptr = sshpkt_ptr(ssh, &dlen);
if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
return r;
/* discard packet */
- for (i = 0; i < KEX_COOKIE_LEN; i++)
- if ((r = sshpkt_get_u8(ssh, NULL)) != 0)
+ 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));
return r;
- for (i = 0; i < PROPOSAL_MAX; i++)
- if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0)
+ }
+ }
+ 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));
return r;
+ }
+ }
/*
* XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
* KEX method has the server move first, but a server might be using
@@ -365,33 +623,24 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
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);
return SSH_ERR_INTERNAL_ERROR;
}
-int
-kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp)
+struct kex *
+kex_new(void)
{
struct kex *kex;
- int r;
- *kexp = NULL;
- if ((kex = calloc(1, sizeof(*kex))) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((kex->peer = sshbuf_new()) == NULL ||
- (kex->my = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = kex_prop2buf(kex->my, proposal)) != 0)
- goto out;
- kex->done = 0;
- kex_reset_dispatch(ssh);
- r = 0;
- *kexp = kex;
- out:
- if (r != 0)
+ if ((kex = calloc(1, sizeof(*kex))) == NULL ||
+ (kex->peer = sshbuf_new()) == NULL ||
+ (kex->my = sshbuf_new()) == NULL ||
+ (kex->client_version = sshbuf_new()) == NULL ||
+ (kex->server_version = sshbuf_new()) == NULL) {
kex_free(kex);
- return r;
+ return NULL;
+ }
+ return kex;
}
void
@@ -405,7 +654,7 @@ kex_free_newkeys(struct newkeys *newkeys)
newkeys->enc.key = NULL;
}
if (newkeys->enc.iv) {
- explicit_bzero(newkeys->enc.iv, newkeys->enc.block_size);
+ explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len);
free(newkeys->enc.iv);
newkeys->enc.iv = NULL;
}
@@ -421,8 +670,7 @@ kex_free_newkeys(struct newkeys *newkeys)
}
free(newkeys->mac.name);
explicit_bzero(&newkeys->mac, sizeof(newkeys->mac));
- explicit_bzero(newkeys, sizeof(*newkeys));
- free(newkeys);
+ freezero(newkeys, sizeof(*newkeys));
}
void
@@ -430,12 +678,13 @@ kex_free(struct kex *kex)
{
u_int mode;
+ if (kex == NULL)
+ return;
+
#ifdef WITH_OPENSSL
- if (kex->dh)
- DH_free(kex->dh);
+ DH_free(kex->dh);
#ifdef OPENSSL_HAS_ECC
- if (kex->ec_client_key)
- EC_KEY_free(kex->ec_client_key);
+ EC_KEY_free(kex->ec_client_key);
#endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
for (mode = 0; mode < MODE_MAX; mode++) {
@@ -444,18 +693,35 @@ kex_free(struct kex *kex)
}
sshbuf_free(kex->peer);
sshbuf_free(kex->my);
+ sshbuf_free(kex->client_version);
+ sshbuf_free(kex->server_version);
+ sshbuf_free(kex->client_pub);
free(kex->session_id);
- free(kex->client_version_string);
- free(kex->server_version_string);
+ free(kex->failed_choice);
+ free(kex->hostkey_alg);
+ free(kex->name);
free(kex);
}
int
+kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
+{
+ int r;
+
+ if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0)
+ return r;
+ ssh->kex->flags = KEX_INITIAL;
+ kex_reset_dispatch(ssh);
+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
+ return 0;
+}
+
+int
kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
{
int r;
- if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0)
+ if ((r = kex_ready(ssh, proposal)) != 0)
return r;
if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */
kex_free(ssh->kex);
@@ -465,6 +731,25 @@ kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
return 0;
}
+/*
+ * Request key re-exchange, returns 0 on success or a ssherr.h error
+ * code otherwise. Must not be called if KEX is incomplete or in-progress.
+ */
+int
+kex_start_rekex(struct ssh *ssh)
+{
+ if (ssh->kex == NULL) {
+ error("%s: no kex", __func__);
+ return SSH_ERR_INTERNAL_ERROR;
+ }
+ if (ssh->kex->done == 0) {
+ error("%s: requested twice", __func__);
+ return SSH_ERR_INTERNAL_ERROR;
+ }
+ ssh->kex->done = 0;
+ return kex_send_kexinit(ssh);
+}
+
static int
choose_enc(struct sshenc *enc, char *client, char *server)
{
@@ -472,8 +757,11 @@ 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)
+ if ((enc->cipher = cipher_by_name(name)) == NULL) {
+ error("%s: unsupported cipher %s", __func__, name);
+ free(name);
return SSH_ERR_INTERNAL_ERROR;
+ }
enc->name = name;
enc->enabled = 0;
enc->iv = NULL;
@@ -491,11 +779,11 @@ 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)
+ if (mac_setup(mac, name) < 0) {
+ error("%s: unsupported MAC %s", __func__, name);
+ free(name);
return SSH_ERR_INTERNAL_ERROR;
- /* truncate the key */
- if (ssh->compat & SSH_BUG_HMAC)
- mac->key_len = 16;
+ }
mac->name = name;
mac->key = NULL;
mac->enabled = 0;
@@ -509,13 +797,18 @@ choose_comp(struct sshcomp *comp, char *client, char *server)
if (name == NULL)
return SSH_ERR_NO_COMPRESS_ALG_MATCH;
+#ifdef WITH_ZLIB
if (strcmp(name, "zlib@openssh.com") == 0) {
comp->type = COMP_DELAYED;
} else if (strcmp(name, "zlib") == 0) {
comp->type = COMP_ZLIB;
- } else if (strcmp(name, "none") == 0) {
+ } else
+#endif /* WITH_ZLIB */
+ if (strcmp(name, "none") == 0) {
comp->type = COMP_NONE;
} else {
+ error("%s: unsupported compression scheme %s", __func__, name);
+ free(name);
return SSH_ERR_INTERNAL_ERROR;
}
comp->name = name;
@@ -529,10 +822,13 @@ choose_kex(struct kex *k, char *client, char *server)
k->name = match_list(client, server, NULL);
+ debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
if (k->name == NULL)
return SSH_ERR_NO_KEX_ALG_MATCH;
- if ((kexalg = kex_alg_by_name(k->name)) == NULL)
+ if ((kexalg = kex_alg_by_name(k->name)) == NULL) {
+ error("%s: unsupported KEX method %s", __func__, k->name);
return SSH_ERR_INTERNAL_ERROR;
+ }
k->kex_type = kexalg->type;
k->hash_alg = kexalg->hash_alg;
k->ec_nid = kexalg->ec_nid;
@@ -542,15 +838,19 @@ choose_kex(struct kex *k, char *client, char *server)
static int
choose_hostkeyalg(struct kex *k, char *client, char *server)
{
- char *hostkeyalg = match_list(client, server, NULL);
+ k->hostkey_alg = match_list(client, server, NULL);
- if (hostkeyalg == NULL)
+ debug("kex: host key algorithm: %s",
+ k->hostkey_alg ? k->hostkey_alg : "(no match)");
+ if (k->hostkey_alg == NULL)
return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
- k->hostkey_type = sshkey_type_from_name(hostkeyalg);
- if (k->hostkey_type == KEY_UNSPEC)
+ 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);
return SSH_ERR_INTERNAL_ERROR;
- k->hostkey_nid = sshkey_ecdsa_nid_from_name(hostkeyalg);
- free(hostkeyalg);
+ }
+ k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
return 0;
}
@@ -589,8 +889,11 @@ kex_choose_conf(struct ssh *ssh)
u_int mode, ctos, need, dh_need, authlen;
int r, first_kex_follows;
- if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0 ||
- (r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
+ debug2("local %s KEXINIT proposal", kex->server ? "server" : "client");
+ if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0)
+ goto out;
+ debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server");
+ if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
goto out;
if (kex->server) {
@@ -601,18 +904,28 @@ kex_choose_conf(struct ssh *ssh)
sprop=peer;
}
- /* Check whether server offers roaming */
- if (!kex->server) {
- char *roaming = match_list(KEX_RESUME,
- peer[PROPOSAL_KEX_ALGS], NULL);
+ /* Check whether client supports ext_info_c */
+ if (kex->server && (kex->flags & KEX_INITIAL)) {
+ char *ext;
- if (roaming) {
- kex->roaming = 1;
- free(roaming);
- }
+ ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL);
+ kex->ext_info_c = (ext != NULL);
+ free(ext);
}
/* Algorithm Negotiation */
+ if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
+ sprop[PROPOSAL_KEX_ALGS])) != 0) {
+ kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
+ peer[PROPOSAL_KEX_ALGS] = NULL;
+ goto out;
+ }
+ if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
+ sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
+ kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
+ peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
+ goto out;
+ }
for (mode = 0; mode < MODE_MAX; mode++) {
if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
@@ -625,47 +938,50 @@ kex_choose_conf(struct ssh *ssh)
nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
if ((r = choose_enc(&newkeys->enc, cprop[nenc],
- sprop[nenc])) != 0)
+ sprop[nenc])) != 0) {
+ kex->failed_choice = peer[nenc];
+ peer[nenc] = NULL;
goto out;
+ }
authlen = cipher_authlen(newkeys->enc.cipher);
/* ignore mac for authenticated encryption */
if (authlen == 0 &&
(r = choose_mac(ssh, &newkeys->mac, cprop[nmac],
- sprop[nmac])) != 0)
+ sprop[nmac])) != 0) {
+ kex->failed_choice = peer[nmac];
+ peer[nmac] = NULL;
goto out;
+ }
if ((r = choose_comp(&newkeys->comp, cprop[ncomp],
- sprop[ncomp])) != 0)
+ sprop[ncomp])) != 0) {
+ kex->failed_choice = peer[ncomp];
+ peer[ncomp] = NULL;
goto out;
- debug("kex: %s %s %s %s",
+ }
+ debug("kex: %s cipher: %s MAC: %s compression: %s",
ctos ? "client->server" : "server->client",
newkeys->enc.name,
authlen == 0 ? newkeys->mac.name : "<implicit>",
newkeys->comp.name);
}
- if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
- sprop[PROPOSAL_KEX_ALGS])) != 0 ||
- (r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
- sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0)
- goto out;
need = dh_need = 0;
for (mode = 0; mode < MODE_MAX; mode++) {
newkeys = kex->newkeys[mode];
- need = MAX(need, newkeys->enc.key_len);
- need = MAX(need, newkeys->enc.block_size);
- need = MAX(need, newkeys->enc.iv_len);
- need = MAX(need, newkeys->mac.key_len);
- dh_need = MAX(dh_need, cipher_seclen(newkeys->enc.cipher));
- dh_need = MAX(dh_need, newkeys->enc.block_size);
- dh_need = MAX(dh_need, newkeys->enc.iv_len);
- dh_need = MAX(dh_need, newkeys->mac.key_len);
+ need = MAXIMUM(need, newkeys->enc.key_len);
+ need = MAXIMUM(need, newkeys->enc.block_size);
+ need = MAXIMUM(need, newkeys->enc.iv_len);
+ need = MAXIMUM(need, newkeys->mac.key_len);
+ dh_need = MAXIMUM(dh_need, cipher_seclen(newkeys->enc.cipher));
+ dh_need = MAXIMUM(dh_need, newkeys->enc.block_size);
+ dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len);
+ dh_need = MAXIMUM(dh_need, newkeys->mac.key_len);
}
/* XXX need runden? */
kex->we_need = need;
kex->dh_need = dh_need;
/* ignore the next message if the proposals do not match */
- if (first_kex_follows && !proposals_match(my, peer) &&
- !(ssh->compat & SSH_BUG_FIRSTKEX))
+ if (first_kex_follows && !proposals_match(my, peer))
ssh->dispatch_skip_packets = 1;
r = 0;
out:
@@ -688,7 +1004,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
return SSH_ERR_INVALID_ARGUMENT;
- if ((digest = calloc(1, roundup(need, mdsz))) == NULL) {
+ if ((digest = calloc(1, ROUNDUP(need, mdsz))) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
@@ -702,6 +1018,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
kex->session_id_len) != 0 ||
ssh_digest_final(hashctx, digest, mdsz) != 0) {
r = SSH_ERR_LIBCRYPTO_ERROR;
+ error("%s: KEX hash failed", __func__);
goto out;
}
ssh_digest_free(hashctx);
@@ -718,6 +1035,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__);
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
@@ -732,8 +1050,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
digest = NULL;
r = 0;
out:
- if (digest)
- free(digest);
+ free(digest);
ssh_digest_free(hashctx);
return r;
}
@@ -748,6 +1065,14 @@ kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
u_int i, j, mode, ctos;
int r;
+ /* save initial hash as session id */
+ if (kex->session_id == NULL) {
+ kex->session_id_len = hashlen;
+ kex->session_id = malloc(kex->session_id_len);
+ if (kex->session_id == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ memcpy(kex->session_id, hash, kex->session_id_len);
+ }
for (i = 0; i < NKEYS; i++) {
if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
shared_secret, &keys[i])) != 0) {
@@ -766,70 +1091,288 @@ kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
return 0;
}
-#ifdef WITH_OPENSSL
int
-kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen,
- const BIGNUM *secret)
+kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp)
{
- struct sshbuf *shared_secret;
- int r;
+ struct kex *kex = ssh->kex;
- if ((shared_secret = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_put_bignum2(shared_secret, secret)) == 0)
- r = kex_derive_keys(ssh, hash, hashlen, shared_secret);
- sshbuf_free(shared_secret);
- return r;
+ *pubp = NULL;
+ *prvp = NULL;
+ if (kex->load_host_public_key == NULL ||
+ kex->load_host_private_key == NULL) {
+ error("%s: missing hostkey loader", __func__);
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+ *pubp = kex->load_host_public_key(kex->hostkey_type,
+ kex->hostkey_nid, ssh);
+ *prvp = kex->load_host_private_key(kex->hostkey_type,
+ kex->hostkey_nid, ssh);
+ if (*pubp == NULL)
+ return SSH_ERR_NO_HOSTKEY_LOADED;
+ return 0;
+}
+
+int
+kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key)
+{
+ struct kex *kex = ssh->kex;
+
+ if (kex->verify_host_key == NULL) {
+ error("%s: missing hostkey verifier", __func__);
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+ if (server_host_key->type != kex->hostkey_type ||
+ (kex->hostkey_type == KEY_ECDSA &&
+ server_host_key->ecdsa_nid != kex->hostkey_nid))
+ return SSH_ERR_KEY_TYPE_MISMATCH;
+ if (kex->verify_host_key(server_host_key, ssh) == -1)
+ return SSH_ERR_SIGNATURE_INVALID;
+ return 0;
+}
+
+#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
+void
+dump_digest(const char *msg, const u_char *digest, int len)
+{
+ fprintf(stderr, "%s\n", msg);
+ sshbuf_dump_data(digest, len, stderr);
}
#endif
-#ifdef WITH_SSH1
+/*
+ * Send a plaintext error message to the peer, suffixed by \r\n.
+ * Only used during banner exchange, and there only for the server.
+ */
+static void
+send_error(struct ssh *ssh, char *msg)
+{
+ char *crnl = "\r\n";
+
+ if (!ssh->kex->server)
+ return;
+
+ if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
+ msg, strlen(msg)) != strlen(msg) ||
+ atomicio(vwrite, ssh_packet_get_connection_out(ssh),
+ crnl, strlen(crnl)) != strlen(crnl))
+ error("%s: write: %.100s", __func__, strerror(errno));
+}
+
+/*
+ * Sends our identification string and waits for the peer's. Will block for
+ * up to timeout_ms (or indefinitely if timeout_ms <= 0).
+ * Returns on 0 success or a ssherr.h code on failure.
+ */
int
-derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus,
- u_int8_t cookie[8], u_int8_t id[16])
+kex_exchange_identification(struct ssh *ssh, int timeout_ms,
+ const char *version_addendum)
{
- u_int8_t hbuf[2048], sbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH];
- struct ssh_digest_ctx *hashctx = NULL;
- size_t hlen, slen;
- int r;
+ int remote_major, remote_minor, mismatch, oerrno = 0;
+ size_t len, i, n;
+ int r, expect_nl;
+ u_char c;
+ struct sshbuf *our_version = ssh->kex->server ?
+ ssh->kex->server_version : ssh->kex->client_version;
+ struct sshbuf *peer_version = ssh->kex->server ?
+ ssh->kex->client_version : ssh->kex->server_version;
+ char *our_version_string = NULL, *peer_version_string = NULL;
+ char *cp, *remote_version = NULL;
+
+ /* Prepare and send our banner */
+ sshbuf_reset(our_version);
+ if (version_addendum != NULL && *version_addendum == '\0')
+ version_addendum = NULL;
+ if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n",
+ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
+ version_addendum == NULL ? "" : " ",
+ version_addendum == NULL ? "" : version_addendum)) != 0) {
+ oerrno = errno;
+ error("%s: sshbuf_putf: %s", __func__, ssh_err(r));
+ goto out;
+ }
- hlen = BN_num_bytes(host_modulus);
- slen = BN_num_bytes(server_modulus);
- if (hlen < (512 / 8) || (u_int)hlen > sizeof(hbuf) ||
- slen < (512 / 8) || (u_int)slen > sizeof(sbuf))
- return SSH_ERR_KEY_BITS_MISMATCH;
- if (BN_bn2bin(host_modulus, hbuf) <= 0 ||
- BN_bn2bin(server_modulus, sbuf) <= 0) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
+ if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
+ sshbuf_mutable_ptr(our_version),
+ sshbuf_len(our_version)) != sshbuf_len(our_version)) {
+ oerrno = errno;
+ debug("%s: write: %.100s", __func__, strerror(errno));
+ r = SSH_ERR_SYSTEM_ERROR;
+ goto out;
+ }
+ if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */
+ oerrno = errno;
+ error("%s: sshbuf_consume_end: %s", __func__, ssh_err(r));
goto out;
}
- if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL) {
+ our_version_string = sshbuf_dup_string(our_version);
+ if (our_version_string == NULL) {
+ error("%s: sshbuf_dup_string failed", __func__);
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if (ssh_digest_update(hashctx, hbuf, hlen) != 0 ||
- ssh_digest_update(hashctx, sbuf, slen) != 0 ||
- ssh_digest_update(hashctx, cookie, 8) != 0 ||
- ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
+ debug("Local version string %.100s", our_version_string);
+
+ /* Read other side's version identification. */
+ for (n = 0; ; n++) {
+ if (n >= SSH_MAX_PRE_BANNER_LINES) {
+ send_error(ssh, "No SSH identification string "
+ "received.");
+ error("%s: No SSH version received in first %u lines "
+ "from server", __func__, SSH_MAX_PRE_BANNER_LINES);
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ sshbuf_reset(peer_version);
+ expect_nl = 0;
+ for (i = 0; ; i++) {
+ if (timeout_ms > 0) {
+ r = waitrfd(ssh_packet_get_connection_in(ssh),
+ &timeout_ms);
+ if (r == -1 && errno == ETIMEDOUT) {
+ send_error(ssh, "Timed out waiting "
+ "for SSH identification string.");
+ error("Connection timed out during "
+ "banner exchange");
+ r = SSH_ERR_CONN_TIMEOUT;
+ goto out;
+ } else if (r == -1) {
+ oerrno = errno;
+ error("%s: %s",
+ __func__, strerror(errno));
+ r = SSH_ERR_SYSTEM_ERROR;
+ goto out;
+ }
+ }
+
+ len = atomicio(read, ssh_packet_get_connection_in(ssh),
+ &c, 1);
+ if (len != 1 && errno == EPIPE) {
+ error("%s: Connection closed by remote host",
+ __func__);
+ r = SSH_ERR_CONN_CLOSED;
+ goto out;
+ } else if (len != 1) {
+ oerrno = errno;
+ error("%s: read: %.100s",
+ __func__, strerror(errno));
+ r = SSH_ERR_SYSTEM_ERROR;
+ goto out;
+ }
+ if (c == '\r') {
+ expect_nl = 1;
+ continue;
+ }
+ if (c == '\n')
+ break;
+ if (c == '\0' || expect_nl) {
+ error("%s: banner line contains invalid "
+ "characters", __func__);
+ goto invalid;
+ }
+ if ((r = sshbuf_put_u8(peer_version, c)) != 0) {
+ oerrno = errno;
+ error("%s: sshbuf_put: %s",
+ __func__, ssh_err(r));
+ goto out;
+ }
+ if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) {
+ error("%s: banner line too long", __func__);
+ goto invalid;
+ }
+ }
+ /* Is this an actual protocol banner? */
+ if (sshbuf_len(peer_version) > 4 &&
+ memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0)
+ break;
+ /* If not, then just log the line and continue */
+ if ((cp = sshbuf_dup_string(peer_version)) == NULL) {
+ error("%s: sshbuf_dup_string failed", __func__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ /* Do not accept lines before the SSH ident from a client */
+ if (ssh->kex->server) {
+ error("%s: client sent invalid protocol identifier "
+ "\"%.256s\"", __func__, cp);
+ free(cp);
+ goto invalid;
+ }
+ debug("%s: banner line %zu: %s", __func__, n, cp);
+ free(cp);
+ }
+ peer_version_string = sshbuf_dup_string(peer_version);
+ if (peer_version_string == NULL)
+ error("%s: sshbuf_dup_string failed", __func__);
+ /* XXX must be same size for sscanf */
+ if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) {
+ error("%s: calloc failed", __func__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ /*
+ * Check that the versions match. In future this might accept
+ * several versions and set appropriate flags to handle them.
+ */
+ if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n",
+ &remote_major, &remote_minor, remote_version) != 3) {
+ error("Bad remote protocol version identification: '%.100s'",
+ peer_version_string);
+ invalid:
+ send_error(ssh, "Invalid SSH identification string.");
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ debug("Remote protocol version %d.%d, remote software version %.100s",
+ remote_major, remote_minor, remote_version);
+ ssh->compat = compat_datafellows(remote_version);
+
+ mismatch = 0;
+ switch (remote_major) {
+ case 2:
+ break;
+ case 1:
+ if (remote_minor != 99)
+ mismatch = 1;
+ break;
+ default:
+ mismatch = 1;
+ break;
+ }
+ if (mismatch) {
+ error("Protocol major versions differ: %d vs. %d",
+ PROTOCOL_MAJOR_2, remote_major);
+ send_error(ssh, "Protocol major versions differ.");
+ r = SSH_ERR_NO_PROTOCOL_VERSION;
goto out;
}
- memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5));
+
+ if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) {
+ logit("probed from %s port %d with %s. Don't panic.",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+ peer_version_string);
+ r = SSH_ERR_CONN_CLOSED; /* XXX */
+ goto out;
+ }
+ if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) {
+ logit("scanned from %s port %d with %s. Don't panic.",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+ peer_version_string);
+ r = SSH_ERR_CONN_CLOSED; /* XXX */
+ goto out;
+ }
+ if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
+ logit("Remote version \"%.100s\" uses unsafe RSA signature "
+ "scheme; disabling use of RSA keys", remote_version);
+ }
+ /* success */
r = 0;
out:
- ssh_digest_free(hashctx);
- explicit_bzero(hbuf, sizeof(hbuf));
- explicit_bzero(sbuf, sizeof(sbuf));
- explicit_bzero(obuf, sizeof(obuf));
+ free(our_version_string);
+ free(peer_version_string);
+ free(remote_version);
+ if (r == SSH_ERR_SYSTEM_ERROR)
+ errno = oerrno;
return r;
}
-#endif
-#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
-void
-dump_digest(char *msg, u_char *digest, int len)
-{
- fprintf(stderr, "%s\n", msg);
- sshbuf_dump_data(digest, len, stderr);
-}
-#endif
diff --git a/kex.h b/kex.h
index f70b81fc..a5ae6ac0 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.71 2015/02/16 22:13:32 djm Exp $ */
+/* $OpenBSD: kex.h,v 1.109 2019/09/06 05:23:55 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -27,14 +27,12 @@
#define KEX_H
#include "mac.h"
-#include "buffer.h" /* XXX for typedef */
-#include "key.h" /* XXX for typedef */
-
-#ifdef WITH_LEAKMALLOC
-#include "leakmalloc.h"
-#endif
+#include "crypto_api.h"
#ifdef WITH_OPENSSL
+# include <openssl/bn.h>
+# include <openssl/dh.h>
+# include <openssl/ecdsa.h>
# ifdef OPENSSL_HAS_ECC
# include <openssl/ec.h>
# else /* OPENSSL_HAS_ECC */
@@ -43,6 +41,8 @@
# define EC_POINT void
# endif /* OPENSSL_HAS_ECC */
#else /* WITH_OPENSSL */
+# define DH void
+# define BIGNUM void
# define EC_KEY void
# define EC_GROUP void
# define EC_POINT void
@@ -50,17 +50,22 @@
#define KEX_COOKIE_LEN 16
-#define KEX_DH1 "diffie-hellman-group1-sha1"
-#define KEX_DH14 "diffie-hellman-group14-sha1"
-#define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1"
-#define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256"
-#define KEX_RESUME "resume@appgate.com"
-#define KEX_ECDH_SHA2_NISTP256 "ecdh-sha2-nistp256"
-#define KEX_ECDH_SHA2_NISTP384 "ecdh-sha2-nistp384"
-#define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521"
-#define KEX_CURVE25519_SHA256 "curve25519-sha256@libssh.org"
+#define KEX_DH1 "diffie-hellman-group1-sha1"
+#define KEX_DH14_SHA1 "diffie-hellman-group14-sha1"
+#define KEX_DH14_SHA256 "diffie-hellman-group14-sha256"
+#define KEX_DH16_SHA512 "diffie-hellman-group16-sha512"
+#define KEX_DH18_SHA512 "diffie-hellman-group18-sha512"
+#define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1"
+#define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256"
+#define KEX_ECDH_SHA2_NISTP256 "ecdh-sha2-nistp256"
+#define KEX_ECDH_SHA2_NISTP384 "ecdh-sha2-nistp384"
+#define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521"
+#define KEX_CURVE25519_SHA256 "curve25519-sha256"
+#define KEX_CURVE25519_SHA256_OLD "curve25519-sha256@libssh.org"
+#define KEX_SNTRUP4591761X25519_SHA512 "sntrup4591761x25519-sha512@tinyssh.org"
#define COMP_NONE 0
+/* pre-auth compression (COMP_ZLIB) is only supported in the client */
#define COMP_ZLIB 1
#define COMP_DELAYED 2
@@ -89,14 +94,19 @@ enum kex_modes {
enum kex_exchange {
KEX_DH_GRP1_SHA1,
KEX_DH_GRP14_SHA1,
+ KEX_DH_GRP14_SHA256,
+ KEX_DH_GRP16_SHA512,
+ KEX_DH_GRP18_SHA512,
KEX_DH_GEX_SHA1,
KEX_DH_GEX_SHA256,
KEX_ECDH_SHA2,
KEX_C25519_SHA256,
+ KEX_KEM_SNTRUP4591761X25519_SHA512,
KEX_MAX
};
#define KEX_INIT_SENT 0x0001
+#define KEX_INITIAL 0x0002
struct sshenc {
char *name;
@@ -129,38 +139,48 @@ struct kex {
u_int dh_need;
int server;
char *name;
+ char *hostkey_alg;
int hostkey_type;
int hostkey_nid;
u_int kex_type;
- int roaming;
+ char *server_sig_algs;
+ int ext_info_c;
struct sshbuf *my;
struct sshbuf *peer;
+ struct sshbuf *client_version;
+ struct sshbuf *server_version;
sig_atomic_t done;
u_int flags;
int hash_alg;
int ec_nid;
- char *client_version_string;
- char *server_version_string;
+ char *failed_choice;
int (*verify_host_key)(struct sshkey *, struct ssh *);
struct sshkey *(*load_host_public_key)(int, int, struct ssh *);
struct sshkey *(*load_host_private_key)(int, int, struct ssh *);
int (*host_key_index)(struct sshkey *, int, struct ssh *);
- int (*sign)(struct sshkey *, struct sshkey *,
- u_char **, size_t *, const u_char *, size_t, u_int);
+ int (*sign)(struct ssh *, struct sshkey *, struct sshkey *,
+ u_char **, size_t *, const u_char *, size_t, const char *);
int (*kex[KEX_MAX])(struct ssh *);
/* kex specific state */
DH *dh; /* DH */
u_int min, max, nbits; /* GEX */
EC_KEY *ec_client_key; /* ECDH */
const EC_GROUP *ec_group; /* ECDH */
- u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 */
+ u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 + KEM */
u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */
+ u_char sntrup4591761_client_key[crypto_kem_sntrup4591761_SECRETKEYBYTES]; /* KEM */
+ struct sshbuf *client_pub;
};
int kex_names_valid(const char *);
char *kex_alg_list(char);
+char *kex_names_cat(const char *, const char *);
+int kex_assemble_names(char **, const char *, const char *);
+
+int kex_exchange_identification(struct ssh *, int, const char *);
-int kex_new(struct ssh *, char *[PROPOSAL_MAX], struct kex **);
+struct kex *kex_new(void);
+int kex_ready(struct ssh *, char *[PROPOSAL_MAX]);
int kex_setup(struct ssh *, char *[PROPOSAL_MAX]);
void kex_free_newkeys(struct newkeys *);
void kex_free(struct kex *);
@@ -168,41 +188,52 @@ void kex_free(struct kex *);
int kex_buf2prop(struct sshbuf *, int *, char ***);
int kex_prop2buf(struct sshbuf *, char *proposal[PROPOSAL_MAX]);
void kex_prop_free(char **);
+int kex_load_hostkey(struct ssh *, struct sshkey **, struct sshkey **);
+int kex_verify_host_key(struct ssh *, struct sshkey *);
int kex_send_kexinit(struct ssh *);
-int kex_input_kexinit(int, u_int32_t, void *);
+int kex_input_kexinit(int, u_int32_t, struct ssh *);
+int kex_input_ext_info(int, u_int32_t, struct ssh *);
int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *);
-int kex_derive_keys_bn(struct ssh *, u_char *, u_int, const BIGNUM *);
int kex_send_newkeys(struct ssh *);
+int kex_start_rekex(struct ssh *);
-int kexdh_client(struct ssh *);
-int kexdh_server(struct ssh *);
int kexgex_client(struct ssh *);
int kexgex_server(struct ssh *);
-int kexecdh_client(struct ssh *);
-int kexecdh_server(struct ssh *);
-int kexc25519_client(struct ssh *);
-int kexc25519_server(struct ssh *);
+int kex_gen_client(struct ssh *);
+int kex_gen_server(struct ssh *);
+
+int kex_dh_keypair(struct kex *);
+int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **,
+ struct sshbuf **);
+int kex_dh_dec(struct kex *, const struct sshbuf *, struct sshbuf **);
+
+int kex_ecdh_keypair(struct kex *);
+int kex_ecdh_enc(struct kex *, const struct sshbuf *, struct sshbuf **,
+ struct sshbuf **);
+int kex_ecdh_dec(struct kex *, const struct sshbuf *, struct sshbuf **);
+
+int kex_c25519_keypair(struct kex *);
+int kex_c25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **,
+ struct sshbuf **);
+int kex_c25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **);
-int kex_dh_hash(const char *, const char *,
- const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
- const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);
+int kex_kem_sntrup4591761x25519_keypair(struct kex *);
+int kex_kem_sntrup4591761x25519_enc(struct kex *, const struct sshbuf *,
+ struct sshbuf **, struct sshbuf **);
+int kex_kem_sntrup4591761x25519_dec(struct kex *, const struct sshbuf *,
+ struct sshbuf **);
-int kexgex_hash(int, const char *, const char *,
- const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
+int kex_dh_keygen(struct kex *);
+int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *);
+
+int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *,
+ const struct sshbuf *, const struct sshbuf *, const struct sshbuf *,
int, int, int,
const BIGNUM *, const BIGNUM *, const BIGNUM *,
- const BIGNUM *, const BIGNUM *,
+ const BIGNUM *, const u_char *, size_t,
u_char *, size_t *);
-int kex_ecdh_hash(int, const EC_GROUP *, const char *, const char *,
- const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
- const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char *, size_t *);
-
-int kex_c25519_hash(int, const char *, const char *, const char *, size_t,
- const char *, size_t, const u_char *, size_t, const u_char *, const u_char *,
- const u_char *, size_t, u_char *, size_t *);
-
void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE])
__attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
__attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
@@ -210,12 +241,13 @@ int kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
const u_char pub[CURVE25519_SIZE], struct sshbuf *out)
__attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
__attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
-
-int
-derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]);
+int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE],
+ const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int)
+ __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
+ __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
-void dump_digest(char *, u_char *, int);
+void dump_digest(const char *, const u_char *, int);
#endif
#if !defined(WITH_OPENSSL) || !defined(OPENSSL_HAS_ECC)
diff --git a/kexc25519.c b/kexc25519.c
index b6e6c401..f13d766d 100644
--- a/kexc25519.c
+++ b/kexc25519.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: kexc25519.c,v 1.8 2015/01/19 20:16:15 markus Exp $ */
+/* $OpenBSD: kexc25519.c,v 1.17 2019/01/21 10:40:11 djm Exp $ */
/*
- * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved.
+ * Copyright (c) 2019 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
* Copyright (c) 2013 Aris Adamantiadis. All rights reserved.
*
@@ -29,20 +29,16 @@
#include <sys/types.h>
-#include <signal.h>
+#include <stdio.h>
#include <string.h>
+#include <signal.h>
-#include <openssl/bn.h>
-#include <openssl/evp.h>
-
-#include "sshbuf.h"
-#include "ssh2.h"
#include "sshkey.h"
-#include "cipher.h"
#include "kex.h"
-#include "log.h"
+#include "sshbuf.h"
#include "digest.h"
#include "ssherr.h"
+#include "ssh2.h"
extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE],
const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE])
@@ -60,69 +56,144 @@ kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE])
}
int
-kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
- const u_char pub[CURVE25519_SIZE], struct sshbuf *out)
+kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE],
+ const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int raw)
{
u_char shared_key[CURVE25519_SIZE];
+ u_char zero[CURVE25519_SIZE];
int r;
crypto_scalarmult_curve25519(shared_key, key, pub);
+
+ /* Check for all-zero shared secret */
+ explicit_bzero(zero, CURVE25519_SIZE);
+ if (timingsafe_bcmp(zero, shared_key, CURVE25519_SIZE) == 0)
+ return SSH_ERR_KEY_INVALID_EC_VALUE;
+
#ifdef DEBUG_KEXECDH
dump_digest("shared secret", shared_key, CURVE25519_SIZE);
#endif
- sshbuf_reset(out);
- r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE);
+ if (raw)
+ r = sshbuf_put(out, shared_key, CURVE25519_SIZE);
+ else
+ r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE);
explicit_bzero(shared_key, CURVE25519_SIZE);
return r;
}
int
-kex_c25519_hash(
- int hash_alg,
- const char *client_version_string,
- const char *server_version_string,
- const char *ckexinit, size_t ckexinitlen,
- const char *skexinit, size_t skexinitlen,
- const u_char *serverhostkeyblob, size_t sbloblen,
- const u_char client_dh_pub[CURVE25519_SIZE],
- const u_char server_dh_pub[CURVE25519_SIZE],
- const u_char *shared_secret, size_t secretlen,
- u_char *hash, size_t *hashlen)
+kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
+ const u_char pub[CURVE25519_SIZE], struct sshbuf *out)
+{
+ return kexc25519_shared_key_ext(key, pub, out, 0);
+}
+
+int
+kex_c25519_keypair(struct kex *kex)
{
- struct sshbuf *b;
+ struct sshbuf *buf = NULL;
+ u_char *cp = NULL;
int r;
- if (*hashlen < ssh_digest_bytes(hash_alg))
- return SSH_ERR_INVALID_ARGUMENT;
- if ((b = sshbuf_new()) == NULL)
+ if ((buf = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_put_cstring(b, client_version_string)) < 0 ||
- (r = sshbuf_put_cstring(b, server_version_string)) < 0 ||
- /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
- (r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 ||
- (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 ||
- (r = sshbuf_put(b, ckexinit, ckexinitlen)) < 0 ||
- (r = sshbuf_put_u32(b, skexinitlen+1)) < 0 ||
- (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 ||
- (r = sshbuf_put(b, skexinit, skexinitlen)) < 0 ||
- (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) < 0 ||
- (r = sshbuf_put_string(b, client_dh_pub, CURVE25519_SIZE)) < 0 ||
- (r = sshbuf_put_string(b, server_dh_pub, CURVE25519_SIZE)) < 0 ||
- (r = sshbuf_put(b, shared_secret, secretlen)) < 0) {
- sshbuf_free(b);
- return r;
+ if ((r = sshbuf_reserve(buf, CURVE25519_SIZE, &cp)) != 0)
+ goto out;
+ kexc25519_keygen(kex->c25519_client_key, cp);
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key c25519:", cp, CURVE25519_SIZE);
+#endif
+ kex->client_pub = buf;
+ buf = NULL;
+ out:
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_c25519_enc(struct kex *kex, const struct sshbuf *client_blob,
+ struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
+{
+ struct sshbuf *server_blob = NULL;
+ struct sshbuf *buf = NULL;
+ const u_char *client_pub;
+ u_char *server_pub;
+ u_char server_key[CURVE25519_SIZE];
+ int r;
+
+ *server_blobp = NULL;
+ *shared_secretp = NULL;
+
+ if (sshbuf_len(client_blob) != CURVE25519_SIZE) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ client_pub = sshbuf_ptr(client_blob);
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key 25519:", client_pub, CURVE25519_SIZE);
+#endif
+ /* allocate space for encrypted KEM key and ECDH pub key */
+ if ((server_blob = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_reserve(server_blob, CURVE25519_SIZE, &server_pub)) != 0)
+ goto out;
+ kexc25519_keygen(server_key, server_pub);
+ /* allocate shared secret */
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 0)) < 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
+ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ *server_blobp = server_blob;
+ *shared_secretp = buf;
+ server_blob = NULL;
+ buf = NULL;
+ out:
+ explicit_bzero(server_key, sizeof(server_key));
+ sshbuf_free(server_blob);
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_c25519_dec(struct kex *kex, const struct sshbuf *server_blob,
+ struct sshbuf **shared_secretp)
+{
+ struct sshbuf *buf = NULL;
+ const u_char *server_pub;
+ int r;
+
+ *shared_secretp = NULL;
+
+ if (sshbuf_len(server_blob) != CURVE25519_SIZE) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
}
-#ifdef DEBUG_KEX
- sshbuf_dump(b, stderr);
+ server_pub = sshbuf_ptr(server_blob);
+#ifdef DEBUG_KEXECDH
+ dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
#endif
- if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
- sshbuf_free(b);
- return SSH_ERR_LIBCRYPTO_ERROR;
+ /* shared secret */
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
}
- sshbuf_free(b);
- *hashlen = ssh_digest_bytes(hash_alg);
-#ifdef DEBUG_KEX
- dump_digest("hash", hash, *hashlen);
+ if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
+ buf, 0)) < 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
#endif
- return 0;
+ *shared_secretp = buf;
+ buf = NULL;
+ out:
+ sshbuf_free(buf);
+ return r;
}
diff --git a/kexc25519c.c b/kexc25519c.c
deleted file mode 100644
index b7ef65dc..00000000
--- a/kexc25519c.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* $OpenBSD: kexc25519c.c,v 1.7 2015/01/26 06:10:03 djm Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2010 Damien Miller. All rights reserved.
- * Copyright (c) 2013 Aris Adamantiadis. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-
-#include "sshkey.h"
-#include "cipher.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "ssh2.h"
-#include "sshbuf.h"
-#include "digest.h"
-#include "ssherr.h"
-
-static int
-input_kex_c25519_reply(int type, u_int32_t seq, void *ctxt);
-
-int
-kexc25519_client(struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- int r;
-
- kexc25519_keygen(kex->c25519_client_key, kex->c25519_client_pubkey);
-#ifdef DEBUG_KEXECDH
- dump_digest("client private key:", kex->c25519_client_key,
- sizeof(kex->c25519_client_key));
-#endif
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 ||
- (r = sshpkt_put_string(ssh, kex->c25519_client_pubkey,
- sizeof(kex->c25519_client_pubkey))) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- return r;
-
- debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
- ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_c25519_reply);
- return 0;
-}
-
-static int
-input_kex_c25519_reply(int type, u_int32_t seq, void *ctxt)
-{
- struct ssh *ssh = ctxt;
- struct kex *kex = ssh->kex;
- struct sshkey *server_host_key = NULL;
- struct sshbuf *shared_secret = NULL;
- u_char *server_pubkey = NULL;
- u_char *server_host_key_blob = NULL, *signature = NULL;
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t slen, pklen, sbloblen, hashlen;
- int r;
-
- if (kex->verify_host_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
-
- /* hostkey */
- if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
- &sbloblen)) != 0 ||
- (r = sshkey_from_blob(server_host_key_blob, sbloblen,
- &server_host_key)) != 0)
- goto out;
- if (server_host_key->type != kex->hostkey_type ||
- (kex->hostkey_type == KEY_ECDSA &&
- server_host_key->ecdsa_nid != kex->hostkey_nid)) {
- r = SSH_ERR_KEY_TYPE_MISMATCH;
- goto out;
- }
- if (kex->verify_host_key(server_host_key, ssh) == -1) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
-
- /* Q_S, server public key */
- /* signed H */
- if ((r = sshpkt_get_string(ssh, &server_pubkey, &pklen)) != 0 ||
- (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
- if (pklen != CURVE25519_SIZE) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
-
-#ifdef DEBUG_KEXECDH
- dump_digest("server public key:", server_pubkey, CURVE25519_SIZE);
-#endif
-
- if ((shared_secret = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = kexc25519_shared_key(kex->c25519_client_key, server_pubkey,
- shared_secret)) < 0)
- goto out;
-
- /* calc and verify H */
- hashlen = sizeof(hash);
- if ((r = kex_c25519_hash(
- kex->hash_alg,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- server_host_key_blob, sbloblen,
- kex->c25519_client_pubkey,
- server_pubkey,
- sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
- hash, &hashlen)) < 0)
- goto out;
-
- if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
- ssh->compat)) != 0)
- goto out;
-
- /* save session id */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
- r = kex_send_newkeys(ssh);
-out:
- explicit_bzero(hash, sizeof(hash));
- explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
- free(server_host_key_blob);
- free(server_pubkey);
- free(signature);
- sshkey_free(server_host_key);
- sshbuf_free(shared_secret);
- return r;
-}
diff --git a/kexc25519s.c b/kexc25519s.c
deleted file mode 100644
index b2d2c858..00000000
--- a/kexc25519s.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/* $OpenBSD: kexc25519s.c,v 1.8 2015/01/26 06:10:03 djm Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2010 Damien Miller. All rights reserved.
- * Copyright (c) 2013 Aris Adamantiadis. All rights reserved.
- *
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <string.h>
-#include <signal.h>
-
-#include "sshkey.h"
-#include "cipher.h"
-#include "digest.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "ssh2.h"
-#include "sshbuf.h"
-#include "ssherr.h"
-
-static int input_kex_c25519_init(int, u_int32_t, void *);
-
-int
-kexc25519_server(struct ssh *ssh)
-{
- debug("expecting SSH2_MSG_KEX_ECDH_INIT");
- ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_c25519_init);
- return 0;
-}
-
-static int
-input_kex_c25519_init(int type, u_int32_t seq, void *ctxt)
-{
- struct ssh *ssh = ctxt;
- struct kex *kex = ssh->kex;
- struct sshkey *server_host_private, *server_host_public;
- struct sshbuf *shared_secret = NULL;
- u_char *server_host_key_blob = NULL, *signature = NULL;
- u_char server_key[CURVE25519_SIZE];
- u_char *client_pubkey = NULL;
- u_char server_pubkey[CURVE25519_SIZE];
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t slen, pklen, sbloblen, hashlen;
- int r;
-
- /* generate private key */
- kexc25519_keygen(server_key, server_pubkey);
-#ifdef DEBUG_KEXECDH
- dump_digest("server private key:", server_key, sizeof(server_key));
-#endif
- if (kex->load_host_public_key == NULL ||
- kex->load_host_private_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- server_host_public = kex->load_host_public_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- server_host_private = kex->load_host_private_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- if (server_host_public == NULL) {
- r = SSH_ERR_NO_HOSTKEY_LOADED;
- goto out;
- }
-
- if ((r = sshpkt_get_string(ssh, &client_pubkey, &pklen)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
- if (pklen != CURVE25519_SIZE) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
-#ifdef DEBUG_KEXECDH
- dump_digest("client public key:", client_pubkey, CURVE25519_SIZE);
-#endif
-
- if ((shared_secret = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = kexc25519_shared_key(server_key, client_pubkey,
- shared_secret)) < 0)
- goto out;
-
- /* calc H */
- if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
- &sbloblen)) != 0)
- goto out;
- hashlen = sizeof(hash);
- if ((r = kex_c25519_hash(
- kex->hash_alg,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- server_host_key_blob, sbloblen,
- client_pubkey,
- server_pubkey,
- sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
- hash, &hashlen)) < 0)
- goto out;
-
- /* save session id := H */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- /* sign H */
- if ((r = kex->sign(server_host_private, server_host_public,
- &signature, &slen, hash, hashlen, ssh->compat)) < 0)
- goto out;
-
- /* send server hostkey, ECDH pubkey 'Q_S' and signed H */
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 ||
- (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
- (r = sshpkt_put_string(ssh, server_pubkey, sizeof(server_pubkey))) != 0 ||
- (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- goto out;
-
- if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
- r = kex_send_newkeys(ssh);
-out:
- explicit_bzero(hash, sizeof(hash));
- explicit_bzero(server_key, sizeof(server_key));
- free(server_host_key_blob);
- free(signature);
- free(client_pubkey);
- sshbuf_free(shared_secret);
- return r;
-}
diff --git a/kexdh.c b/kexdh.c
index feea6697..67133e33 100644
--- a/kexdh.c
+++ b/kexdh.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: kexdh.c,v 1.25 2015/01/19 20:16:15 markus Exp $ */
+/* $OpenBSD: kexdh.c,v 1.32 2019/01/21 10:40:11 djm Exp $ */
/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
+ * Copyright (c) 2019 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,64 +30,172 @@
#include <sys/types.h>
#include <signal.h>
+#include <stdio.h>
+#include <string.h>
-#include <openssl/evp.h>
+#include "openbsd-compat/openssl-compat.h"
+#include <openssl/dh.h>
-#include "ssh2.h"
#include "sshkey.h"
-#include "cipher.h"
#include "kex.h"
-#include "ssherr.h"
#include "sshbuf.h"
#include "digest.h"
+#include "ssherr.h"
+#include "dh.h"
int
-kex_dh_hash(
- const char *client_version_string,
- const char *server_version_string,
- const u_char *ckexinit, size_t ckexinitlen,
- const u_char *skexinit, size_t skexinitlen,
- const u_char *serverhostkeyblob, size_t sbloblen,
- const BIGNUM *client_dh_pub,
- const BIGNUM *server_dh_pub,
- const BIGNUM *shared_secret,
- u_char *hash, size_t *hashlen)
+kex_dh_keygen(struct kex *kex)
{
- struct sshbuf *b;
- int r;
-
- if (*hashlen < ssh_digest_bytes(SSH_DIGEST_SHA1))
+ switch (kex->kex_type) {
+ case KEX_DH_GRP1_SHA1:
+ kex->dh = dh_new_group1();
+ break;
+ case KEX_DH_GRP14_SHA1:
+ case KEX_DH_GRP14_SHA256:
+ kex->dh = dh_new_group14();
+ break;
+ case KEX_DH_GRP16_SHA512:
+ kex->dh = dh_new_group16();
+ break;
+ case KEX_DH_GRP18_SHA512:
+ kex->dh = dh_new_group18();
+ break;
+ default:
return SSH_ERR_INVALID_ARGUMENT;
- if ((b = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
- (r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
- /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
- (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
- (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
- (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
- (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 ||
- (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
- (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
- (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
- (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 ||
- (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 ||
- (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
- sshbuf_free(b);
- return r;
}
-#ifdef DEBUG_KEX
- sshbuf_dump(b, stderr);
+ if (kex->dh == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ return (dh_gen_key(kex->dh, kex->we_need * 8));
+}
+
+int
+kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out)
+{
+ BIGNUM *shared_secret = NULL;
+ u_char *kbuf = NULL;
+ size_t klen = 0;
+ int kout, r;
+
+#ifdef DEBUG_KEXDH
+ fprintf(stderr, "dh_pub= ");
+ BN_print_fp(stderr, dh_pub);
+ fprintf(stderr, "\n");
+ debug("bits %d", BN_num_bits(dh_pub));
+ DHparams_print_fp(stderr, kex->dh);
+ fprintf(stderr, "\n");
#endif
- if (ssh_digest_buffer(SSH_DIGEST_SHA1, b, hash, *hashlen) != 0) {
- sshbuf_free(b);
- return SSH_ERR_LIBCRYPTO_ERROR;
+
+ if (!dh_pub_is_valid(kex->dh, dh_pub)) {
+ r = SSH_ERR_MESSAGE_INCOMPLETE;
+ goto out;
+ }
+ klen = DH_size(kex->dh);
+ if ((kbuf = malloc(klen)) == NULL ||
+ (shared_secret = BN_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 ||
+ BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
}
- sshbuf_free(b);
- *hashlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
-#ifdef DEBUG_KEX
- dump_digest("hash", hash, *hashlen);
+#ifdef DEBUG_KEXDH
+ dump_digest("shared secret", kbuf, kout);
+#endif
+ r = sshbuf_put_bignum2(out, shared_secret);
+ out:
+ freezero(kbuf, klen);
+ BN_clear_free(shared_secret);
+ return r;
+}
+
+int
+kex_dh_keypair(struct kex *kex)
+{
+ const BIGNUM *pub_key;
+ struct sshbuf *buf = NULL;
+ int r;
+
+ if ((r = kex_dh_keygen(kex)) != 0)
+ return r;
+ DH_get0_key(kex->dh, &pub_key, NULL);
+ if ((buf = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((r = sshbuf_put_bignum2(buf, pub_key)) != 0 ||
+ (r = sshbuf_get_u32(buf, NULL)) != 0)
+ goto out;
+#ifdef DEBUG_KEXDH
+ DHparams_print_fp(stderr, kex->dh);
+ fprintf(stderr, "pub= ");
+ BN_print_fp(stderr, pub_key);
+ fprintf(stderr, "\n");
#endif
- return 0;
+ kex->client_pub = buf;
+ buf = NULL;
+ out:
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_dh_enc(struct kex *kex, const struct sshbuf *client_blob,
+ struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
+{
+ const BIGNUM *pub_key;
+ struct sshbuf *server_blob = NULL;
+ int r;
+
+ *server_blobp = NULL;
+ *shared_secretp = NULL;
+
+ if ((r = kex_dh_keygen(kex)) != 0)
+ goto out;
+ DH_get0_key(kex->dh, &pub_key, NULL);
+ if ((server_blob = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put_bignum2(server_blob, pub_key)) != 0 ||
+ (r = sshbuf_get_u32(server_blob, NULL)) != 0)
+ goto out;
+ if ((r = kex_dh_dec(kex, client_blob, shared_secretp)) != 0)
+ goto out;
+ *server_blobp = server_blob;
+ server_blob = NULL;
+ out:
+ DH_free(kex->dh);
+ kex->dh = NULL;
+ sshbuf_free(server_blob);
+ return r;
+}
+
+int
+kex_dh_dec(struct kex *kex, const struct sshbuf *dh_blob,
+ struct sshbuf **shared_secretp)
+{
+ struct sshbuf *buf = NULL;
+ BIGNUM *dh_pub = NULL;
+ int r;
+
+ *shared_secretp = NULL;
+
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put_stringb(buf, dh_blob)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &dh_pub)) != 0)
+ goto out;
+ sshbuf_reset(buf);
+ if ((r = kex_dh_compute_key(kex, dh_pub, buf)) != 0)
+ goto out;
+ *shared_secretp = buf;
+ buf = NULL;
+ out:
+ DH_free(kex->dh);
+ kex->dh = NULL;
+ sshbuf_free(buf);
+ return r;
}
#endif /* WITH_OPENSSL */
diff --git a/kexdhc.c b/kexdhc.c
deleted file mode 100644
index af259f16..00000000
--- a/kexdhc.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/* $OpenBSD: kexdhc.c,v 1.18 2015/01/26 06:10:03 djm Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#ifdef WITH_OPENSSL
-
-#include <sys/types.h>
-
-#include <openssl/dh.h>
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-
-#include "sshkey.h"
-#include "cipher.h"
-#include "digest.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-#include "dispatch.h"
-#include "compat.h"
-#include "ssherr.h"
-#include "sshbuf.h"
-
-static int input_kex_dh(int, u_int32_t, void *);
-
-int
-kexdh_client(struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- int r;
-
- /* generate and send 'e', client DH public key */
- switch (kex->kex_type) {
- case KEX_DH_GRP1_SHA1:
- kex->dh = dh_new_group1();
- break;
- case KEX_DH_GRP14_SHA1:
- kex->dh = dh_new_group14();
- break;
- default:
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- if (kex->dh == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- debug("sending SSH2_MSG_KEXDH_INIT");
- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 ||
- (r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 ||
- (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- goto out;
-#ifdef DEBUG_KEXDH
- DHparams_print_fp(stderr, kex->dh);
- fprintf(stderr, "pub= ");
- BN_print_fp(stderr, kex->dh->pub_key);
- fprintf(stderr, "\n");
-#endif
- debug("expecting SSH2_MSG_KEXDH_REPLY");
- ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_REPLY, &input_kex_dh);
- r = 0;
- out:
- return r;
-}
-
-static int
-input_kex_dh(int type, u_int32_t seq, void *ctxt)
-{
- struct ssh *ssh = ctxt;
- struct kex *kex = ssh->kex;
- BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
- struct sshkey *server_host_key = NULL;
- u_char *kbuf = NULL, *server_host_key_blob = NULL, *signature = NULL;
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t klen = 0, slen, sbloblen, hashlen;
- int kout, r;
-
- if (kex->verify_host_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- /* key, cert */
- if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
- &sbloblen)) != 0 ||
- (r = sshkey_from_blob(server_host_key_blob, sbloblen,
- &server_host_key)) != 0)
- goto out;
- if (server_host_key->type != kex->hostkey_type ||
- (kex->hostkey_type == KEY_ECDSA &&
- server_host_key->ecdsa_nid != kex->hostkey_nid)) {
- r = SSH_ERR_KEY_TYPE_MISMATCH;
- goto out;
- }
- if (kex->verify_host_key(server_host_key, ssh) == -1) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
- /* DH parameter f, server public DH key */
- if ((dh_server_pub = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- /* signed H */
- if ((r = sshpkt_get_bignum2(ssh, dh_server_pub)) != 0 ||
- (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "dh_server_pub= ");
- BN_print_fp(stderr, dh_server_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
- if (!dh_pub_is_valid(kex->dh, dh_server_pub)) {
- sshpkt_disconnect(ssh, "bad server public DH value");
- r = SSH_ERR_MESSAGE_INCOMPLETE;
- goto out;
- }
-
- klen = DH_size(kex->dh);
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 ||
- BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
-#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
-#endif
-
- /* calc and verify H */
- hashlen = sizeof(hash);
- if ((r = kex_dh_hash(
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- server_host_key_blob, sbloblen,
- kex->dh->pub_key,
- dh_server_pub,
- shared_secret,
- hash, &hashlen)) != 0)
- goto out;
-
- if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
- ssh->compat)) != 0)
- goto out;
-
- /* save session id */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
- r = kex_send_newkeys(ssh);
- out:
- explicit_bzero(hash, sizeof(hash));
- DH_free(kex->dh);
- kex->dh = NULL;
- if (dh_server_pub)
- BN_clear_free(dh_server_pub);
- if (kbuf) {
- explicit_bzero(kbuf, klen);
- free(kbuf);
- }
- if (shared_secret)
- BN_clear_free(shared_secret);
- sshkey_free(server_host_key);
- free(server_host_key_blob);
- free(signature);
- return r;
-}
-#endif /* WITH_OPENSSL */
diff --git a/kexdhs.c b/kexdhs.c
deleted file mode 100644
index de7c05b1..00000000
--- a/kexdhs.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* $OpenBSD: kexdhs.c,v 1.22 2015/01/26 06:10:03 djm Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#ifdef WITH_OPENSSL
-
-#include <sys/types.h>
-
-#include <stdarg.h>
-#include <string.h>
-#include <signal.h>
-
-#include <openssl/dh.h>
-
-#include "sshkey.h"
-#include "cipher.h"
-#include "digest.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-
-#include "dispatch.h"
-#include "compat.h"
-#include "ssherr.h"
-#include "sshbuf.h"
-
-static int input_kex_dh_init(int, u_int32_t, void *);
-
-int
-kexdh_server(struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- int r;
-
- /* generate server DH public key */
- switch (kex->kex_type) {
- case KEX_DH_GRP1_SHA1:
- kex->dh = dh_new_group1();
- break;
- case KEX_DH_GRP14_SHA1:
- kex->dh = dh_new_group14();
- break;
- default:
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- if (kex->dh == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
- goto out;
-
- debug("expecting SSH2_MSG_KEXDH_INIT");
- ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_INIT, &input_kex_dh_init);
- r = 0;
- out:
- return r;
-}
-
-int
-input_kex_dh_init(int type, u_int32_t seq, void *ctxt)
-{
- struct ssh *ssh = ctxt;
- struct kex *kex = ssh->kex;
- BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
- struct sshkey *server_host_public, *server_host_private;
- u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL;
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t sbloblen, slen;
- size_t klen = 0, hashlen;
- int kout, r;
-
- if (kex->load_host_public_key == NULL ||
- kex->load_host_private_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- server_host_public = kex->load_host_public_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- server_host_private = kex->load_host_private_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- if (server_host_public == NULL) {
- r = SSH_ERR_NO_HOSTKEY_LOADED;
- goto out;
- }
-
- /* key, cert */
- if ((dh_client_pub = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshpkt_get_bignum2(ssh, dh_client_pub)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
-
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "dh_client_pub= ");
- BN_print_fp(stderr, dh_client_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_client_pub));
-#endif
-
-#ifdef DEBUG_KEXDH
- DHparams_print_fp(stderr, kex->dh);
- fprintf(stderr, "pub= ");
- BN_print_fp(stderr, kex->dh->pub_key);
- fprintf(stderr, "\n");
-#endif
- if (!dh_pub_is_valid(kex->dh, dh_client_pub)) {
- sshpkt_disconnect(ssh, "bad client public DH value");
- r = SSH_ERR_MESSAGE_INCOMPLETE;
- goto out;
- }
-
- klen = DH_size(kex->dh);
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 ||
- BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
-#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
-#endif
- if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
- &sbloblen)) != 0)
- goto out;
- /* calc H */
- hashlen = sizeof(hash);
- if ((r = kex_dh_hash(
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- server_host_key_blob, sbloblen,
- dh_client_pub,
- kex->dh->pub_key,
- shared_secret,
- hash, &hashlen)) != 0)
- goto out;
-
- /* save session id := H */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- /* sign H */
- if ((r = kex->sign(server_host_private, server_host_public,
- &signature, &slen, hash, hashlen, ssh->compat)) < 0)
- goto out;
-
- /* destroy_sensitive_data(); */
-
- /* send server hostkey, DH pubkey 'f' and singed H */
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 ||
- (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
- (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */
- (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- goto out;
-
- if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
- r = kex_send_newkeys(ssh);
- out:
- explicit_bzero(hash, sizeof(hash));
- DH_free(kex->dh);
- kex->dh = NULL;
- if (dh_client_pub)
- BN_clear_free(dh_client_pub);
- if (kbuf) {
- explicit_bzero(kbuf, klen);
- free(kbuf);
- }
- if (shared_secret)
- BN_clear_free(shared_secret);
- free(server_host_key_blob);
- free(signature);
- return r;
-}
-#endif /* WITH_OPENSSL */
diff --git a/kexecdh.c b/kexecdh.c
index 2a4fec6b..efb2e55a 100644
--- a/kexecdh.c
+++ b/kexecdh.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: kexecdh.c,v 1.6 2015/01/19 20:16:15 markus Exp $ */
+/* $OpenBSD: kexecdh.c,v 1.10 2019/01/21 10:40:11 djm Exp $ */
/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
+ * Copyright (c) 2019 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,71 +30,210 @@
#include <sys/types.h>
-#include <signal.h>
+#include <stdio.h>
#include <string.h>
+#include <signal.h>
-#include <openssl/bn.h>
-#include <openssl/evp.h>
-#include <openssl/ec.h>
#include <openssl/ecdh.h>
-#include "ssh2.h"
#include "sshkey.h"
-#include "cipher.h"
#include "kex.h"
#include "sshbuf.h"
#include "digest.h"
#include "ssherr.h"
+static int
+kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key,
+ const EC_GROUP *, struct sshbuf **);
+
int
-kex_ecdh_hash(
- int hash_alg,
- const EC_GROUP *ec_group,
- const char *client_version_string,
- const char *server_version_string,
- const u_char *ckexinit, size_t ckexinitlen,
- const u_char *skexinit, size_t skexinitlen,
- const u_char *serverhostkeyblob, size_t sbloblen,
- const EC_POINT *client_dh_pub,
- const EC_POINT *server_dh_pub,
- const BIGNUM *shared_secret,
- u_char *hash, size_t *hashlen)
+kex_ecdh_keypair(struct kex *kex)
{
- struct sshbuf *b;
+ EC_KEY *client_key = NULL;
+ const EC_GROUP *group;
+ const EC_POINT *public_key;
+ struct sshbuf *buf = NULL;
int r;
- if (*hashlen < ssh_digest_bytes(hash_alg))
- return SSH_ERR_INVALID_ARGUMENT;
- if ((b = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
- (r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
- /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
- (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
- (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
- (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
- (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 ||
- (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
- (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
- (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
- (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 ||
- (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 ||
- (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
- sshbuf_free(b);
- return r;
+ if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (EC_KEY_generate_key(client_key) != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
}
-#ifdef DEBUG_KEX
- sshbuf_dump(b, stderr);
+ group = EC_KEY_get0_group(client_key);
+ public_key = EC_KEY_get0_public_key(client_key);
+
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put_ec(buf, public_key, group)) != 0 ||
+ (r = sshbuf_get_u32(buf, NULL)) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ fputs("client private key:\n", stderr);
+ sshkey_dump_ec_key(client_key);
#endif
- if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
- sshbuf_free(b);
- return SSH_ERR_LIBCRYPTO_ERROR;
+ kex->ec_client_key = client_key;
+ kex->ec_group = group;
+ client_key = NULL; /* owned by the kex */
+ kex->client_pub = buf;
+ buf = NULL;
+ out:
+ EC_KEY_free(client_key);
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob,
+ struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
+{
+ const EC_GROUP *group;
+ const EC_POINT *pub_key;
+ EC_KEY *server_key = NULL;
+ struct sshbuf *server_blob = NULL;
+ int r;
+
+ *server_blobp = NULL;
+ *shared_secretp = NULL;
+
+ if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (EC_KEY_generate_key(server_key) != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
}
- sshbuf_free(b);
- *hashlen = ssh_digest_bytes(hash_alg);
-#ifdef DEBUG_KEX
- dump_digest("hash", hash, *hashlen);
+ group = EC_KEY_get0_group(server_key);
+
+#ifdef DEBUG_KEXECDH
+ fputs("server private key:\n", stderr);
+ sshkey_dump_ec_key(server_key);
+#endif
+ pub_key = EC_KEY_get0_public_key(server_key);
+ if ((server_blob = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put_ec(server_blob, pub_key, group)) != 0 ||
+ (r = sshbuf_get_u32(server_blob, NULL)) != 0)
+ goto out;
+ if ((r = kex_ecdh_dec_key_group(kex, client_blob, server_key, group,
+ shared_secretp)) != 0)
+ goto out;
+ *server_blobp = server_blob;
+ server_blob = NULL;
+ out:
+ EC_KEY_free(server_key);
+ sshbuf_free(server_blob);
+ return r;
+}
+
+static int
+kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob,
+ EC_KEY *key, const EC_GROUP *group, struct sshbuf **shared_secretp)
+{
+ struct sshbuf *buf = NULL;
+ BIGNUM *shared_secret = NULL;
+ EC_POINT *dh_pub = NULL;
+ u_char *kbuf = NULL;
+ size_t klen = 0;
+ int r;
+
+ *shared_secretp = NULL;
+
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0)
+ goto out;
+ if ((dh_pub = EC_POINT_new(group)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) {
+ goto out;
+ }
+ sshbuf_reset(buf);
+
+#ifdef DEBUG_KEXECDH
+ fputs("public key:\n", stderr);
+ sshkey_dump_ec_point(group, dh_pub);
#endif
- return 0;
+ if (sshkey_ec_validate_public(group, dh_pub) != 0) {
+ r = SSH_ERR_MESSAGE_INCOMPLETE;
+ goto out;
+ }
+ klen = (EC_GROUP_get_degree(group) + 7) / 8;
+ if ((kbuf = malloc(klen)) == NULL ||
+ (shared_secret = BN_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen ||
+ BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+#ifdef DEBUG_KEXECDH
+ dump_digest("shared secret", kbuf, klen);
+#endif
+ if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0)
+ goto out;
+ *shared_secretp = buf;
+ buf = NULL;
+ out:
+ EC_POINT_clear_free(dh_pub);
+ BN_clear_free(shared_secret);
+ freezero(kbuf, klen);
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_ecdh_dec(struct kex *kex, const struct sshbuf *server_blob,
+ struct sshbuf **shared_secretp)
+{
+ int r;
+
+ r = kex_ecdh_dec_key_group(kex, server_blob, kex->ec_client_key,
+ kex->ec_group, shared_secretp);
+ EC_KEY_free(kex->ec_client_key);
+ kex->ec_client_key = NULL;
+ return r;
+}
+
+#else
+
+#include "ssherr.h"
+
+struct kex;
+struct sshbuf;
+struct sshkey;
+
+int
+kex_ecdh_keypair(struct kex *kex)
+{
+ return SSH_ERR_SIGN_ALG_UNSUPPORTED;
+}
+
+int
+kex_ecdh_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_ecdh_dec(struct kex *kex, const struct sshbuf *server_blob,
+ struct sshbuf **shared_secretp)
+{
+ return SSH_ERR_SIGN_ALG_UNSUPPORTED;
}
#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
diff --git a/kexecdhc.c b/kexecdhc.c
deleted file mode 100644
index 90220ce8..00000000
--- a/kexecdhc.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/* $OpenBSD: kexecdhc.c,v 1.10 2015/01/26 06:10:03 djm Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2010 Damien Miller. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
-
-#include <sys/types.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-
-#include <openssl/ecdh.h>
-
-#include "sshkey.h"
-#include "cipher.h"
-#include "digest.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-#include "dispatch.h"
-#include "compat.h"
-#include "ssherr.h"
-#include "sshbuf.h"
-
-static int input_kex_ecdh_reply(int, u_int32_t, void *);
-
-int
-kexecdh_client(struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- EC_KEY *client_key = NULL;
- const EC_GROUP *group;
- const EC_POINT *public_key;
- int r;
-
- if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (EC_KEY_generate_key(client_key) != 1) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- group = EC_KEY_get0_group(client_key);
- public_key = EC_KEY_get0_public_key(client_key);
-
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 ||
- (r = sshpkt_put_ec(ssh, public_key, group)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- goto out;
- debug("sending SSH2_MSG_KEX_ECDH_INIT");
-
-#ifdef DEBUG_KEXECDH
- fputs("client private key:\n", stderr);
- sshkey_dump_ec_key(client_key);
-#endif
- kex->ec_client_key = client_key;
- kex->ec_group = group;
- client_key = NULL; /* owned by the kex */
-
- debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
- ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_ecdh_reply);
- r = 0;
- out:
- if (client_key)
- EC_KEY_free(client_key);
- return r;
-}
-
-static int
-input_kex_ecdh_reply(int type, u_int32_t seq, void *ctxt)
-{
- struct ssh *ssh = ctxt;
- struct kex *kex = ssh->kex;
- const EC_GROUP *group;
- EC_POINT *server_public = NULL;
- EC_KEY *client_key;
- BIGNUM *shared_secret = NULL;
- struct sshkey *server_host_key = NULL;
- u_char *server_host_key_blob = NULL, *signature = NULL;
- u_char *kbuf = NULL;
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t slen, sbloblen;
- size_t klen = 0, hashlen;
- int r;
-
- if (kex->verify_host_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- group = kex->ec_group;
- client_key = kex->ec_client_key;
-
- /* hostkey */
- if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
- &sbloblen)) != 0 ||
- (r = sshkey_from_blob(server_host_key_blob, sbloblen,
- &server_host_key)) != 0)
- goto out;
- if (server_host_key->type != kex->hostkey_type ||
- (kex->hostkey_type == KEY_ECDSA &&
- server_host_key->ecdsa_nid != kex->hostkey_nid)) {
- r = SSH_ERR_KEY_TYPE_MISMATCH;
- goto out;
- }
- if (kex->verify_host_key(server_host_key, ssh) == -1) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
-
- /* Q_S, server public key */
- /* signed H */
- if ((server_public = EC_POINT_new(group)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshpkt_get_ec(ssh, server_public, group)) != 0 ||
- (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
-
-#ifdef DEBUG_KEXECDH
- fputs("server public key:\n", stderr);
- sshkey_dump_ec_point(group, server_public);
-#endif
- if (sshkey_ec_validate_public(group, server_public) != 0) {
- sshpkt_disconnect(ssh, "invalid server public key");
- r = SSH_ERR_MESSAGE_INCOMPLETE;
- goto out;
- }
-
- klen = (EC_GROUP_get_degree(group) + 7) / 8;
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (ECDH_compute_key(kbuf, klen, server_public,
- client_key, NULL) != (int)klen ||
- BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
-
-#ifdef DEBUG_KEXECDH
- dump_digest("shared secret", kbuf, klen);
-#endif
- /* calc and verify H */
- hashlen = sizeof(hash);
- if ((r = kex_ecdh_hash(
- kex->hash_alg,
- group,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- server_host_key_blob, sbloblen,
- EC_KEY_get0_public_key(client_key),
- server_public,
- shared_secret,
- hash, &hashlen)) != 0)
- goto out;
-
- if ((r = sshkey_verify(server_host_key, signature, slen, hash,
- hashlen, ssh->compat)) != 0)
- goto out;
-
- /* save session id */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
- r = kex_send_newkeys(ssh);
- out:
- explicit_bzero(hash, sizeof(hash));
- if (kex->ec_client_key) {
- EC_KEY_free(kex->ec_client_key);
- kex->ec_client_key = NULL;
- }
- if (server_public)
- EC_POINT_clear_free(server_public);
- if (kbuf) {
- explicit_bzero(kbuf, klen);
- free(kbuf);
- }
- if (shared_secret)
- BN_clear_free(shared_secret);
- sshkey_free(server_host_key);
- free(server_host_key_blob);
- free(signature);
- return r;
-}
-#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
-
diff --git a/kexecdhs.c b/kexecdhs.c
deleted file mode 100644
index 0adb80e6..00000000
--- a/kexecdhs.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/* $OpenBSD: kexecdhs.c,v 1.14 2015/01/26 06:10:03 djm Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2010 Damien Miller. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
-
-#include <sys/types.h>
-#include <string.h>
-#include <signal.h>
-
-#include <openssl/ecdh.h>
-
-#include "sshkey.h"
-#include "cipher.h"
-#include "digest.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "ssh2.h"
-
-#include "dispatch.h"
-#include "compat.h"
-#include "ssherr.h"
-#include "sshbuf.h"
-
-static int input_kex_ecdh_init(int, u_int32_t, void *);
-
-int
-kexecdh_server(struct ssh *ssh)
-{
- debug("expecting SSH2_MSG_KEX_ECDH_INIT");
- ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_ecdh_init);
- return 0;
-}
-
-static int
-input_kex_ecdh_init(int type, u_int32_t seq, void *ctxt)
-{
- struct ssh *ssh = ctxt;
- struct kex *kex = ssh->kex;
- EC_POINT *client_public;
- EC_KEY *server_key = NULL;
- const EC_GROUP *group;
- const EC_POINT *public_key;
- BIGNUM *shared_secret = NULL;
- struct sshkey *server_host_private, *server_host_public;
- u_char *server_host_key_blob = NULL, *signature = NULL;
- u_char *kbuf = NULL;
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t slen, sbloblen;
- size_t klen = 0, hashlen;
- int r;
-
- if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (EC_KEY_generate_key(server_key) != 1) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- group = EC_KEY_get0_group(server_key);
-
-#ifdef DEBUG_KEXECDH
- fputs("server private key:\n", stderr);
- sshkey_dump_ec_key(server_key);
-#endif
-
- if (kex->load_host_public_key == NULL ||
- kex->load_host_private_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- server_host_public = kex->load_host_public_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- server_host_private = kex->load_host_private_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- if (server_host_public == NULL) {
- r = SSH_ERR_NO_HOSTKEY_LOADED;
- goto out;
- }
- if ((client_public = EC_POINT_new(group)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshpkt_get_ec(ssh, client_public, group)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
-
-#ifdef DEBUG_KEXECDH
- fputs("client public key:\n", stderr);
- sshkey_dump_ec_point(group, client_public);
-#endif
- if (sshkey_ec_validate_public(group, client_public) != 0) {
- sshpkt_disconnect(ssh, "invalid client public key");
- r = SSH_ERR_MESSAGE_INCOMPLETE;
- goto out;
- }
-
- /* Calculate shared_secret */
- klen = (EC_GROUP_get_degree(group) + 7) / 8;
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (ECDH_compute_key(kbuf, klen, client_public,
- server_key, NULL) != (int)klen ||
- BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
-
-#ifdef DEBUG_KEXECDH
- dump_digest("shared secret", kbuf, klen);
-#endif
- /* calc H */
- if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
- &sbloblen)) != 0)
- goto out;
- hashlen = sizeof(hash);
- if ((r = kex_ecdh_hash(
- kex->hash_alg,
- group,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- server_host_key_blob, sbloblen,
- client_public,
- EC_KEY_get0_public_key(server_key),
- shared_secret,
- hash, &hashlen)) != 0)
- goto out;
-
- /* save session id := H */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- /* sign H */
- if ((r = kex->sign(server_host_private, server_host_public,
- &signature, &slen, hash, hashlen, ssh->compat)) < 0)
- goto out;
-
- /* destroy_sensitive_data(); */
-
- public_key = EC_KEY_get0_public_key(server_key);
- /* send server hostkey, ECDH pubkey 'Q_S' and signed H */
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 ||
- (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
- (r = sshpkt_put_ec(ssh, public_key, group)) != 0 ||
- (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- goto out;
-
- if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
- r = kex_send_newkeys(ssh);
- out:
- explicit_bzero(hash, sizeof(hash));
- if (kex->ec_client_key) {
- EC_KEY_free(kex->ec_client_key);
- kex->ec_client_key = NULL;
- }
- if (server_key)
- EC_KEY_free(server_key);
- if (kbuf) {
- explicit_bzero(kbuf, klen);
- free(kbuf);
- }
- if (shared_secret)
- BN_clear_free(shared_secret);
- free(server_host_key_blob);
- free(signature);
- return r;
-}
-#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
-
diff --git a/kexgen.c b/kexgen.c
new file mode 100644
index 00000000..69348b96
--- /dev/null
+++ b/kexgen.c
@@ -0,0 +1,340 @@
+/* $OpenBSD: kexgen.c,v 1.4 2019/11/25 00:51:37 djm Exp $ */
+/*
+ * Copyright (c) 2019 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include "sshkey.h"
+#include "kex.h"
+#include "log.h"
+#include "packet.h"
+#include "ssh2.h"
+#include "sshbuf.h"
+#include "digest.h"
+#include "ssherr.h"
+
+static int input_kex_gen_init(int, u_int32_t, struct ssh *);
+static int input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh);
+
+static int
+kex_gen_hash(
+ int hash_alg,
+ const struct sshbuf *client_version,
+ const struct sshbuf *server_version,
+ const struct sshbuf *client_kexinit,
+ const struct sshbuf *server_kexinit,
+ const struct sshbuf *server_host_key_blob,
+ const struct sshbuf *client_pub,
+ const struct sshbuf *server_pub,
+ const struct sshbuf *shared_secret,
+ u_char *hash, size_t *hashlen)
+{
+ struct sshbuf *b;
+ int r;
+
+ if (*hashlen < ssh_digest_bytes(hash_alg))
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((b = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((r = sshbuf_put_stringb(b, client_version)) != 0 ||
+ (r = sshbuf_put_stringb(b, server_version)) != 0 ||
+ /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
+ (r = sshbuf_put_u32(b, sshbuf_len(client_kexinit) + 1)) != 0 ||
+ (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
+ (r = sshbuf_putb(b, client_kexinit)) != 0 ||
+ (r = sshbuf_put_u32(b, sshbuf_len(server_kexinit) + 1)) != 0 ||
+ (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
+ (r = sshbuf_putb(b, server_kexinit)) != 0 ||
+ (r = sshbuf_put_stringb(b, server_host_key_blob)) != 0 ||
+ (r = sshbuf_put_stringb(b, client_pub)) != 0 ||
+ (r = sshbuf_put_stringb(b, server_pub)) != 0 ||
+ (r = sshbuf_putb(b, shared_secret)) != 0) {
+ sshbuf_free(b);
+ return r;
+ }
+#ifdef DEBUG_KEX
+ sshbuf_dump(b, stderr);
+#endif
+ if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
+ sshbuf_free(b);
+ return SSH_ERR_LIBCRYPTO_ERROR;
+ }
+ sshbuf_free(b);
+ *hashlen = ssh_digest_bytes(hash_alg);
+#ifdef DEBUG_KEX
+ dump_digest("hash", hash, *hashlen);
+#endif
+ return 0;
+}
+
+int
+kex_gen_client(struct ssh *ssh)
+{
+ struct kex *kex = ssh->kex;
+ int r;
+
+ switch (kex->kex_type) {
+#ifdef WITH_OPENSSL
+ case KEX_DH_GRP1_SHA1:
+ case KEX_DH_GRP14_SHA1:
+ case KEX_DH_GRP14_SHA256:
+ case KEX_DH_GRP16_SHA512:
+ case KEX_DH_GRP18_SHA512:
+ r = kex_dh_keypair(kex);
+ break;
+ case KEX_ECDH_SHA2:
+ r = kex_ecdh_keypair(kex);
+ break;
+#endif
+ case KEX_C25519_SHA256:
+ r = kex_c25519_keypair(kex);
+ break;
+ case KEX_KEM_SNTRUP4591761X25519_SHA512:
+ r = kex_kem_sntrup4591761x25519_keypair(kex);
+ break;
+ default:
+ r = SSH_ERR_INVALID_ARGUMENT;
+ break;
+ }
+ if (r != 0)
+ return r;
+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 ||
+ (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ return r;
+ debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
+ ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_gen_reply);
+ return 0;
+}
+
+static int
+input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh)
+{
+ struct kex *kex = ssh->kex;
+ struct sshkey *server_host_key = NULL;
+ struct sshbuf *shared_secret = NULL;
+ struct sshbuf *server_blob = NULL;
+ struct sshbuf *tmp = NULL, *server_host_key_blob = NULL;
+ u_char *signature = NULL;
+ u_char hash[SSH_DIGEST_MAX_LENGTH];
+ size_t slen, hashlen;
+ int r;
+
+ /* hostkey */
+ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
+ goto out;
+ /* sshkey_fromb() consumes its buffer, so make a copy */
+ if ((tmp = sshbuf_fromb(server_host_key_blob)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshkey_fromb(tmp, &server_host_key)) != 0)
+ goto out;
+ if ((r = kex_verify_host_key(ssh, server_host_key)) != 0)
+ goto out;
+
+ /* Q_S, server public key */
+ /* signed H */
+ if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 ||
+ (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ goto out;
+
+ /* compute shared secret */
+ switch (kex->kex_type) {
+#ifdef WITH_OPENSSL
+ case KEX_DH_GRP1_SHA1:
+ case KEX_DH_GRP14_SHA1:
+ case KEX_DH_GRP14_SHA256:
+ case KEX_DH_GRP16_SHA512:
+ case KEX_DH_GRP18_SHA512:
+ r = kex_dh_dec(kex, server_blob, &shared_secret);
+ break;
+ case KEX_ECDH_SHA2:
+ r = kex_ecdh_dec(kex, server_blob, &shared_secret);
+ break;
+#endif
+ case KEX_C25519_SHA256:
+ r = kex_c25519_dec(kex, server_blob, &shared_secret);
+ break;
+ case KEX_KEM_SNTRUP4591761X25519_SHA512:
+ r = kex_kem_sntrup4591761x25519_dec(kex, server_blob,
+ &shared_secret);
+ break;
+ default:
+ r = SSH_ERR_INVALID_ARGUMENT;
+ break;
+ }
+ if (r !=0 )
+ goto out;
+
+ /* calc and verify H */
+ hashlen = sizeof(hash);
+ if ((r = kex_gen_hash(
+ kex->hash_alg,
+ kex->client_version,
+ kex->server_version,
+ kex->my,
+ kex->peer,
+ server_host_key_blob,
+ kex->client_pub,
+ server_blob,
+ shared_secret,
+ hash, &hashlen)) != 0)
+ goto out;
+
+ if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
+ kex->hostkey_alg, ssh->compat, NULL)) != 0)
+ goto out;
+
+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
+ r = kex_send_newkeys(ssh);
+out:
+ explicit_bzero(hash, sizeof(hash));
+ explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
+ explicit_bzero(kex->sntrup4591761_client_key,
+ sizeof(kex->sntrup4591761_client_key));
+ sshbuf_free(server_host_key_blob);
+ free(signature);
+ sshbuf_free(tmp);
+ sshkey_free(server_host_key);
+ sshbuf_free(server_blob);
+ sshbuf_free(shared_secret);
+ sshbuf_free(kex->client_pub);
+ kex->client_pub = NULL;
+ return r;
+}
+
+int
+kex_gen_server(struct ssh *ssh)
+{
+ debug("expecting SSH2_MSG_KEX_ECDH_INIT");
+ ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_gen_init);
+ return 0;
+}
+
+static int
+input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh)
+{
+ struct kex *kex = ssh->kex;
+ struct sshkey *server_host_private, *server_host_public;
+ struct sshbuf *shared_secret = NULL;
+ struct sshbuf *server_pubkey = NULL;
+ struct sshbuf *client_pubkey = NULL;
+ struct sshbuf *server_host_key_blob = NULL;
+ u_char *signature = NULL, hash[SSH_DIGEST_MAX_LENGTH];
+ size_t slen, hashlen;
+ int r;
+
+ if ((r = kex_load_hostkey(ssh, &server_host_private,
+ &server_host_public)) != 0)
+ goto out;
+
+ if ((r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ goto out;
+
+ /* compute shared secret */
+ switch (kex->kex_type) {
+#ifdef WITH_OPENSSL
+ case KEX_DH_GRP1_SHA1:
+ case KEX_DH_GRP14_SHA1:
+ case KEX_DH_GRP14_SHA256:
+ case KEX_DH_GRP16_SHA512:
+ case KEX_DH_GRP18_SHA512:
+ r = kex_dh_enc(kex, client_pubkey, &server_pubkey,
+ &shared_secret);
+ break;
+ case KEX_ECDH_SHA2:
+ r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey,
+ &shared_secret);
+ break;
+#endif
+ case KEX_C25519_SHA256:
+ r = kex_c25519_enc(kex, client_pubkey, &server_pubkey,
+ &shared_secret);
+ break;
+ case KEX_KEM_SNTRUP4591761X25519_SHA512:
+ r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey,
+ &server_pubkey, &shared_secret);
+ break;
+ default:
+ r = SSH_ERR_INVALID_ARGUMENT;
+ break;
+ }
+ if (r !=0 )
+ goto out;
+
+ /* calc H */
+ if ((server_host_key_blob = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshkey_putb(server_host_public, server_host_key_blob)) != 0)
+ goto out;
+ hashlen = sizeof(hash);
+ if ((r = kex_gen_hash(
+ kex->hash_alg,
+ kex->client_version,
+ kex->server_version,
+ kex->peer,
+ kex->my,
+ server_host_key_blob,
+ client_pubkey,
+ server_pubkey,
+ shared_secret,
+ hash, &hashlen)) != 0)
+ goto out;
+
+ /* sign H */
+ if ((r = kex->sign(ssh, server_host_private, server_host_public,
+ &signature, &slen, hash, hashlen, kex->hostkey_alg)) != 0)
+ goto out;
+
+ /* send server hostkey, ECDH pubkey 'Q_S' and signed H */
+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 ||
+ (r = sshpkt_put_stringb(ssh, server_host_key_blob)) != 0 ||
+ (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 ||
+ (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ goto out;
+
+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
+ r = kex_send_newkeys(ssh);
+out:
+ explicit_bzero(hash, sizeof(hash));
+ sshbuf_free(server_host_key_blob);
+ free(signature);
+ sshbuf_free(shared_secret);
+ sshbuf_free(client_pubkey);
+ sshbuf_free(server_pubkey);
+ return r;
+}
diff --git a/kexgex.c b/kexgex.c
index 8b0d8333..8040a132 100644
--- a/kexgex.c
+++ b/kexgex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgex.c,v 1.29 2015/01/19 20:16:15 markus Exp $ */
+/* $OpenBSD: kexgex.c,v 1.32 2019/01/23 00:30:41 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -33,6 +33,8 @@
#include <openssl/evp.h>
#include <signal.h>
+#include "openbsd-compat/openssl-compat.h"
+
#include "sshkey.h"
#include "cipher.h"
#include "kex.h"
@@ -44,17 +46,17 @@
int
kexgex_hash(
int hash_alg,
- const char *client_version_string,
- const char *server_version_string,
- const u_char *ckexinit, size_t ckexinitlen,
- const u_char *skexinit, size_t skexinitlen,
- const u_char *serverhostkeyblob, size_t sbloblen,
+ const struct sshbuf *client_version,
+ const struct sshbuf *server_version,
+ const struct sshbuf *client_kexinit,
+ const struct sshbuf *server_kexinit,
+ const struct sshbuf *server_host_key_blob,
int min, int wantbits, int max,
const BIGNUM *prime,
const BIGNUM *gen,
const BIGNUM *client_dh_pub,
const BIGNUM *server_dh_pub,
- const BIGNUM *shared_secret,
+ const u_char *shared_secret, size_t secretlen,
u_char *hash, size_t *hashlen)
{
struct sshbuf *b;
@@ -64,16 +66,16 @@ kexgex_hash(
return SSH_ERR_INVALID_ARGUMENT;
if ((b = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
- (r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
+ if ((r = sshbuf_put_stringb(b, client_version)) < 0 ||
+ (r = sshbuf_put_stringb(b, server_version)) < 0 ||
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
- (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
+ (r = sshbuf_put_u32(b, sshbuf_len(client_kexinit) + 1)) != 0 ||
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
- (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
- (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 ||
+ (r = sshbuf_putb(b, client_kexinit)) != 0 ||
+ (r = sshbuf_put_u32(b, sshbuf_len(server_kexinit) + 1)) != 0 ||
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
- (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
- (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
+ (r = sshbuf_putb(b, server_kexinit)) != 0 ||
+ (r = sshbuf_put_stringb(b, server_host_key_blob)) != 0 ||
(min != -1 && (r = sshbuf_put_u32(b, min)) != 0) ||
(r = sshbuf_put_u32(b, wantbits)) != 0 ||
(max != -1 && (r = sshbuf_put_u32(b, max)) != 0) ||
@@ -81,7 +83,7 @@ kexgex_hash(
(r = sshbuf_put_bignum2(b, gen)) != 0 ||
(r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 ||
(r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 ||
- (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
+ (r = sshbuf_put(b, shared_secret, secretlen)) != 0) {
sshbuf_free(b);
return r;
}
diff --git a/kexgexc.c b/kexgexc.c
index e8e059a8..323a659b 100644
--- a/kexgexc.c
+++ b/kexgexc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgexc.c,v 1.20 2015/01/26 06:10:03 djm Exp $ */
+/* $OpenBSD: kexgexc.c,v 1.35 2019/11/25 00:51:37 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -37,6 +37,8 @@
#include <string.h>
#include <signal.h>
+#include "openbsd-compat/openssl-compat.h"
+
#include "sshkey.h"
#include "cipher.h"
#include "digest.h"
@@ -49,9 +51,10 @@
#include "dispatch.h"
#include "ssherr.h"
#include "sshbuf.h"
+#include "misc.h"
-static int input_kex_dh_gex_group(int, u_int32_t, void *);
-static int input_kex_dh_gex_reply(int, u_int32_t, void *);
+static int input_kex_dh_gex_group(int, u_int32_t, struct ssh *);
+static int input_kex_dh_gex_reply(int, u_int32_t, struct ssh *);
int
kexgex_client(struct ssh *ssh)
@@ -65,25 +68,17 @@ kexgex_client(struct ssh *ssh)
kex->min = DH_GRP_MIN;
kex->max = DH_GRP_MAX;
kex->nbits = nbits;
- if (ssh->compat & SSH_OLD_DHGEX) {
- /* Old GEX request */
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST_OLD))
- != 0 ||
- (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- goto out;
- debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD(%u) sent", kex->nbits);
- } else {
- /* New GEX request */
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST)) != 0 ||
- (r = sshpkt_put_u32(ssh, kex->min)) != 0 ||
- (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 ||
- (r = sshpkt_put_u32(ssh, kex->max)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- goto out;
- debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent",
- kex->min, kex->nbits, kex->max);
- }
+ if (datafellows & SSH_BUG_DHGEX_LARGE)
+ kex->nbits = MINIMUM(kex->nbits, 4096);
+ /* New GEX request */
+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST)) != 0 ||
+ (r = sshpkt_put_u32(ssh, kex->min)) != 0 ||
+ (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 ||
+ (r = sshpkt_put_u32(ssh, kex->max)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ goto out;
+ debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent",
+ kex->min, kex->nbits, kex->max);
#ifdef DEBUG_KEXDH
fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",
kex->min, kex->nbits, kex->max);
@@ -96,22 +91,17 @@ kexgex_client(struct ssh *ssh)
}
static int
-input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt)
+input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh)
{
- struct ssh *ssh = ctxt;
struct kex *kex = ssh->kex;
BIGNUM *p = NULL, *g = NULL;
+ const BIGNUM *pub_key;
int r, bits;
debug("got SSH2_MSG_KEX_DH_GEX_GROUP");
- if ((p = BN_new()) == NULL ||
- (g = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshpkt_get_bignum2(ssh, p)) != 0 ||
- (r = sshpkt_get_bignum2(ssh, g)) != 0 ||
+ if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 ||
+ (r = sshpkt_get_bignum2(ssh, &g)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
goto out;
if ((bits = BN_num_bits(p)) < 0 ||
@@ -126,153 +116,103 @@ input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt)
p = g = NULL; /* belong to kex->dh now */
/* generate and send 'e', client DH public key */
- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 ||
- (r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 ||
- (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 ||
+ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
+ goto out;
+ DH_get0_key(kex->dh, &pub_key, NULL);
+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 ||
+ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
goto out;
debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
#ifdef DEBUG_KEXDH
DHparams_print_fp(stderr, kex->dh);
fprintf(stderr, "pub= ");
- BN_print_fp(stderr, kex->dh->pub_key);
+ BN_print_fp(stderr, pub_key);
fprintf(stderr, "\n");
#endif
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, NULL);
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply);
r = 0;
out:
- if (p)
- BN_clear_free(p);
- if (g)
- BN_clear_free(g);
+ BN_clear_free(p);
+ BN_clear_free(g);
return r;
}
static int
-input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt)
+input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
{
- struct ssh *ssh = ctxt;
struct kex *kex = ssh->kex;
- BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
+ BIGNUM *dh_server_pub = NULL;
+ const BIGNUM *pub_key, *dh_p, *dh_g;
+ struct sshbuf *shared_secret = NULL;
+ struct sshbuf *tmp = NULL, *server_host_key_blob = NULL;
struct sshkey *server_host_key = NULL;
- u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL;
+ u_char *signature = NULL;
u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t klen = 0, slen, sbloblen, hashlen;
- int kout, r;
+ size_t slen, hashlen;
+ int r;
debug("got SSH2_MSG_KEX_DH_GEX_REPLY");
- if (kex->verify_host_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
/* key, cert */
- if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
- &sbloblen)) != 0 ||
- (r = sshkey_from_blob(server_host_key_blob, sbloblen,
- &server_host_key)) != 0)
+ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
goto out;
- if (server_host_key->type != kex->hostkey_type) {
- r = SSH_ERR_KEY_TYPE_MISMATCH;
- goto out;
- }
- if (server_host_key->type != kex->hostkey_type ||
- (kex->hostkey_type == KEY_ECDSA &&
- server_host_key->ecdsa_nid != kex->hostkey_nid)) {
- r = SSH_ERR_KEY_TYPE_MISMATCH;
- goto out;
- }
- if (kex->verify_host_key(server_host_key, ssh) == -1) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
- /* DH parameter f, server public DH key */
- if ((dh_server_pub = BN_new()) == NULL) {
+ /* sshkey_fromb() consumes its buffer, so make a copy */
+ if ((tmp = sshbuf_fromb(server_host_key_blob)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- /* signed H */
- if ((r = sshpkt_get_bignum2(ssh, dh_server_pub)) != 0 ||
+ if ((r = sshkey_fromb(tmp, &server_host_key)) != 0 ||
+ (r = kex_verify_host_key(ssh, server_host_key)) != 0)
+ goto out;
+ /* DH parameter f, server public DH key, signed H */
+ if ((r = sshpkt_get_bignum2(ssh, &dh_server_pub)) != 0 ||
(r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
goto out;
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "dh_server_pub= ");
- BN_print_fp(stderr, dh_server_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
- if (!dh_pub_is_valid(kex->dh, dh_server_pub)) {
- sshpkt_disconnect(ssh, "bad server public DH value");
- r = SSH_ERR_MESSAGE_INCOMPLETE;
- goto out;
- }
-
- klen = DH_size(kex->dh);
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
+ if ((shared_secret = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 ||
- BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
+ if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0)
goto out;
- }
-#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
-#endif
if (ssh->compat & SSH_OLD_DHGEX)
kex->min = kex->max = -1;
/* calc and verify H */
+ DH_get0_key(kex->dh, &pub_key, NULL);
+ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
hashlen = sizeof(hash);
if ((r = kexgex_hash(
kex->hash_alg,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- server_host_key_blob, sbloblen,
+ kex->client_version,
+ kex->server_version,
+ kex->my,
+ kex->peer,
+ server_host_key_blob,
kex->min, kex->nbits, kex->max,
- kex->dh->p, kex->dh->g,
- kex->dh->pub_key,
+ dh_p, dh_g,
+ pub_key,
dh_server_pub,
- shared_secret,
+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
hash, &hashlen)) != 0)
goto out;
if ((r = sshkey_verify(server_host_key, signature, slen, hash,
- hashlen, ssh->compat)) != 0)
+ hashlen, kex->hostkey_alg, ssh->compat, NULL)) != 0)
goto out;
- /* save session id */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
r = kex_send_newkeys(ssh);
out:
explicit_bzero(hash, sizeof(hash));
DH_free(kex->dh);
kex->dh = NULL;
- if (dh_server_pub)
- BN_clear_free(dh_server_pub);
- if (kbuf) {
- explicit_bzero(kbuf, klen);
- free(kbuf);
- }
- if (shared_secret)
- BN_clear_free(shared_secret);
+ BN_clear_free(dh_server_pub);
+ sshbuf_free(shared_secret);
sshkey_free(server_host_key);
- free(server_host_key_blob);
+ sshbuf_free(tmp);
+ sshbuf_free(server_host_key_blob);
free(signature);
return r;
}
diff --git a/kexgexs.c b/kexgexs.c
index 9c281d28..8ee3aacc 100644
--- a/kexgexs.c
+++ b/kexgexs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgexs.c,v 1.24 2015/01/26 06:10:03 djm Exp $ */
+/* $OpenBSD: kexgexs.c,v 1.42 2019/01/23 00:30:41 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -28,7 +28,6 @@
#ifdef WITH_OPENSSL
-#include <sys/param.h> /* MIN MAX */
#include <stdarg.h>
#include <stdio.h>
@@ -37,6 +36,8 @@
#include <openssl/dh.h>
+#include "openbsd-compat/openssl-compat.h"
+
#include "sshkey.h"
#include "cipher.h"
#include "digest.h"
@@ -53,15 +54,14 @@
#include "dispatch.h"
#include "ssherr.h"
#include "sshbuf.h"
+#include "misc.h"
-static int input_kex_dh_gex_request(int, u_int32_t, void *);
-static int input_kex_dh_gex_init(int, u_int32_t, void *);
+static int input_kex_dh_gex_request(int, u_int32_t, struct ssh *);
+static int input_kex_dh_gex_init(int, u_int32_t, struct ssh *);
int
kexgex_server(struct ssh *ssh)
{
- ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST_OLD,
- &input_kex_dh_gex_request);
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST,
&input_kex_dh_gex_request);
debug("expecting SSH2_MSG_KEX_DH_GEX_REQUEST");
@@ -69,46 +69,29 @@ kexgex_server(struct ssh *ssh)
}
static int
-input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt)
+input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh)
{
- struct ssh *ssh = ctxt;
struct kex *kex = ssh->kex;
int r;
u_int min = 0, max = 0, nbits = 0;
+ const BIGNUM *dh_p, *dh_g;
- switch (type) {
- case SSH2_MSG_KEX_DH_GEX_REQUEST:
- debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
- if ((r = sshpkt_get_u32(ssh, &min)) != 0 ||
- (r = sshpkt_get_u32(ssh, &nbits)) != 0 ||
- (r = sshpkt_get_u32(ssh, &max)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
- kex->nbits = nbits;
- kex->min = min;
- kex->max = max;
- min = MAX(DH_GRP_MIN, min);
- max = MIN(DH_GRP_MAX, max);
- nbits = MAX(DH_GRP_MIN, nbits);
- nbits = MIN(DH_GRP_MAX, nbits);
- break;
- case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD:
- debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received");
- if ((r = sshpkt_get_u32(ssh, &nbits)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
- kex->nbits = nbits;
- /* unused for old GEX */
- kex->min = min = DH_GRP_MIN;
- kex->max = max = DH_GRP_MAX;
- break;
- default:
- r = SSH_ERR_INVALID_ARGUMENT;
+ debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
+ if ((r = sshpkt_get_u32(ssh, &min)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &nbits)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &max)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
goto out;
- }
+ kex->nbits = nbits;
+ kex->min = min;
+ kex->max = max;
+ min = MAXIMUM(DH_GRP_MIN, min);
+ max = MINIMUM(DH_GRP_MAX, max);
+ nbits = MAXIMUM(DH_GRP_MIN, nbits);
+ nbits = MINIMUM(DH_GRP_MAX, nbits);
if (kex->max < kex->min || kex->nbits < kex->min ||
- kex->max < kex->nbits) {
+ kex->max < kex->nbits || kex->max < DH_GRP_MIN) {
r = SSH_ERR_DH_GEX_OUT_OF_RANGE;
goto out;
}
@@ -121,9 +104,10 @@ input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt)
goto out;
}
debug("SSH2_MSG_KEX_DH_GEX_GROUP sent");
+ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP)) != 0 ||
- (r = sshpkt_put_bignum2(ssh, kex->dh->p)) != 0 ||
- (r = sshpkt_put_bignum2(ssh, kex->dh->g)) != 0 ||
+ (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 ||
+ (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
goto out;
@@ -131,10 +115,6 @@ input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt)
if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
goto out;
- /* old KEX does not use min/max in kexgex_hash() */
- if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD)
- kex->min = kex->max = -1;
-
debug("expecting SSH2_MSG_KEX_DH_GEX_INIT");
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &input_kex_dh_gex_init);
r = 0;
@@ -143,134 +123,81 @@ input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt)
}
static int
-input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt)
+input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
{
- struct ssh *ssh = ctxt;
struct kex *kex = ssh->kex;
- BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
+ BIGNUM *dh_client_pub = NULL;
+ const BIGNUM *pub_key, *dh_p, *dh_g;
+ struct sshbuf *shared_secret = NULL;
+ struct sshbuf *server_host_key_blob = NULL;
struct sshkey *server_host_public, *server_host_private;
- u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL;
+ u_char *signature = NULL;
u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t sbloblen, slen;
- size_t klen = 0, hashlen;
- int kout, r;
+ size_t slen, hashlen;
+ int r;
- if (kex->load_host_public_key == NULL ||
- kex->load_host_private_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- server_host_public = kex->load_host_public_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- server_host_private = kex->load_host_private_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- if (server_host_public == NULL) {
- r = SSH_ERR_NO_HOSTKEY_LOADED;
+ if ((r = kex_load_hostkey(ssh, &server_host_private,
+ &server_host_public)) != 0)
goto out;
- }
/* key, cert */
- if ((dh_client_pub = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshpkt_get_bignum2(ssh, dh_client_pub)) != 0 ||
+ if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
goto out;
-
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "dh_client_pub= ");
- BN_print_fp(stderr, dh_client_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_client_pub));
-#endif
-
-#ifdef DEBUG_KEXDH
- DHparams_print_fp(stderr, kex->dh);
- fprintf(stderr, "pub= ");
- BN_print_fp(stderr, kex->dh->pub_key);
- fprintf(stderr, "\n");
-#endif
- if (!dh_pub_is_valid(kex->dh, dh_client_pub)) {
- sshpkt_disconnect(ssh, "bad client public DH value");
- r = SSH_ERR_MESSAGE_INCOMPLETE;
+ if ((shared_secret = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
goto out;
}
-
- klen = DH_size(kex->dh);
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
+ if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0)
+ goto out;
+ if ((server_host_key_blob = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 ||
- BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
-#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
-#endif
- if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
- &sbloblen)) != 0)
+ if ((r = sshkey_putb(server_host_public, server_host_key_blob)) != 0)
goto out;
+
/* calc H */
+ DH_get0_key(kex->dh, &pub_key, NULL);
+ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
hashlen = sizeof(hash);
if ((r = kexgex_hash(
kex->hash_alg,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- server_host_key_blob, sbloblen,
+ kex->client_version,
+ kex->server_version,
+ kex->peer,
+ kex->my,
+ server_host_key_blob,
kex->min, kex->nbits, kex->max,
- kex->dh->p, kex->dh->g,
+ dh_p, dh_g,
dh_client_pub,
- kex->dh->pub_key,
- shared_secret,
+ pub_key,
+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
hash, &hashlen)) != 0)
goto out;
- /* save session id := H */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
/* sign H */
- if ((r = kex->sign(server_host_private, server_host_public,
- &signature, &slen, hash, hashlen, ssh->compat)) < 0)
+ if ((r = kex->sign(ssh, server_host_private, server_host_public,
+ &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0)
goto out;
- /* destroy_sensitive_data(); */
-
- /* send server hostkey, DH pubkey 'f' and singed H */
+ /* send server hostkey, DH pubkey 'f' and signed H */
if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 ||
- (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
- (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */
+ (r = sshpkt_put_stringb(ssh, server_host_key_blob)) != 0 ||
+ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */
(r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
goto out;
- if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
r = kex_send_newkeys(ssh);
out:
+ explicit_bzero(hash, sizeof(hash));
DH_free(kex->dh);
kex->dh = NULL;
- if (dh_client_pub)
- BN_clear_free(dh_client_pub);
- if (kbuf) {
- explicit_bzero(kbuf, klen);
- free(kbuf);
- }
- if (shared_secret)
- BN_clear_free(shared_secret);
- free(server_host_key_blob);
+ BN_clear_free(dh_client_pub);
+ sshbuf_free(shared_secret);
+ sshbuf_free(server_host_key_blob);
free(signature);
return r;
}
diff --git a/kexsntrup4591761x25519.c b/kexsntrup4591761x25519.c
new file mode 100644
index 00000000..3b9b664f
--- /dev/null
+++ b/kexsntrup4591761x25519.c
@@ -0,0 +1,219 @@
+/* $OpenBSD: kexsntrup4591761x25519.c,v 1.3 2019/01/21 10:40:11 djm Exp $ */
+/*
+ * Copyright (c) 2019 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include "sshkey.h"
+#include "kex.h"
+#include "sshbuf.h"
+#include "digest.h"
+#include "ssherr.h"
+
+int
+kex_kem_sntrup4591761x25519_keypair(struct kex *kex)
+{
+ struct sshbuf *buf = NULL;
+ u_char *cp = NULL;
+ size_t need;
+ int r;
+
+ if ((buf = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE;
+ if ((r = sshbuf_reserve(buf, need, &cp)) != 0)
+ goto out;
+ crypto_kem_sntrup4591761_keypair(cp, kex->sntrup4591761_client_key);
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key sntrup4591761:", cp,
+ crypto_kem_sntrup4591761_PUBLICKEYBYTES);
+#endif
+ cp += crypto_kem_sntrup4591761_PUBLICKEYBYTES;
+ kexc25519_keygen(kex->c25519_client_key, cp);
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key c25519:", cp, CURVE25519_SIZE);
+#endif
+ kex->client_pub = buf;
+ buf = NULL;
+ out:
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_kem_sntrup4591761x25519_enc(struct kex *kex,
+ const struct sshbuf *client_blob, struct sshbuf **server_blobp,
+ struct sshbuf **shared_secretp)
+{
+ struct sshbuf *server_blob = NULL;
+ struct sshbuf *buf = NULL;
+ const u_char *client_pub;
+ u_char *kem_key, *ciphertext, *server_pub;
+ u_char server_key[CURVE25519_SIZE];
+ u_char hash[SSH_DIGEST_MAX_LENGTH];
+ size_t need;
+ int r;
+
+ *server_blobp = NULL;
+ *shared_secretp = NULL;
+
+ /* client_blob contains both KEM and ECDH client pubkeys */
+ need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE;
+ if (sshbuf_len(client_blob) != need) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ client_pub = sshbuf_ptr(client_blob);
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key sntrup4591761:", client_pub,
+ crypto_kem_sntrup4591761_PUBLICKEYBYTES);
+ dump_digest("client public key 25519:",
+ client_pub + crypto_kem_sntrup4591761_PUBLICKEYBYTES,
+ CURVE25519_SIZE);
+#endif
+ /* allocate buffer for concatenation of KEM key and ECDH shared key */
+ /* the buffer will be hashed and the result is the shared secret */
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES,
+ &kem_key)) != 0)
+ goto out;
+ /* allocate space for encrypted KEM key and ECDH pub key */
+ if ((server_blob = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE;
+ if ((r = sshbuf_reserve(server_blob, need, &ciphertext)) != 0)
+ goto out;
+ /* generate and encrypt KEM key with client key */
+ crypto_kem_sntrup4591761_enc(ciphertext, kem_key, client_pub);
+ /* generate ECDH key pair, store server pubkey after ciphertext */
+ server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES;
+ kexc25519_keygen(server_key, server_pub);
+ /* append ECDH shared key */
+ client_pub += crypto_kem_sntrup4591761_PUBLICKEYBYTES;
+ if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 1)) < 0)
+ goto out;
+ if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
+ dump_digest("server cipher text:", ciphertext,
+ crypto_kem_sntrup4591761_CIPHERTEXTBYTES);
+ dump_digest("server kem key:", kem_key, sizeof(kem_key));
+ dump_digest("concatenation of KEM key and ECDH shared key:",
+ sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ /* string-encoded hash is resulting shared secret */
+ sshbuf_reset(buf);
+ if ((r = sshbuf_put_string(buf, hash,
+ ssh_digest_bytes(kex->hash_alg))) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ *server_blobp = server_blob;
+ *shared_secretp = buf;
+ server_blob = NULL;
+ buf = NULL;
+ out:
+ explicit_bzero(hash, sizeof(hash));
+ explicit_bzero(server_key, sizeof(server_key));
+ sshbuf_free(server_blob);
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_kem_sntrup4591761x25519_dec(struct kex *kex,
+ const struct sshbuf *server_blob, struct sshbuf **shared_secretp)
+{
+ struct sshbuf *buf = NULL;
+ u_char *kem_key = NULL;
+ const u_char *ciphertext, *server_pub;
+ u_char hash[SSH_DIGEST_MAX_LENGTH];
+ size_t need;
+ int r, decoded;
+
+ *shared_secretp = NULL;
+
+ need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE;
+ if (sshbuf_len(server_blob) != need) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ ciphertext = sshbuf_ptr(server_blob);
+ server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES;
+#ifdef DEBUG_KEXECDH
+ dump_digest("server cipher text:", ciphertext,
+ crypto_kem_sntrup4591761_CIPHERTEXTBYTES);
+ dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
+#endif
+ /* hash concatenation of KEM key and ECDH shared key */
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES,
+ &kem_key)) != 0)
+ goto out;
+ decoded = crypto_kem_sntrup4591761_dec(kem_key, ciphertext,
+ kex->sntrup4591761_client_key);
+ if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
+ buf, 1)) < 0)
+ goto out;
+ if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("client kem key:", kem_key, sizeof(kem_key));
+ dump_digest("concatenation of KEM key and ECDH shared key:",
+ sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ sshbuf_reset(buf);
+ if ((r = sshbuf_put_string(buf, hash,
+ ssh_digest_bytes(kex->hash_alg))) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ if (decoded != 0) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ *shared_secretp = buf;
+ buf = NULL;
+ out:
+ explicit_bzero(hash, sizeof(hash));
+ sshbuf_free(buf);
+ return r;
+}
diff --git a/key.c b/key.c
deleted file mode 100644
index bbe027b6..00000000
--- a/key.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/* $OpenBSD: key.c,v 1.127 2015/01/28 22:36:00 djm Exp $ */
-/*
- * placed in the public domain
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <limits.h>
-
-#define SSH_KEY_NO_DEFINE
-#include "key.h"
-
-#include "compat.h"
-#include "sshkey.h"
-#include "ssherr.h"
-#include "log.h"
-#include "authfile.h"
-
-void
-key_add_private(Key *k)
-{
- int r;
-
- if ((r = sshkey_add_private(k)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-Key *
-key_new_private(int type)
-{
- Key *ret = NULL;
-
- if ((ret = sshkey_new_private(type)) == NULL)
- fatal("%s: failed", __func__);
- return ret;
-}
-
-int
-key_read(Key *ret, char **cpp)
-{
- return sshkey_read(ret, cpp) == 0 ? 1 : -1;
-}
-
-int
-key_write(const Key *key, FILE *f)
-{
- return sshkey_write(key, f) == 0 ? 1 : 0;
-}
-
-Key *
-key_generate(int type, u_int bits)
-{
- int r;
- Key *ret = NULL;
-
- if ((r = sshkey_generate(type, bits, &ret)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- return ret;
-}
-
-void
-key_cert_copy(const Key *from_key, Key *to_key)
-{
- int r;
-
- if ((r = sshkey_cert_copy(from_key, to_key)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-Key *
-key_from_private(const Key *k)
-{
- int r;
- Key *ret = NULL;
-
- if ((r = sshkey_from_private(k, &ret)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- return ret;
-}
-
-static void
-fatal_on_fatal_errors(int r, const char *func, int extra_fatal)
-{
- if (r == SSH_ERR_INTERNAL_ERROR ||
- r == SSH_ERR_ALLOC_FAIL ||
- (extra_fatal != 0 && r == extra_fatal))
- fatal("%s: %s", func, ssh_err(r));
-}
-
-Key *
-key_from_blob(const u_char *blob, u_int blen)
-{
- int r;
- Key *ret = NULL;
-
- if ((r = sshkey_from_blob(blob, blen, &ret)) != 0) {
- fatal_on_fatal_errors(r, __func__, 0);
- error("%s: %s", __func__, ssh_err(r));
- return NULL;
- }
- return ret;
-}
-
-int
-key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
-{
- u_char *blob;
- size_t blen;
- int r;
-
- if (blobp != NULL)
- *blobp = NULL;
- if (lenp != NULL)
- *lenp = 0;
- if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
- fatal_on_fatal_errors(r, __func__, 0);
- error("%s: %s", __func__, ssh_err(r));
- return 0;
- }
- if (blen > INT_MAX)
- fatal("%s: giant len %zu", __func__, blen);
- if (blobp != NULL)
- *blobp = blob;
- if (lenp != NULL)
- *lenp = blen;
- return blen;
-}
-
-int
-key_sign(const Key *key, u_char **sigp, u_int *lenp,
- const u_char *data, u_int datalen)
-{
- int r;
- u_char *sig;
- size_t siglen;
-
- if (sigp != NULL)
- *sigp = NULL;
- if (lenp != NULL)
- *lenp = 0;
- if ((r = sshkey_sign(key, &sig, &siglen,
- data, datalen, datafellows)) != 0) {
- fatal_on_fatal_errors(r, __func__, 0);
- error("%s: %s", __func__, ssh_err(r));
- return -1;
- }
- if (siglen > INT_MAX)
- fatal("%s: giant len %zu", __func__, siglen);
- if (sigp != NULL)
- *sigp = sig;
- if (lenp != NULL)
- *lenp = siglen;
- return 0;
-}
-
-int
-key_verify(const Key *key, const u_char *signature, u_int signaturelen,
- const u_char *data, u_int datalen)
-{
- int r;
-
- if ((r = sshkey_verify(key, signature, signaturelen,
- data, datalen, datafellows)) != 0) {
- fatal_on_fatal_errors(r, __func__, 0);
- error("%s: %s", __func__, ssh_err(r));
- return r == SSH_ERR_SIGNATURE_INVALID ? 0 : -1;
- }
- return 1;
-}
-
-Key *
-key_demote(const Key *k)
-{
- int r;
- Key *ret = NULL;
-
- if ((r = sshkey_demote(k, &ret)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- return ret;
-}
-
-int
-key_to_certified(Key *k, int legacy)
-{
- int r;
-
- if ((r = sshkey_to_certified(k, legacy)) != 0) {
- fatal_on_fatal_errors(r, __func__, 0);
- error("%s: %s", __func__, ssh_err(r));
- return -1;
- }
- return 0;
-}
-
-int
-key_drop_cert(Key *k)
-{
- int r;
-
- if ((r = sshkey_drop_cert(k)) != 0) {
- fatal_on_fatal_errors(r, __func__, 0);
- error("%s: %s", __func__, ssh_err(r));
- return -1;
- }
- return 0;
-}
-
-int
-key_certify(Key *k, Key *ca)
-{
- int r;
-
- if ((r = sshkey_certify(k, ca)) != 0) {
- fatal_on_fatal_errors(r, __func__, 0);
- error("%s: %s", __func__, ssh_err(r));
- return -1;
- }
- return 0;
-}
-
-int
-key_cert_check_authority(const Key *k, int want_host, int require_principal,
- const char *name, const char **reason)
-{
- int r;
-
- if ((r = sshkey_cert_check_authority(k, want_host, require_principal,
- name, reason)) != 0) {
- fatal_on_fatal_errors(r, __func__, 0);
- error("%s: %s", __func__, ssh_err(r));
- return -1;
- }
- return 0;
-}
-
-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
-int
-key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
-{
- int r;
-
- if ((r = sshkey_ec_validate_public(group, public)) != 0) {
- fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
- error("%s: %s", __func__, ssh_err(r));
- return -1;
- }
- return 0;
-}
-
-int
-key_ec_validate_private(const EC_KEY *key)
-{
- int r;
-
- if ((r = sshkey_ec_validate_private(key)) != 0) {
- fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
- error("%s: %s", __func__, ssh_err(r));
- return -1;
- }
- return 0;
-}
-#endif /* WITH_OPENSSL */
-
-void
-key_private_serialize(const Key *key, struct sshbuf *b)
-{
- int r;
-
- if ((r = sshkey_private_serialize(key, b)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-Key *
-key_private_deserialize(struct sshbuf *blob)
-{
- int r;
- Key *ret = NULL;
-
- if ((r = sshkey_private_deserialize(blob, &ret)) != 0) {
- fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
- error("%s: %s", __func__, ssh_err(r));
- return NULL;
- }
- return ret;
-}
-
-/* authfile.c */
-
-int
-key_save_private(Key *key, const char *filename, const char *passphrase,
- const char *comment, int force_new_format, const char *new_format_cipher,
- int new_format_rounds)
-{
- int r;
-
- if ((r = sshkey_save_private(key, filename, passphrase, comment,
- force_new_format, new_format_cipher, new_format_rounds)) != 0) {
- fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
- error("%s: %s", __func__, ssh_err(r));
- return 0;
- }
- return 1;
-}
-
-int
-key_load_file(int fd, const char *filename, struct sshbuf *blob)
-{
- int r;
-
- if ((r = sshkey_load_file(fd, blob)) != 0) {
- fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
- error("%s: %s", __func__, ssh_err(r));
- return 0;
- }
- return 1;
-}
-
-Key *
-key_load_cert(const char *filename)
-{
- int r;
- Key *ret = NULL;
-
- if ((r = sshkey_load_cert(filename, &ret)) != 0) {
- fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
- /* Old authfile.c ignored all file errors. */
- if (r == SSH_ERR_SYSTEM_ERROR)
- debug("%s: %s", __func__, ssh_err(r));
- else
- error("%s: %s", __func__, ssh_err(r));
- return NULL;
- }
- return ret;
-
-}
-
-Key *
-key_load_public(const char *filename, char **commentp)
-{
- int r;
- Key *ret = NULL;
-
- if ((r = sshkey_load_public(filename, &ret, commentp)) != 0) {
- fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
- /* Old authfile.c ignored all file errors. */
- if (r == SSH_ERR_SYSTEM_ERROR)
- debug("%s: %s", __func__, ssh_err(r));
- else
- error("%s: %s", __func__, ssh_err(r));
- return NULL;
- }
- return ret;
-}
-
-Key *
-key_load_private(const char *path, const char *passphrase,
- char **commentp)
-{
- int r;
- Key *ret = NULL;
-
- if ((r = sshkey_load_private(path, passphrase, &ret, commentp)) != 0) {
- fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
- /* Old authfile.c ignored all file errors. */
- if (r == SSH_ERR_SYSTEM_ERROR ||
- r == SSH_ERR_KEY_WRONG_PASSPHRASE)
- debug("%s: %s", __func__, ssh_err(r));
- else
- error("%s: %s", __func__, ssh_err(r));
- return NULL;
- }
- return ret;
-}
-
-Key *
-key_load_private_cert(int type, const char *filename, const char *passphrase,
- int *perm_ok)
-{
- int r;
- Key *ret = NULL;
-
- if ((r = sshkey_load_private_cert(type, filename, passphrase,
- &ret, perm_ok)) != 0) {
- fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
- /* Old authfile.c ignored all file errors. */
- if (r == SSH_ERR_SYSTEM_ERROR ||
- r == SSH_ERR_KEY_WRONG_PASSPHRASE)
- debug("%s: %s", __func__, ssh_err(r));
- else
- error("%s: %s", __func__, ssh_err(r));
- return NULL;
- }
- return ret;
-}
-
-Key *
-key_load_private_type(int type, const char *filename, const char *passphrase,
- char **commentp, int *perm_ok)
-{
- int r;
- Key *ret = NULL;
-
- if ((r = sshkey_load_private_type(type, filename, passphrase,
- &ret, commentp, perm_ok)) != 0) {
- fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
- /* Old authfile.c ignored all file errors. */
- if (r == SSH_ERR_SYSTEM_ERROR ||
- (r == SSH_ERR_KEY_WRONG_PASSPHRASE))
- debug("%s: %s", __func__, ssh_err(r));
- else
- error("%s: %s", __func__, ssh_err(r));
- return NULL;
- }
- return ret;
-}
-
-int
-key_perm_ok(int fd, const char *filename)
-{
- return sshkey_perm_ok(fd, filename) == 0 ? 1 : 0;
-}
-
diff --git a/key.h b/key.h
deleted file mode 100644
index 89fd5cfd..00000000
--- a/key.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* $OpenBSD: key.h,v 1.47 2015/01/28 22:36:00 djm Exp $ */
-
-/*
- * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef KEY_H
-#define KEY_H
-
-#include "sshkey.h"
-
-typedef struct sshkey Key;
-
-#define types sshkey_types
-#define fp_type sshkey_fp_type
-#define fp_rep sshkey_fp_rep
-
-#ifndef SSH_KEY_NO_DEFINE
-#define key_new sshkey_new
-#define key_free sshkey_free
-#define key_equal_public sshkey_equal_public
-#define key_equal sshkey_equal
-#define key_type sshkey_type
-#define key_cert_type sshkey_cert_type
-#define key_ssh_name sshkey_ssh_name
-#define key_ssh_name_plain sshkey_ssh_name_plain
-#define key_type_from_name sshkey_type_from_name
-#define key_ecdsa_nid_from_name sshkey_ecdsa_nid_from_name
-#define key_type_is_cert sshkey_type_is_cert
-#define key_size sshkey_size
-#define key_ecdsa_bits_to_nid sshkey_ecdsa_bits_to_nid
-#define key_ecdsa_key_to_nid sshkey_ecdsa_key_to_nid
-#define key_is_cert sshkey_is_cert
-#define key_type_plain sshkey_type_plain
-#define key_cert_is_legacy sshkey_cert_is_legacy
-#define key_curve_name_to_nid sshkey_curve_name_to_nid
-#define key_curve_nid_to_bits sshkey_curve_nid_to_bits
-#define key_curve_nid_to_name sshkey_curve_nid_to_name
-#define key_ec_nid_to_hash_alg sshkey_ec_nid_to_hash_alg
-#define key_dump_ec_point sshkey_dump_ec_point
-#define key_dump_ec_key sshkey_dump_ec_key
-#endif
-
-void key_add_private(Key *);
-Key *key_new_private(int);
-void key_free(Key *);
-Key *key_demote(const Key *);
-int key_write(const Key *, FILE *);
-int key_read(Key *, char **);
-
-Key *key_generate(int, u_int);
-Key *key_from_private(const Key *);
-int key_to_certified(Key *, int);
-int key_drop_cert(Key *);
-int key_certify(Key *, Key *);
-void key_cert_copy(const Key *, Key *);
-int key_cert_check_authority(const Key *, int, int, const char *,
- const char **);
-char *key_alg_list(int, int);
-
-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
-int key_ec_validate_public(const EC_GROUP *, const EC_POINT *);
-int key_ec_validate_private(const EC_KEY *);
-#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
-
-Key *key_from_blob(const u_char *, u_int);
-int key_to_blob(const Key *, u_char **, u_int *);
-
-int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
-int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
-
-void key_private_serialize(const Key *, struct sshbuf *);
-Key *key_private_deserialize(struct sshbuf *);
-
-/* authfile.c */
-int key_save_private(Key *, const char *, const char *, const char *,
- int, const char *, int);
-int key_load_file(int, const char *, struct sshbuf *);
-Key *key_load_cert(const char *);
-Key *key_load_public(const char *, char **);
-Key *key_load_private(const char *, const char *, char **);
-Key *key_load_private_cert(int, const char *, const char *, int *);
-Key *key_load_private_type(int, const char *, const char *, char **, int *);
-int key_perm_ok(int, const char *);
-
-#endif
diff --git a/krl.c b/krl.c
index 4bbaa208..c431f704 100644
--- a/krl.c
+++ b/krl.c
@@ -14,11 +14,10 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $OpenBSD: krl.c,v 1.31 2015/01/30 01:10:33 djm Exp $ */
+/* $OpenBSD: krl.c,v 1.50 2020/04/03 05:48:57 djm Exp $ */
#include "includes.h"
-#include <sys/param.h> /* MIN */
#include <sys/types.h>
#include <openbsd-compat/sys-tree.h>
#include <openbsd-compat/sys-queue.h>
@@ -26,6 +25,7 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
+#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
@@ -38,6 +38,7 @@
#include "log.h"
#include "digest.h"
#include "bitmap.h"
+#include "utf8.h"
#include "krl.h"
@@ -97,6 +98,7 @@ struct ssh_krl {
char *comment;
struct revoked_blob_tree revoked_keys;
struct revoked_blob_tree revoked_sha1s;
+ struct revoked_blob_tree revoked_sha256s;
struct revoked_certs_list revoked_certs;
};
@@ -121,7 +123,7 @@ blob_cmp(struct revoked_blob *a, struct revoked_blob *b)
int r;
if (a->len != b->len) {
- if ((r = memcmp(a->blob, b->blob, MIN(a->len, b->len))) != 0)
+ if ((r = memcmp(a->blob, b->blob, MINIMUM(a->len, b->len))) != 0)
return r;
return a->len > b->len ? 1 : -1;
} else
@@ -137,6 +139,7 @@ ssh_krl_init(void)
return NULL;
RB_INIT(&krl->revoked_keys);
RB_INIT(&krl->revoked_sha1s);
+ RB_INIT(&krl->revoked_sha256s);
TAILQ_INIT(&krl->revoked_certs);
return krl;
}
@@ -179,6 +182,11 @@ ssh_krl_free(struct ssh_krl *krl)
free(rb->blob);
free(rb);
}
+ RB_FOREACH_SAFE(rb, revoked_blob_tree, &krl->revoked_sha256s, trb) {
+ RB_REMOVE(revoked_blob_tree, &krl->revoked_sha256s, rb);
+ free(rb->blob);
+ free(rb);
+ }
TAILQ_FOREACH_SAFE(rc, &krl->revoked_certs, entry, trc) {
TAILQ_REMOVE(&krl->revoked_certs, rc, entry);
revoked_certs_free(rc);
@@ -409,27 +417,49 @@ ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key)
return revoke_blob(&krl->revoked_keys, blob, len);
}
-int
-ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key)
+static int
+revoke_by_hash(struct revoked_blob_tree *target, const u_char *p, size_t len)
{
u_char *blob;
- size_t len;
int r;
- debug3("%s: revoke type %s by sha1", __func__, sshkey_type(key));
- if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1,
- &blob, &len)) != 0)
+ /* need to copy hash, as revoke_blob steals ownership */
+ if ((blob = malloc(len)) == NULL)
+ return SSH_ERR_SYSTEM_ERROR;
+ memcpy(blob, p, len);
+ if ((r = revoke_blob(target, blob, len)) != 0) {
+ free(blob);
return r;
- return revoke_blob(&krl->revoked_sha1s, blob, len);
+ }
+ return 0;
+}
+
+int
+ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const u_char *p, size_t len)
+{
+ debug3("%s: revoke by sha1", __func__);
+ if (len != 20)
+ return SSH_ERR_INVALID_FORMAT;
+ return revoke_by_hash(&krl->revoked_sha1s, p, len);
+}
+
+int
+ssh_krl_revoke_key_sha256(struct ssh_krl *krl, const u_char *p, size_t len)
+{
+ debug3("%s: revoke by sha256", __func__);
+ if (len != 32)
+ return SSH_ERR_INVALID_FORMAT;
+ return revoke_by_hash(&krl->revoked_sha256s, p, len);
}
int
ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key)
{
+ /* XXX replace with SHA256? */
if (!sshkey_is_cert(key))
- return ssh_krl_revoke_key_sha1(krl, key);
+ return ssh_krl_revoke_key_explicit(krl, key);
- if (sshkey_cert_is_legacy(key) || key->cert->serial == 0) {
+ if (key->cert->serial == 0) {
return ssh_krl_revoke_cert_by_key_id(krl,
key->cert->signature_key,
key->cert->key_id);
@@ -458,9 +488,9 @@ choose_next_state(int current_state, u_int64_t contig, int final,
* Avoid unsigned overflows.
* The limits are high enough to avoid confusing the calculations.
*/
- contig = MIN(contig, 1ULL<<31);
- last_gap = MIN(last_gap, 1ULL<<31);
- next_gap = MIN(next_gap, 1ULL<<31);
+ contig = MINIMUM(contig, 1ULL<<31);
+ last_gap = MINIMUM(last_gap, 1ULL<<31);
+ next_gap = MINIMUM(next_gap, 1ULL<<31);
/*
* Calculate the cost to switch from the current state to candidates.
@@ -486,8 +516,8 @@ choose_next_state(int current_state, u_int64_t contig, int final,
/* Estimate base cost in bits of each section type */
cost_list += 64 * contig + (final ? 0 : 8+64);
cost_range += (2 * 64) + (final ? 0 : 8+64);
- cost_bitmap += last_gap + contig + (final ? 0 : MIN(next_gap, 8+64));
- cost_bitmap_restart += contig + (final ? 0 : MIN(next_gap, 8+64));
+ cost_bitmap += last_gap + contig + (final ? 0 : MINIMUM(next_gap, 8+64));
+ cost_bitmap_restart += contig + (final ? 0 : MINIMUM(next_gap, 8+64));
/* Convert to byte costs for actual comparison */
cost_list = (cost_list + 7) / 8;
@@ -704,7 +734,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf)
int
ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
- const struct sshkey **sign_keys, u_int nsign_keys)
+ struct sshkey **sign_keys, u_int nsign_keys)
{
int r = SSH_ERR_INTERNAL_ERROR;
struct revoked_certs *rc;
@@ -723,7 +753,7 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
if ((r = sshbuf_put(buf, KRL_MAGIC, sizeof(KRL_MAGIC) - 1)) != 0 ||
(r = sshbuf_put_u32(buf, KRL_FORMAT_VERSION)) != 0 ||
(r = sshbuf_put_u64(buf, krl->krl_version)) != 0 ||
- (r = sshbuf_put_u64(buf, krl->generated_date) != 0) ||
+ (r = sshbuf_put_u64(buf, krl->generated_date)) != 0 ||
(r = sshbuf_put_u64(buf, krl->flags)) != 0 ||
(r = sshbuf_put_string(buf, NULL, 0)) != 0 ||
(r = sshbuf_put_cstring(buf, krl->comment)) != 0)
@@ -763,6 +793,18 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
(r = sshbuf_put_stringb(buf, sect)) != 0)
goto out;
}
+ sshbuf_reset(sect);
+ RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha256s) {
+ KRL_DBG(("%s: hash len %zu ", __func__, rb->len));
+ if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0)
+ goto out;
+ }
+ if (sshbuf_len(sect) != 0) {
+ if ((r = sshbuf_put_u8(buf,
+ KRL_SECTION_FINGERPRINT_SHA256)) != 0 ||
+ (r = sshbuf_put_stringb(buf, sect)) != 0)
+ goto out;
+ }
for (i = 0; i < nsign_keys; i++) {
KRL_DBG(("%s: signature key %s", __func__,
@@ -772,7 +814,7 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
goto out;
if ((r = sshkey_sign(sign_keys[i], &sblob, &slen,
- sshbuf_ptr(buf), sshbuf_len(buf), 0)) == -1)
+ sshbuf_ptr(buf), sshbuf_len(buf), NULL, NULL, 0)) != 0)
goto out;
KRL_DBG(("%s: signature sig len %zu", __func__, slen));
if ((r = sshbuf_put_string(buf, sblob, slen)) != 0)
@@ -826,10 +868,8 @@ parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl)
goto out;
while (sshbuf_len(buf) > 0) {
- if (subsect != NULL) {
- sshbuf_free(subsect);
- subsect = NULL;
- }
+ sshbuf_free(subsect);
+ subsect = NULL;
if ((r = sshbuf_get_u8(buf, &type)) != 0 ||
(r = sshbuf_froms(buf, &subsect)) != 0)
goto out;
@@ -917,6 +957,29 @@ parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl)
return r;
}
+static int
+blob_section(struct sshbuf *sect, struct revoked_blob_tree *target_tree,
+ size_t expected_len)
+{
+ u_char *rdata = NULL;
+ size_t rlen = 0;
+ int r;
+
+ while (sshbuf_len(sect) > 0) {
+ if ((r = sshbuf_get_string(sect, &rdata, &rlen)) != 0)
+ return r;
+ if (expected_len != 0 && rlen != expected_len) {
+ error("%s: bad length", __func__);
+ free(rdata);
+ return SSH_ERR_INVALID_FORMAT;
+ }
+ if ((r = revoke_blob(target_tree, rdata, rlen)) != 0) {
+ free(rdata);
+ return r;
+ }
+ }
+ return 0;
+}
/* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */
int
@@ -928,9 +991,9 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
char timestamp[64];
int r = SSH_ERR_INTERNAL_ERROR, sig_seen;
struct sshkey *key = NULL, **ca_used = NULL, **tmp_ca_used;
- u_char type, *rdata = NULL;
+ u_char type;
const u_char *blob;
- size_t i, j, sig_off, sects_off, rlen, blen, nca_used;
+ size_t i, j, sig_off, sects_off, blen, nca_used;
u_int format_version;
nca_used = 0;
@@ -1017,7 +1080,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
}
/* Check signature over entire KRL up to this point */
if ((r = sshkey_verify(key, blob, blen,
- sshbuf_ptr(buf), sshbuf_len(buf) - sig_off, 0)) != 0)
+ sshbuf_ptr(buf), sig_off, NULL, 0, NULL)) != 0)
goto out;
/* Check if this key has already signed this KRL */
for (i = 0; i < nca_used; i++) {
@@ -1029,7 +1092,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
}
}
/* Record keys used to sign the KRL */
- tmp_ca_used = reallocarray(ca_used, nca_used + 1,
+ tmp_ca_used = recallocarray(ca_used, nca_used, nca_used + 1,
sizeof(*ca_used));
if (tmp_ca_used == NULL) {
r = SSH_ERR_ALLOC_FAIL;
@@ -1038,7 +1101,6 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
ca_used = tmp_ca_used;
ca_used[nca_used++] = key;
key = NULL;
- break;
}
if (sshbuf_len(copy) != 0) {
@@ -1059,10 +1121,8 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
if ((r = sshbuf_consume(copy, sects_off)) != 0)
goto out;
while (sshbuf_len(copy) > 0) {
- if (sect != NULL) {
- sshbuf_free(sect);
- sect = NULL;
- }
+ sshbuf_free(sect);
+ sect = NULL;
if ((r = sshbuf_get_u8(copy, &type)) != 0 ||
(r = sshbuf_froms(copy, &sect)) != 0)
goto out;
@@ -1074,28 +1134,23 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
goto out;
break;
case KRL_SECTION_EXPLICIT_KEY:
+ if ((r = blob_section(sect,
+ &krl->revoked_keys, 0)) != 0)
+ goto out;
+ break;
case KRL_SECTION_FINGERPRINT_SHA1:
- while (sshbuf_len(sect) > 0) {
- if ((r = sshbuf_get_string(sect,
- &rdata, &rlen)) != 0)
- goto out;
- if (type == KRL_SECTION_FINGERPRINT_SHA1 &&
- rlen != 20) {
- error("%s: bad SHA1 length", __func__);
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- if ((r = revoke_blob(
- type == KRL_SECTION_EXPLICIT_KEY ?
- &krl->revoked_keys : &krl->revoked_sha1s,
- rdata, rlen)) != 0)
- goto out;
- rdata = NULL; /* revoke_blob frees rdata */
- }
+ if ((r = blob_section(sect,
+ &krl->revoked_sha1s, 20)) != 0)
+ goto out;
+ break;
+ case KRL_SECTION_FINGERPRINT_SHA256:
+ if ((r = blob_section(sect,
+ &krl->revoked_sha256s, 32)) != 0)
+ goto out;
break;
case KRL_SECTION_SIGNATURE:
/* Handled above, but still need to stay in synch */
- sshbuf_reset(sect);
+ sshbuf_free(sect);
sect = NULL;
if ((r = sshbuf_skip_string(copy)) != 0)
goto out;
@@ -1105,7 +1160,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
- if (sshbuf_len(sect) > 0) {
+ if (sect != NULL && sshbuf_len(sect) > 0) {
error("KRL section contains unparsed data");
r = SSH_ERR_INVALID_FORMAT;
goto out;
@@ -1156,7 +1211,6 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
for (i = 0; i < nca_used; i++)
sshkey_free(ca_used[i]);
free(ca_used);
- free(rdata);
sshkey_free(key);
sshbuf_free(copy);
sshbuf_free(sect);
@@ -1180,10 +1234,10 @@ is_cert_revoked(const struct sshkey *key, struct revoked_certs *rc)
}
/*
- * Legacy cert formats lack serial numbers. Zero serials numbers
- * are ignored (it's the default when the CA doesn't specify one).
+ * Zero serials numbers are ignored (it's the default when the
+ * CA doesn't specify one).
*/
- if (sshkey_cert_is_legacy(key) || key->cert->serial == 0)
+ if (key->cert->serial == 0)
return 0;
memset(&rs, 0, sizeof(rs));
@@ -1216,6 +1270,16 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
KRL_DBG(("%s: revoked by key SHA1", __func__));
return SSH_ERR_KEY_REVOKED;
}
+ memset(&rb, 0, sizeof(rb));
+ if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA256,
+ &rb.blob, &rb.len)) != 0)
+ return r;
+ erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha256s, &rb);
+ free(rb.blob);
+ if (erb != NULL) {
+ KRL_DBG(("%s: revoked by key SHA256", __func__));
+ return SSH_ERR_KEY_REVOKED;
+ }
/* Next, explicit keys */
memset(&rb, 0, sizeof(rb));
@@ -1273,19 +1337,11 @@ ssh_krl_file_contains_key(const char *path, const struct sshkey *key)
{
struct sshbuf *krlbuf = NULL;
struct ssh_krl *krl = NULL;
- int oerrno = 0, r, fd;
+ int oerrno = 0, r;
if (path == NULL)
return 0;
-
- if ((krlbuf = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((fd = open(path, O_RDONLY)) == -1) {
- r = SSH_ERR_SYSTEM_ERROR;
- oerrno = errno;
- goto out;
- }
- if ((r = sshkey_load_file(fd, krlbuf)) != 0) {
+ if ((r = sshbuf_load_file(path, &krlbuf)) != 0) {
oerrno = errno;
goto out;
}
@@ -1294,10 +1350,103 @@ ssh_krl_file_contains_key(const char *path, const struct sshkey *key)
debug2("%s: checking KRL %s", __func__, path);
r = ssh_krl_check_key(krl, key);
out:
- close(fd);
sshbuf_free(krlbuf);
ssh_krl_free(krl);
if (r != 0)
errno = oerrno;
return r;
}
+
+int
+krl_dump(struct ssh_krl *krl, FILE *f)
+{
+ struct sshkey *key = NULL;
+ struct revoked_blob *rb;
+ struct revoked_certs *rc;
+ struct revoked_serial *rs;
+ struct revoked_key_id *rki;
+ int r, ret = 0;
+ char *fp, timestamp[64];
+
+ /* Try to print in a KRL spec-compatible format */
+ format_timestamp(krl->generated_date, timestamp, sizeof(timestamp));
+ fprintf(f, "# KRL version %llu\n",
+ (unsigned long long)krl->krl_version);
+ fprintf(f, "# Generated at %s\n", timestamp);
+ if (krl->comment != NULL && *krl->comment != '\0') {
+ r = INT_MAX;
+ asmprintf(&fp, INT_MAX, &r, "%s", krl->comment);
+ fprintf(f, "# Comment: %s\n", fp);
+ free(fp);
+ }
+ fputc('\n', f);
+
+ RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) {
+ if ((r = sshkey_from_blob(rb->blob, rb->len, &key)) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ error("Parse key in KRL: %s", ssh_err(r));
+ continue;
+ }
+ if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
+ SSH_FP_DEFAULT)) == NULL) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ error("sshkey_fingerprint failed");
+ continue;
+ }
+ fprintf(f, "hash: SHA256:%s # %s\n", fp, sshkey_ssh_name(key));
+ free(fp);
+ free(key);
+ }
+ RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha256s) {
+ fp = tohex(rb->blob, rb->len);
+ fprintf(f, "hash: SHA256:%s\n", fp);
+ free(fp);
+ }
+ RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) {
+ /*
+ * There is not KRL spec keyword for raw SHA1 hashes, so
+ * print them as comments.
+ */
+ fp = tohex(rb->blob, rb->len);
+ fprintf(f, "# hash SHA1:%s\n", fp);
+ free(fp);
+ }
+
+ TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
+ fputc('\n', f);
+ if (rc->ca_key == NULL)
+ fprintf(f, "# Wildcard CA\n");
+ else {
+ if ((fp = sshkey_fingerprint(rc->ca_key,
+ SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ error("sshkey_fingerprint failed");
+ continue;
+ }
+ fprintf(f, "# CA key %s %s\n",
+ sshkey_ssh_name(rc->ca_key), fp);
+ free(fp);
+ }
+ RB_FOREACH(rs, revoked_serial_tree, &rc->revoked_serials) {
+ if (rs->lo == rs->hi) {
+ fprintf(f, "serial: %llu\n",
+ (unsigned long long)rs->lo);
+ } else {
+ fprintf(f, "serial: %llu-%llu\n",
+ (unsigned long long)rs->lo,
+ (unsigned long long)rs->hi);
+ }
+ }
+ RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) {
+ /*
+ * We don't want key IDs with embedded newlines to
+ * mess up the display.
+ */
+ r = INT_MAX;
+ asmprintf(&fp, INT_MAX, &r, "%s", rki->key_id);
+ fprintf(f, "id: %s\n", fp);
+ free(fp);
+ }
+ }
+ return ret;
+}
diff --git a/krl.h b/krl.h
index 4e12befc..ca6d3f28 100644
--- a/krl.h
+++ b/krl.h
@@ -14,7 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $OpenBSD: krl.h,v 1.4 2015/01/13 19:06:49 djm Exp $ */
+/* $OpenBSD: krl.h,v 1.8 2020/04/03 02:26:56 djm Exp $ */
#ifndef _KRL_H
#define _KRL_H
@@ -29,6 +29,7 @@
#define KRL_SECTION_EXPLICIT_KEY 2
#define KRL_SECTION_FINGERPRINT_SHA1 3
#define KRL_SECTION_SIGNATURE 4
+#define KRL_SECTION_FINGERPRINT_SHA256 5
/* KRL_SECTION_CERTIFICATES subsection types */
#define KRL_SECTION_CERT_SERIAL_LIST 0x20
@@ -43,7 +44,6 @@ struct ssh_krl;
struct ssh_krl *ssh_krl_init(void);
void ssh_krl_free(struct ssh_krl *krl);
void ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version);
-void ssh_krl_set_sign_key(struct ssh_krl *krl, const struct sshkey *sign_key);
int ssh_krl_set_comment(struct ssh_krl *krl, const char *comment);
int ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl,
const struct sshkey *ca_key, u_int64_t serial);
@@ -52,14 +52,16 @@ int ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl,
int ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl,
const struct sshkey *ca_key, const char *key_id);
int ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key);
-int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key);
+int 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);
int ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key);
int ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
- const struct sshkey **sign_keys, u_int nsign_keys);
+ struct sshkey **sign_keys, u_int nsign_keys);
int ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
const struct sshkey **sign_ca_keys, size_t nsign_ca_keys);
int ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key);
int ssh_krl_file_contains_key(const char *path, const struct sshkey *key);
+int krl_dump(struct ssh_krl *krl, FILE *f);
#endif /* _KRL_H */
diff --git a/log.c b/log.c
index 32e1d2e4..d9c2d136 100644
--- a/log.c
+++ b/log.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.c,v 1.45 2013/05/16 09:08:41 dtucker Exp $ */
+/* $OpenBSD: log.c,v 1.51 2018/07/27 12:03:17 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -50,7 +50,6 @@
# include <vis.h>
#endif
-#include "xmalloc.h"
#include "log.h"
static LogLevel log_level = SYSLOG_LEVEL_INFO;
@@ -106,6 +105,12 @@ static struct {
{ NULL, SYSLOG_LEVEL_NOT_SET }
};
+LogLevel
+log_level_get(void)
+{
+ return log_level;
+}
+
SyslogFacility
log_facility_number(char *name)
{
@@ -177,6 +182,16 @@ sigdie(const char *fmt,...)
_exit(1);
}
+void
+logdie(const char *fmt,...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ do_log(SYSLOG_LEVEL_INFO, fmt, args);
+ va_end(args);
+ cleanup_exit(255);
+}
/* Log this message (information that usually should go to the log). */
@@ -247,18 +262,7 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
argv0 = av0;
- switch (level) {
- case SYSLOG_LEVEL_QUIET:
- case SYSLOG_LEVEL_FATAL:
- case SYSLOG_LEVEL_ERROR:
- case SYSLOG_LEVEL_INFO:
- case SYSLOG_LEVEL_VERBOSE:
- case SYSLOG_LEVEL_DEBUG1:
- case SYSLOG_LEVEL_DEBUG2:
- case SYSLOG_LEVEL_DEBUG3:
- log_level = level;
- break;
- default:
+ if (log_change_level(level) != 0) {
fprintf(stderr, "Unrecognized internal syslog level code %d\n",
(int) level);
exit(1);
@@ -331,19 +335,33 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
#endif
}
-void
+int
log_change_level(LogLevel new_log_level)
{
/* no-op if log_init has not been called */
if (argv0 == NULL)
- return;
- log_init(argv0, new_log_level, log_facility, log_on_stderr);
+ return 0;
+
+ switch (new_log_level) {
+ case SYSLOG_LEVEL_QUIET:
+ case SYSLOG_LEVEL_FATAL:
+ case SYSLOG_LEVEL_ERROR:
+ case SYSLOG_LEVEL_INFO:
+ case SYSLOG_LEVEL_VERBOSE:
+ case SYSLOG_LEVEL_DEBUG1:
+ case SYSLOG_LEVEL_DEBUG2:
+ case SYSLOG_LEVEL_DEBUG3:
+ log_level = new_log_level;
+ return 0;
+ default:
+ return -1;
+ }
}
int
log_is_on_stderr(void)
{
- return log_on_stderr;
+ return log_on_stderr && log_stderr_fd == STDERR_FILENO;
}
/* redirect what would usually get written to stderr to specified file */
@@ -444,7 +462,8 @@ do_log(LogLevel level, const char *fmt, va_list args)
tmp_handler(level, fmtbuf, log_handler_ctx);
log_handler = tmp_handler;
} else if (log_on_stderr) {
- snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf);
+ snprintf(msgbuf, sizeof msgbuf, "%.*s\r\n",
+ (int)sizeof msgbuf - 3, fmtbuf);
(void)write(log_stderr_fd, msgbuf, strlen(msgbuf));
} else {
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
diff --git a/log.h b/log.h
index ae7df25d..78cda287 100644
--- a/log.h
+++ b/log.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.h,v 1.20 2013/04/07 02:10:33 dtucker Exp $ */
+/* $OpenBSD: log.h,v 1.24 2019/09/06 04:53:27 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -15,6 +15,8 @@
#ifndef SSH_LOG_H
#define SSH_LOG_H
+#include <stdarg.h> /* va_list */
+
/* Supported syslog facilities and levels. */
typedef enum {
SYSLOG_FACILITY_DAEMON,
@@ -49,7 +51,8 @@ typedef enum {
typedef void (log_handler_fn)(LogLevel, const char *, void *);
void log_init(char *, LogLevel, SyslogFacility, int);
-void log_change_level(LogLevel);
+LogLevel log_level_get(void);
+int log_change_level(LogLevel);
int log_is_on_stderr(void);
void log_redirect_stderr_to(const char *);
@@ -63,6 +66,8 @@ void fatal(const char *, ...) __attribute__((noreturn))
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)));
diff --git a/loginrec.c b/loginrec.c
index 94ae81dc..e5289deb 100644
--- a/loginrec.c
+++ b/loginrec.c
@@ -150,9 +150,13 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
#include <netinet/in.h>
+#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_PATHS_H
@@ -160,12 +164,13 @@
#endif
#include <pwd.h>
#include <stdarg.h>
+#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "xmalloc.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "ssh.h"
#include "loginrec.h"
@@ -174,7 +179,8 @@
#include "packet.h"
#include "canohost.h"
#include "auth.h"
-#include "buffer.h"
+#include "sshbuf.h"
+#include "ssherr.h"
#ifdef HAVE_UTIL_H
# include <util.h>
@@ -207,7 +213,7 @@ int utmpx_get_entry(struct logininfo *li);
int wtmp_get_entry(struct logininfo *li);
int wtmpx_get_entry(struct logininfo *li);
-extern Buffer loginmsg;
+extern struct sshbuf *loginmsg;
/* pick the shortest string */
#define MIN_SIZEOF(s1,s2) (sizeof(s1) < sizeof(s2) ? sizeof(s1) : sizeof(s2))
@@ -463,7 +469,7 @@ login_write(struct logininfo *li)
#ifdef CUSTOM_SYS_AUTH_RECORD_LOGIN
if (li->type == LTYPE_LOGIN &&
!sys_auth_record_login(li->username,li->hostname,li->line,
- &loginmsg))
+ loginmsg))
logit("Writing login record failed for %s", li->username);
#endif
#ifdef SSH_AUDIT_EVENTS
@@ -660,15 +666,9 @@ construct_utmp(struct logininfo *li,
switch (li->type) {
case LTYPE_LOGIN:
ut->ut_type = USER_PROCESS;
-#ifdef _UNICOS
- cray_set_tmpdir(ut);
-#endif
break;
case LTYPE_LOGOUT:
ut->ut_type = DEAD_PROCESS;
-#ifdef _UNICOS
- cray_retain_utmp(ut, li->pid);
-#endif
break;
}
# endif
@@ -1655,7 +1655,7 @@ utmpx_get_entry(struct logininfo *li)
*/
void
-record_failed_login(const char *username, const char *hostname,
+record_failed_login(struct ssh *ssh, const char *username, const char *hostname,
const char *ttyn)
{
int fd;
@@ -1698,8 +1698,8 @@ record_failed_login(const char *username, const char *hostname,
/* strncpy because we don't necessarily want nul termination */
strncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
- if (packet_connection_is_on_socket() &&
- getpeername(packet_get_connection_in(),
+ if (ssh_packet_connection_is_on_socket(ssh) &&
+ getpeername(ssh_packet_get_connection_in(ssh),
(struct sockaddr *)&from, &fromlen) == 0) {
ipv64_normalise_mapped(&from, &fromlen);
if (from.ss_family == AF_INET) {
diff --git a/loginrec.h b/loginrec.h
index 28923e78..62cc0e78 100644
--- a/loginrec.h
+++ b/loginrec.h
@@ -31,6 +31,8 @@
#include "includes.h"
+struct ssh;
+
/**
** you should use the login_* calls to work around platform dependencies
**/
@@ -126,6 +128,7 @@ char *line_fullname(char *dst, const char *src, u_int dstsize);
char *line_stripname(char *dst, const char *src, int dstsize);
char *line_abbrevname(char *dst, const char *src, int dstsize);
-void record_failed_login(const char *, const char *, const char *);
+void record_failed_login(struct ssh *, const char *, const char *,
+ const char *);
#endif /* _HAVE_LOGINREC_H_ */
diff --git a/mac.c b/mac.c
index 64c3aa17..f3dda669 100644
--- a/mac.c
+++ b/mac.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mac.c,v 1.32 2015/01/15 18:32:54 naddy Exp $ */
+/* $OpenBSD: mac.c,v 1.35 2019/09/06 04:53:27 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@@ -27,6 +27,7 @@
#include <sys/types.h>
+#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -58,29 +59,20 @@ static const struct macalg macs[] = {
/* Encrypt-and-MAC (encrypt-and-authenticate) variants */
{ "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 },
{ "hmac-sha1-96", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 0 },
-#ifdef HAVE_EVP_SHA256
{ "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 },
{ "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 },
-#endif
{ "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 },
{ "hmac-md5-96", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 0 },
-#if defined(HAVE_EVP_RIPEMD)
- { "hmac-ripemd160", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 },
- { "hmac-ripemd160@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 },
-#endif
{ "umac-64@openssh.com", SSH_UMAC, 0, 0, 128, 64, 0 },
{ "umac-128@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 0 },
/* Encrypt-then-MAC variants */
{ "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 },
{ "hmac-sha1-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 1 },
-#ifdef HAVE_EVP_SHA256
{ "hmac-sha2-256-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 1 },
{ "hmac-sha2-512-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 1 },
-#endif
{ "hmac-md5-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 1 },
{ "hmac-md5-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 1 },
- { "hmac-ripemd160-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 1 },
{ "umac-64-etm@openssh.com", SSH_UMAC, 0, 0, 128, 64, 1 },
{ "umac-128-etm@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 1 },
@@ -169,7 +161,8 @@ mac_init(struct sshmac *mac)
}
int
-mac_compute(struct sshmac *mac, u_int32_t seqno, const u_char *data, int datalen,
+mac_compute(struct sshmac *mac, u_int32_t seqno,
+ const u_char *data, int datalen,
u_char *digest, size_t dlen)
{
static union {
@@ -213,6 +206,24 @@ mac_compute(struct sshmac *mac, u_int32_t seqno, const u_char *data, int datalen
return 0;
}
+int
+mac_check(struct sshmac *mac, u_int32_t seqno,
+ const u_char *data, size_t dlen,
+ const u_char *theirmac, size_t mlen)
+{
+ u_char ourmac[SSH_DIGEST_MAX_LENGTH];
+ int r;
+
+ if (mac->mac_len > mlen)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((r = mac_compute(mac, seqno, data, dlen,
+ ourmac, sizeof(ourmac))) != 0)
+ return r;
+ if (timingsafe_bcmp(ourmac, theirmac, mac->mac_len) != 0)
+ return SSH_ERR_MAC_INVALID;
+ return 0;
+}
+
void
mac_clear(struct sshmac *mac)
{
diff --git a/mac.h b/mac.h
index e5f6b84d..0b119d7a 100644
--- a/mac.h
+++ b/mac.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mac.h,v 1.9 2015/01/13 19:31:40 markus Exp $ */
+/* $OpenBSD: mac.h,v 1.10 2016/07/08 03:44:42 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@@ -46,6 +46,8 @@ int mac_setup(struct sshmac *, char *);
int mac_init(struct sshmac *);
int mac_compute(struct sshmac *, u_int32_t, const u_char *, int,
u_char *, size_t);
+int mac_check(struct sshmac *, u_int32_t, const u_char *, size_t,
+ const u_char *, size_t);
void mac_clear(struct sshmac *);
#endif /* SSHMAC_H */
diff --git a/match.c b/match.c
index c35e3289..3a8fa9d7 100644
--- a/match.c
+++ b/match.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: match.c,v 1.29 2013/11/20 20:54:10 deraadt Exp $ */
+/* $OpenBSD: match.c,v 1.41 2019/11/13 04:47:52 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -42,9 +42,12 @@
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
#include "xmalloc.h"
#include "match.h"
+#include "misc.h"
/*
* Returns true if the given string matches the pattern (which may contain ?
@@ -115,15 +118,13 @@ match_pattern(const char *s, const char *pattern)
* indicate negation). Returns -1 if negation matches, 1 if there is
* a positive match, 0 if there is no match at all.
*/
-
int
-match_pattern_list(const char *string, const char *pattern, u_int len,
- int dolower)
+match_pattern_list(const char *string, const char *pattern, int dolower)
{
char sub[1024];
int negated;
int got_positive;
- u_int i, subi;
+ u_int i, subi, len = strlen(pattern);
got_positive = 0;
for (i = 0; i < len;) {
@@ -147,7 +148,7 @@ match_pattern_list(const char *string, const char *pattern, u_int len,
if (subi >= sizeof(sub) - 1)
return 0;
- /* If the subpattern was terminated by a comma, skip the comma. */
+ /* If the subpattern was terminated by a comma, then skip it. */
if (i < len && pattern[i] == ',')
i++;
@@ -170,6 +171,19 @@ match_pattern_list(const char *string, const char *pattern, u_int len,
return got_positive;
}
+/* Match a list representing users or groups. */
+int
+match_usergroup_pattern_list(const char *string, const char *pattern)
+{
+#ifdef HAVE_CYGWIN
+ /* Windows usernames may be Unicode and are not case sensitive */
+ return cygwin_ug_match_pattern_list(string, pattern);
+#else
+ /* Case sensitive match */
+ return match_pattern_list(string, pattern, 0);
+#endif
+}
+
/*
* Tries to match the host name (which must be in all lowercase) against the
* comma-separated sequence of subpatterns (each possibly preceded by ! to
@@ -177,9 +191,15 @@ match_pattern_list(const char *string, const char *pattern, u_int len,
* a positive match, 0 if there is no match at all.
*/
int
-match_hostname(const char *host, const char *pattern, u_int len)
+match_hostname(const char *host, const char *pattern)
{
- return match_pattern_list(host, pattern, len, 1);
+ char *hostcopy = xstrdup(host);
+ int r;
+
+ lowercase(hostcopy);
+ r = match_pattern_list(hostcopy, pattern, 1);
+ free(hostcopy);
+ return r;
}
/*
@@ -193,14 +213,13 @@ match_host_and_ip(const char *host, const char *ipaddr,
{
int mhost, mip;
- /* error in ipaddr match */
if ((mip = addr_match_list(ipaddr, patterns)) == -2)
- return -1;
- else if (mip == -1) /* negative ip address match */
- return 0;
+ return -1; /* error in ipaddr match */
+ else if (host == NULL || ipaddr == NULL || mip == -1)
+ return 0; /* negative ip address match, or testing pattern */
/* negative hostname match */
- if ((mhost = match_hostname(host, patterns, strlen(patterns))) == -1)
+ if ((mhost = match_hostname(host, patterns)) == -1)
return 0;
/* no match at all */
if (mhost == 0 && mip == 0)
@@ -209,7 +228,9 @@ match_host_and_ip(const char *host, const char *ipaddr,
}
/*
- * match user, user@host_or_ip, user@host_or_ip_list against pattern
+ * Match user, user@host_or_ip, user@host_or_ip_list against pattern.
+ * If user, host and ipaddr are all NULL then validate pattern/
+ * Returns -1 on invalid pattern, 0 on no match, 1 on match.
*/
int
match_user(const char *user, const char *host, const char *ipaddr,
@@ -218,7 +239,15 @@ match_user(const char *user, const char *host, const char *ipaddr,
char *p, *pat;
int ret;
- if ((p = strchr(pattern,'@')) == NULL)
+ /* test mode */
+ if (user == NULL && host == NULL && ipaddr == NULL) {
+ if ((p = strchr(pattern, '@')) != NULL &&
+ match_host_and_ip(NULL, NULL, p + 1) < 0)
+ return -1;
+ return 0;
+ }
+
+ if ((p = strchr(pattern, '@')) == NULL)
return match_pattern(user, pattern);
pat = xstrdup(pattern);
@@ -277,3 +306,59 @@ match_list(const char *client, const char *server, u_int *next)
free(s);
return NULL;
}
+
+/*
+ * Filter proposal using pattern-list filter.
+ * "blacklist" determines sense of filter:
+ * non-zero indicates that items matching filter should be excluded.
+ * zero indicates that only items matching filter should be included.
+ * returns NULL on allocation error, otherwise caller must free result.
+ */
+static char *
+filter_list(const char *proposal, const char *filter, int blacklist)
+{
+ size_t len = strlen(proposal) + 1;
+ char *fix_prop = malloc(len);
+ char *orig_prop = strdup(proposal);
+ char *cp, *tmp;
+ int r;
+
+ if (fix_prop == NULL || orig_prop == NULL) {
+ free(orig_prop);
+ free(fix_prop);
+ return NULL;
+ }
+
+ tmp = orig_prop;
+ *fix_prop = '\0';
+ while ((cp = strsep(&tmp, ",")) != NULL) {
+ r = match_pattern_list(cp, filter, 0);
+ if ((blacklist && r != 1) || (!blacklist && r == 1)) {
+ if (*fix_prop != '\0')
+ strlcat(fix_prop, ",", len);
+ strlcat(fix_prop, cp, len);
+ }
+ }
+ free(orig_prop);
+ return fix_prop;
+}
+
+/*
+ * Filters a comma-separated list of strings, excluding any entry matching
+ * the 'filter' pattern list. Caller must free returned string.
+ */
+char *
+match_filter_blacklist(const char *proposal, const char *filter)
+{
+ return filter_list(proposal, filter, 1);
+}
+
+/*
+ * Filters a comma-separated list of strings, including only entries matching
+ * the 'filter' pattern list. Caller must free returned string.
+ */
+char *
+match_filter_whitelist(const char *proposal, const char *filter)
+{
+ return filter_list(proposal, filter, 0);
+}
diff --git a/match.h b/match.h
index 3d7f70fc..3a8a6ecd 100644
--- a/match.h
+++ b/match.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: match.h,v 1.15 2010/02/26 20:29:54 djm Exp $ */
+/* $OpenBSD: match.h,v 1.19 2019/03/06 22:14:23 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -15,11 +15,14 @@
#define MATCH_H
int match_pattern(const char *, const char *);
-int match_pattern_list(const char *, const char *, u_int, int);
-int match_hostname(const char *, const char *, u_int);
+int match_pattern_list(const char *, const char *, int);
+int match_usergroup_pattern_list(const char *, const char *);
+int match_hostname(const char *, const char *);
int match_host_and_ip(const char *, const char *, const char *);
int match_user(const char *, const char *, const char *, const char *);
char *match_list(const char *, const char *, u_int *);
+char *match_filter_blacklist(const char *, const char *);
+char *match_filter_whitelist(const char *, const char *);
/* addrmatch.c */
int addr_match_list(const char *, const char *);
diff --git a/md-sha256.c b/md-sha256.c
deleted file mode 100644
index 8c1b3b92..00000000
--- a/md-sha256.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* $OpenBSD: md-sha256.c,v 1.5 2006/08/03 03:34:42 deraadt Exp $ */
-/*
- * Copyright (c) 2005 Damien Miller <djm@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* EVP wrapper for SHA256 */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <openssl/opensslv.h>
-
-#if !defined(HAVE_EVP_SHA256) && (OPENSSL_VERSION_NUMBER >= 0x00907000L)
-
-#include <string.h>
-#include <openssl/evp.h>
-#ifdef HAVE_SHA256_UPDATE
-# ifdef HAVE_SHA2_H
-# include <sha2.h>
-# elif defined(HAVE_CRYPTO_SHA2_H)
-# include <crypto/sha2.h>
-# endif
-#endif
-
-const EVP_MD *evp_ssh_sha256(void);
-
-static int
-ssh_sha256_init(EVP_MD_CTX *ctxt)
-{
- SHA256_Init(ctxt->md_data);
- return (1);
-}
-
-static int
-ssh_sha256_update(EVP_MD_CTX *ctxt, const void *data, unsigned long len)
-{
- SHA256_Update(ctxt->md_data, data, len);
- return (1);
-}
-
-static int
-ssh_sha256_final(EVP_MD_CTX *ctxt, unsigned char *digest)
-{
- SHA256_Final(digest, ctxt->md_data);
- return (1);
-}
-
-static int
-ssh_sha256_cleanup(EVP_MD_CTX *ctxt)
-{
- memset(ctxt->md_data, 0, sizeof(SHA256_CTX));
- return (1);
-}
-
-const EVP_MD *
-evp_ssh_sha256(void)
-{
- static EVP_MD ssh_sha256;
-
- memset(&ssh_sha256, 0, sizeof(ssh_sha256));
- ssh_sha256.type = NID_undef;
- ssh_sha256.md_size = SHA256_DIGEST_LENGTH;
- ssh_sha256.init = ssh_sha256_init;
- ssh_sha256.update = ssh_sha256_update;
- ssh_sha256.final = ssh_sha256_final;
- ssh_sha256.cleanup = ssh_sha256_cleanup;
- ssh_sha256.block_size = SHA256_BLOCK_LENGTH;
- ssh_sha256.ctx_size = sizeof(SHA256_CTX);
-
- return (&ssh_sha256);
-}
-
-#endif /* !defined(HAVE_EVP_SHA256) && (OPENSSL_VERSION_NUMBER >= 0x00907000L) */
-
diff --git a/md5crypt.c b/md5crypt.c
index 22ef9893..52cf2959 100644
--- a/md5crypt.c
+++ b/md5crypt.c
@@ -50,7 +50,7 @@ is_md5_salt(const char *salt)
char *
md5_crypt(const char *pw, const char *salt)
{
- static char passwd[120], salt_copy[9], *p;
+ static char passwd[120], salt_copy[9];
static const char *sp, *ep;
unsigned char final[16];
int sl, pl, i, j;
@@ -139,8 +139,6 @@ md5_crypt(const char *pw, const char *salt)
MD5_Final(final, &ctx1);
}
- p = passwd + strlen(passwd);
-
l = (final[ 0]<<16) | (final[ 6]<<8) | final[12];
strlcat(passwd, to64(l, 4), sizeof(passwd));
l = (final[ 1]<<16) | (final[ 7]<<8) | final[13];
diff --git a/md5crypt.h b/md5crypt.h
index 2341e2c1..978e579c 100644
--- a/md5crypt.h
+++ b/md5crypt.h
@@ -7,8 +7,6 @@
* ----------------------------------------------------------------------------
*/
-/* $Id: md5crypt.h,v 1.4 2003/05/18 14:46:46 djm Exp $ */
-
#ifndef _MD5CRYPT_H
#define _MD5CRYPT_H
diff --git a/mdoc2man.awk b/mdoc2man.awk
index 80e8d5ff..d393ae6f 100644
--- a/mdoc2man.awk
+++ b/mdoc2man.awk
@@ -1,7 +1,5 @@
#!/usr/bin/awk
#
-# $Id: mdoc2man.awk,v 1.9 2009/10/24 00:52:42 dtucker Exp $
-#
# Version history:
# v4+ Adapted for OpenSSH Portable (see cvs Id and history)
# v3, I put the program under a proper license
@@ -321,6 +319,8 @@ function add(str) {
w=nwords
} else if(match(words[w],"^El$")) {
optlist=oldoptlist
+ if(!optlist)
+ add(".PP")
} else if(match(words[w],"^Bk$")) {
if(match(words[w+1],"-words")) {
w++
diff --git a/misc.c b/misc.c
index d208b446..48ff6af8 100644
--- a/misc.c
+++ b/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.96 2015/01/16 06:40:12 deraadt Exp $ */
+/* $OpenBSD: misc.c,v 1.147 2020/04/25 06:59:36 dtucker Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
@@ -29,9 +29,19 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/wait.h>
#include <sys/un.h>
#include <limits.h>
+#ifdef HAVE_LIBGEN_H
+# include <libgen.h>
+#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -43,6 +53,7 @@
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
+#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
@@ -60,6 +71,9 @@
#include "misc.h"
#include "log.h"
#include "ssh.h"
+#include "sshbuf.h"
+#include "ssherr.h"
+#include "platform.h"
/* remove newline at end of string */
char *
@@ -83,9 +97,9 @@ set_nonblock(int fd)
{
int val;
- val = fcntl(fd, F_GETFL, 0);
- if (val < 0) {
- error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
+ val = fcntl(fd, F_GETFL);
+ if (val == -1) {
+ error("fcntl(%d, F_GETFL): %s", fd, strerror(errno));
return (-1);
}
if (val & O_NONBLOCK) {
@@ -107,9 +121,9 @@ unset_nonblock(int fd)
{
int val;
- val = fcntl(fd, F_GETFL, 0);
- if (val < 0) {
- error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
+ val = fcntl(fd, F_GETFL);
+ if (val == -1) {
+ error("fcntl(%d, F_GETFL): %s", fd, strerror(errno));
return (-1);
}
if (!(val & O_NONBLOCK)) {
@@ -156,13 +170,164 @@ set_nodelay(int fd)
error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
}
+/* Allow local port reuse in TIME_WAIT */
+int
+set_reuseaddr(int fd)
+{
+ int on = 1;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
+ error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+/* Get/set routing domain */
+char *
+get_rdomain(int fd)
+{
+#if defined(HAVE_SYS_GET_RDOMAIN)
+ return sys_get_rdomain(fd);
+#elif defined(__OpenBSD__)
+ int rtable;
+ char *ret;
+ socklen_t len = sizeof(rtable);
+
+ if (getsockopt(fd, SOL_SOCKET, SO_RTABLE, &rtable, &len) == -1) {
+ error("Failed to get routing domain for fd %d: %s",
+ fd, strerror(errno));
+ return NULL;
+ }
+ xasprintf(&ret, "%d", rtable);
+ return ret;
+#else /* defined(__OpenBSD__) */
+ return NULL;
+#endif
+}
+
+int
+set_rdomain(int fd, const char *name)
+{
+#if defined(HAVE_SYS_SET_RDOMAIN)
+ return sys_set_rdomain(fd, name);
+#elif defined(__OpenBSD__)
+ int rtable;
+ const char *errstr;
+
+ if (name == NULL)
+ return 0; /* default table */
+
+ rtable = (int)strtonum(name, 0, 255, &errstr);
+ if (errstr != NULL) {
+ /* Shouldn't happen */
+ error("Invalid routing domain \"%s\": %s", name, errstr);
+ return -1;
+ }
+ if (setsockopt(fd, SOL_SOCKET, SO_RTABLE,
+ &rtable, sizeof(rtable)) == -1) {
+ error("Failed to set routing domain %d on fd %d: %s",
+ rtable, fd, strerror(errno));
+ return -1;
+ }
+ return 0;
+#else /* defined(__OpenBSD__) */
+ error("Setting routing domain is not supported on this platform");
+ return -1;
+#endif
+}
+
+/*
+ * Wait up to *timeoutp milliseconds for events on fd. Updates
+ * *timeoutp with time remaining.
+ * Returns 0 if fd ready or -1 on timeout or error (see errno).
+ */
+static int
+waitfd(int fd, int *timeoutp, short events)
+{
+ struct pollfd pfd;
+ struct timeval t_start;
+ int oerrno, r;
+
+ monotime_tv(&t_start);
+ pfd.fd = fd;
+ pfd.events = events;
+ for (; *timeoutp >= 0;) {
+ r = poll(&pfd, 1, *timeoutp);
+ oerrno = errno;
+ ms_subtract_diff(&t_start, timeoutp);
+ errno = oerrno;
+ if (r > 0)
+ return 0;
+ else if (r == -1 && errno != EAGAIN)
+ return -1;
+ else if (r == 0)
+ break;
+ }
+ /* timeout */
+ errno = ETIMEDOUT;
+ return -1;
+}
+
+/*
+ * Wait up to *timeoutp milliseconds for fd to be readable. Updates
+ * *timeoutp with time remaining.
+ * Returns 0 if fd ready or -1 on timeout or error (see errno).
+ */
+int
+waitrfd(int fd, int *timeoutp) {
+ return waitfd(fd, timeoutp, POLLIN);
+}
+
+/*
+ * Attempt a non-blocking connect(2) to the specified address, waiting up to
+ * *timeoutp milliseconds for the connection to complete. If the timeout is
+ * <=0, then wait indefinitely.
+ *
+ * Returns 0 on success or -1 on failure.
+ */
+int
+timeout_connect(int sockfd, const struct sockaddr *serv_addr,
+ socklen_t addrlen, int *timeoutp)
+{
+ int optval = 0;
+ socklen_t optlen = sizeof(optval);
+
+ /* No timeout: just do a blocking connect() */
+ if (timeoutp == NULL || *timeoutp <= 0)
+ return connect(sockfd, serv_addr, addrlen);
+
+ set_nonblock(sockfd);
+ if (connect(sockfd, serv_addr, addrlen) == 0) {
+ /* Succeeded already? */
+ unset_nonblock(sockfd);
+ return 0;
+ } else if (errno != EINPROGRESS)
+ return -1;
+
+ if (waitfd(sockfd, timeoutp, POLLIN | POLLOUT) == -1)
+ return -1;
+
+ /* Completed or failed */
+ if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) {
+ debug("getsockopt: %s", strerror(errno));
+ return -1;
+ }
+ if (optval != 0) {
+ errno = optval;
+ return -1;
+ }
+ unset_nonblock(sockfd);
+ return 0;
+}
+
/* Characters considered whitespace in strsep calls. */
#define WHITESPACE " \t\r\n"
#define QUOTE "\""
/* return next token in configuration line */
-char *
-strdelim(char **s)
+static char *
+strdelim_internal(char **s, int split_equals)
{
char *old;
int wspace = 0;
@@ -172,7 +337,8 @@ strdelim(char **s)
old = *s;
- *s = strpbrk(*s, WHITESPACE QUOTE "=");
+ *s = strpbrk(*s,
+ split_equals ? WHITESPACE QUOTE "=" : WHITESPACE QUOTE);
if (*s == NULL)
return (old);
@@ -189,18 +355,37 @@ strdelim(char **s)
}
/* Allow only one '=' to be skipped */
- if (*s[0] == '=')
+ if (split_equals && *s[0] == '=')
wspace = 1;
*s[0] = '\0';
/* Skip any extra whitespace after first token */
*s += strspn(*s + 1, WHITESPACE) + 1;
- if (*s[0] == '=' && !wspace)
+ if (split_equals && *s[0] == '=' && !wspace)
*s += strspn(*s + 1, WHITESPACE) + 1;
return (old);
}
+/*
+ * Return next token in configuration line; splts on whitespace or a
+ * single '=' character.
+ */
+char *
+strdelim(char **s)
+{
+ return strdelim_internal(s, 1);
+}
+
+/*
+ * Return next token in configuration line; splts on whitespace only.
+ */
+char *
+strdelimw(char **s)
+{
+ return strdelim_internal(s, 0);
+}
+
struct passwd *
pwcopy(struct passwd *pw)
{
@@ -235,13 +420,16 @@ pwcopy(struct passwd *pw)
int
a2port(const char *s)
{
+ struct servent *se;
long long port;
const char *errstr;
port = strtonum(s, 0, 65535, &errstr);
- if (errstr != NULL)
- return -1;
- return (int)port;
+ if (errstr == NULL)
+ return (int)port;
+ if ((se = getservbyname(s, "tcp")) != NULL)
+ return ntohs(se->s_port);
+ return -1;
}
int
@@ -305,7 +493,7 @@ a2tun(const char *s, int *remote)
long
convtime(const char *s)
{
- long total, secs;
+ long total, secs, multiplier = 1;
const char *p;
char *endp;
@@ -332,23 +520,28 @@ convtime(const char *s)
break;
case 'm':
case 'M':
- secs *= MINUTES;
+ multiplier = MINUTES;
break;
case 'h':
case 'H':
- secs *= HOURS;
+ multiplier = HOURS;
break;
case 'd':
case 'D':
- secs *= DAYS;
+ multiplier = DAYS;
break;
case 'w':
case 'W':
- secs *= WEEKS;
+ multiplier = WEEKS;
break;
default:
return -1;
}
+ if (secs >= LONG_MAX / multiplier)
+ return -1;
+ secs *= multiplier;
+ if (total >= LONG_MAX - secs)
+ return -1;
total += secs;
if (total < 0)
return -1;
@@ -369,7 +562,7 @@ put_host_port(const char *host, u_short port)
if (port == 0 || port == SSH_DEFAULT_PORT)
return(xstrdup(host));
- if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0)
+ if (asprintf(&hoststr, "[%s]:%d", host, (int)port) == -1)
fatal("put_host_port: asprintf: %s", strerror(errno));
debug3("put_host_port: %s", hoststr);
return hoststr;
@@ -379,11 +572,12 @@ put_host_port(const char *host, u_short port)
* Search for next delimiter between hostnames/addresses and ports.
* Argument may be modified (for termination).
* Returns *cp if parsing succeeds.
- * *cp is set to the start of the next delimiter, if one was found.
+ * *cp is set to the start of the next field, if one was found.
+ * The delimiter char, if present, is stored in delim.
* If this is the last field, *cp is set to NULL.
*/
char *
-hpdelim(char **cp)
+hpdelim2(char **cp, char *delim)
{
char *s, *old;
@@ -406,6 +600,8 @@ hpdelim(char **cp)
case ':':
case '/':
+ if (delim != NULL)
+ *delim = *s;
*s = '\0'; /* terminate */
*cp = s + 1;
break;
@@ -418,6 +614,12 @@ hpdelim(char **cp)
}
char *
+hpdelim(char **cp)
+{
+ return hpdelim2(cp, NULL);
+}
+
+char *
cleanhostname(char *host)
{
if (*host == '[' && host[strlen(host) - 1] == ']') {
@@ -450,6 +652,298 @@ colon(char *cp)
return NULL;
}
+/*
+ * Parse a [user@]host:[path] string.
+ * Caller must free returned user, host and path.
+ * Any of the pointer return arguments may be NULL (useful for syntax checking).
+ * If user was not specified then *userp will be set to NULL.
+ * If host was not specified then *hostp will be set to NULL.
+ * If path was not specified then *pathp will be set to ".".
+ * Returns 0 on success, -1 on failure.
+ */
+int
+parse_user_host_path(const char *s, char **userp, char **hostp, char **pathp)
+{
+ char *user = NULL, *host = NULL, *path = NULL;
+ char *sdup, *tmp;
+ int ret = -1;
+
+ if (userp != NULL)
+ *userp = NULL;
+ if (hostp != NULL)
+ *hostp = NULL;
+ if (pathp != NULL)
+ *pathp = NULL;
+
+ sdup = xstrdup(s);
+
+ /* Check for remote syntax: [user@]host:[path] */
+ if ((tmp = colon(sdup)) == NULL)
+ goto out;
+
+ /* Extract optional path */
+ *tmp++ = '\0';
+ if (*tmp == '\0')
+ tmp = ".";
+ path = xstrdup(tmp);
+
+ /* Extract optional user and mandatory host */
+ tmp = strrchr(sdup, '@');
+ if (tmp != NULL) {
+ *tmp++ = '\0';
+ host = xstrdup(cleanhostname(tmp));
+ if (*sdup != '\0')
+ user = xstrdup(sdup);
+ } else {
+ host = xstrdup(cleanhostname(sdup));
+ user = NULL;
+ }
+
+ /* Success */
+ if (userp != NULL) {
+ *userp = user;
+ user = NULL;
+ }
+ if (hostp != NULL) {
+ *hostp = host;
+ host = NULL;
+ }
+ if (pathp != NULL) {
+ *pathp = path;
+ path = NULL;
+ }
+ ret = 0;
+out:
+ free(sdup);
+ free(user);
+ free(host);
+ free(path);
+ return ret;
+}
+
+/*
+ * Parse a [user@]host[:port] string.
+ * Caller must free returned user and host.
+ * Any of the pointer return arguments may be NULL (useful for syntax checking).
+ * If user was not specified then *userp will be set to NULL.
+ * If port was not specified then *portp will be -1.
+ * Returns 0 on success, -1 on failure.
+ */
+int
+parse_user_host_port(const char *s, char **userp, char **hostp, int *portp)
+{
+ char *sdup, *cp, *tmp;
+ char *user = NULL, *host = NULL;
+ int port = -1, ret = -1;
+
+ if (userp != NULL)
+ *userp = NULL;
+ if (hostp != NULL)
+ *hostp = NULL;
+ if (portp != NULL)
+ *portp = -1;
+
+ if ((sdup = tmp = strdup(s)) == NULL)
+ return -1;
+ /* Extract optional username */
+ if ((cp = strrchr(tmp, '@')) != NULL) {
+ *cp = '\0';
+ if (*tmp == '\0')
+ goto out;
+ if ((user = strdup(tmp)) == NULL)
+ goto out;
+ tmp = cp + 1;
+ }
+ /* Extract mandatory hostname */
+ if ((cp = hpdelim(&tmp)) == NULL || *cp == '\0')
+ goto out;
+ host = xstrdup(cleanhostname(cp));
+ /* Convert and verify optional port */
+ if (tmp != NULL && *tmp != '\0') {
+ if ((port = a2port(tmp)) <= 0)
+ goto out;
+ }
+ /* Success */
+ if (userp != NULL) {
+ *userp = user;
+ user = NULL;
+ }
+ if (hostp != NULL) {
+ *hostp = host;
+ host = NULL;
+ }
+ if (portp != NULL)
+ *portp = port;
+ ret = 0;
+ out:
+ free(sdup);
+ free(user);
+ free(host);
+ return ret;
+}
+
+/*
+ * Converts a two-byte hex string to decimal.
+ * Returns the decimal value or -1 for invalid input.
+ */
+static int
+hexchar(const char *s)
+{
+ unsigned char result[2];
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ if (s[i] >= '0' && s[i] <= '9')
+ result[i] = (unsigned char)(s[i] - '0');
+ else if (s[i] >= 'a' && s[i] <= 'f')
+ result[i] = (unsigned char)(s[i] - 'a') + 10;
+ else if (s[i] >= 'A' && s[i] <= 'F')
+ result[i] = (unsigned char)(s[i] - 'A') + 10;
+ else
+ return -1;
+ }
+ return (result[0] << 4) | result[1];
+}
+
+/*
+ * Decode an url-encoded string.
+ * Returns a newly allocated string on success or NULL on failure.
+ */
+static char *
+urldecode(const char *src)
+{
+ char *ret, *dst;
+ int ch;
+
+ ret = xmalloc(strlen(src) + 1);
+ for (dst = ret; *src != '\0'; src++) {
+ switch (*src) {
+ case '+':
+ *dst++ = ' ';
+ break;
+ case '%':
+ if (!isxdigit((unsigned char)src[1]) ||
+ !isxdigit((unsigned char)src[2]) ||
+ (ch = hexchar(src + 1)) == -1) {
+ free(ret);
+ return NULL;
+ }
+ *dst++ = ch;
+ src += 2;
+ break;
+ default:
+ *dst++ = *src;
+ break;
+ }
+ }
+ *dst = '\0';
+
+ return ret;
+}
+
+/*
+ * Parse an (scp|ssh|sftp)://[user@]host[:port][/path] URI.
+ * See https://tools.ietf.org/html/draft-ietf-secsh-scp-sftp-ssh-uri-04
+ * Either user or path may be url-encoded (but not host or port).
+ * Caller must free returned user, host and path.
+ * Any of the pointer return arguments may be NULL (useful for syntax checking)
+ * but the scheme must always be specified.
+ * If user was not specified then *userp will be set to NULL.
+ * If port was not specified then *portp will be -1.
+ * If path was not specified then *pathp will be set to NULL.
+ * Returns 0 on success, 1 if non-uri/wrong scheme, -1 on error/invalid uri.
+ */
+int
+parse_uri(const char *scheme, const char *uri, char **userp, char **hostp,
+ int *portp, char **pathp)
+{
+ char *uridup, *cp, *tmp, ch;
+ char *user = NULL, *host = NULL, *path = NULL;
+ int port = -1, ret = -1;
+ size_t len;
+
+ len = strlen(scheme);
+ if (strncmp(uri, scheme, len) != 0 || strncmp(uri + len, "://", 3) != 0)
+ return 1;
+ uri += len + 3;
+
+ if (userp != NULL)
+ *userp = NULL;
+ if (hostp != NULL)
+ *hostp = NULL;
+ if (portp != NULL)
+ *portp = -1;
+ if (pathp != NULL)
+ *pathp = NULL;
+
+ uridup = tmp = xstrdup(uri);
+
+ /* Extract optional ssh-info (username + connection params) */
+ if ((cp = strchr(tmp, '@')) != NULL) {
+ char *delim;
+
+ *cp = '\0';
+ /* Extract username and connection params */
+ if ((delim = strchr(tmp, ';')) != NULL) {
+ /* Just ignore connection params for now */
+ *delim = '\0';
+ }
+ if (*tmp == '\0') {
+ /* Empty username */
+ goto out;
+ }
+ if ((user = urldecode(tmp)) == NULL)
+ goto out;
+ tmp = cp + 1;
+ }
+
+ /* Extract mandatory hostname */
+ if ((cp = hpdelim2(&tmp, &ch)) == NULL || *cp == '\0')
+ goto out;
+ host = xstrdup(cleanhostname(cp));
+ if (!valid_domain(host, 0, NULL))
+ goto out;
+
+ if (tmp != NULL && *tmp != '\0') {
+ if (ch == ':') {
+ /* Convert and verify port. */
+ if ((cp = strchr(tmp, '/')) != NULL)
+ *cp = '\0';
+ if ((port = a2port(tmp)) <= 0)
+ goto out;
+ tmp = cp ? cp + 1 : NULL;
+ }
+ if (tmp != NULL && *tmp != '\0') {
+ /* Extract optional path */
+ if ((path = urldecode(tmp)) == NULL)
+ goto out;
+ }
+ }
+
+ /* Success */
+ if (userp != NULL) {
+ *userp = user;
+ user = NULL;
+ }
+ if (hostp != NULL) {
+ *hostp = host;
+ host = NULL;
+ }
+ if (portp != NULL)
+ *portp = port;
+ if (pathp != NULL) {
+ *pathp = path;
+ path = NULL;
+ }
+ ret = 0;
+ out:
+ free(uridup);
+ free(user);
+ free(host);
+ free(path);
+ return ret;
+}
+
/* function to assist building execv() arguments */
void
addargs(arglist *args, char *fmt, ...)
@@ -472,7 +966,7 @@ addargs(arglist *args, char *fmt, ...)
} else if (args->num+2 >= nalloc)
nalloc *= 2;
- args->list = xrealloc(args->list, nalloc, sizeof(char *));
+ args->list = xrecallocarray(args->list, args->nalloc, nalloc, sizeof(char *));
args->nalloc = nalloc;
args->list[args->num++] = cp;
args->list[args->num] = NULL;
@@ -567,13 +1061,18 @@ char *
percent_expand(const char *string, ...)
{
#define EXPAND_MAX_KEYS 16
- u_int num_keys, i, j;
+ u_int num_keys, i;
struct {
const char *key;
const char *repl;
} keys[EXPAND_MAX_KEYS];
- char buf[4096];
+ struct sshbuf *buf;
va_list ap;
+ int r;
+ char *ret;
+
+ if ((buf = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
/* Gather keys */
va_start(ap, string);
@@ -590,125 +1089,113 @@ percent_expand(const char *string, ...)
va_end(ap);
/* Expand string */
- *buf = '\0';
for (i = 0; *string != '\0'; string++) {
if (*string != '%') {
append:
- buf[i++] = *string;
- if (i >= sizeof(buf))
- fatal("%s: string too long", __func__);
- buf[i] = '\0';
+ if ((r = sshbuf_put_u8(buf, *string)) != 0) {
+ fatal("%s: sshbuf_put_u8: %s",
+ __func__, ssh_err(r));
+ }
continue;
}
string++;
/* %% case */
if (*string == '%')
goto append;
- for (j = 0; j < num_keys; j++) {
- if (strchr(keys[j].key, *string) != NULL) {
- i = strlcat(buf, keys[j].repl, sizeof(buf));
- if (i >= sizeof(buf))
- fatal("%s: string too long", __func__);
+ if (*string == '\0')
+ fatal("%s: invalid format", __func__);
+ 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));
+ }
break;
}
}
- if (j >= num_keys)
+ if (i >= num_keys)
fatal("%s: unknown key %%%c", __func__, *string);
}
- return (xstrdup(buf));
+ if ((ret = sshbuf_dup_string(buf)) == NULL)
+ fatal("%s: sshbuf_dup_string failed", __func__);
+ sshbuf_free(buf);
+ return ret;
#undef EXPAND_MAX_KEYS
}
-/*
- * Read an entire line from a public key file into a static buffer, discarding
- * lines that exceed the buffer size. Returns 0 on success, -1 on failure.
- */
-int
-read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
- u_long *lineno)
-{
- while (fgets(buf, bufsz, f) != NULL) {
- if (buf[0] == '\0')
- continue;
- (*lineno)++;
- if (buf[strlen(buf) - 1] == '\n' || feof(f)) {
- return 0;
- } else {
- debug("%s: %s line %lu exceeds size limit", __func__,
- filename, *lineno);
- /* discard remainder of line */
- while (fgetc(f) != '\n' && !feof(f))
- ; /* nothing */
- }
- }
- return -1;
-}
-
int
-tun_open(int tun, int mode)
+tun_open(int tun, int mode, char **ifname)
{
#if defined(CUSTOM_SYS_TUN_OPEN)
- return (sys_tun_open(tun, mode));
+ return (sys_tun_open(tun, mode, ifname));
#elif defined(SSH_TUN_OPENBSD)
struct ifreq ifr;
char name[100];
int fd = -1, sock;
+ const char *tunbase = "tun";
+
+ if (ifname != NULL)
+ *ifname = NULL;
+
+ if (mode == SSH_TUNMODE_ETHERNET)
+ tunbase = "tap";
/* Open the tunnel device */
if (tun <= SSH_TUNID_MAX) {
- snprintf(name, sizeof(name), "/dev/tun%d", tun);
+ snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun);
fd = open(name, O_RDWR);
} else if (tun == SSH_TUNID_ANY) {
for (tun = 100; tun >= 0; tun--) {
- snprintf(name, sizeof(name), "/dev/tun%d", tun);
+ snprintf(name, sizeof(name), "/dev/%s%d",
+ tunbase, tun);
if ((fd = open(name, O_RDWR)) >= 0)
break;
}
} else {
debug("%s: invalid tunnel %u", __func__, tun);
- return (-1);
+ return -1;
}
- if (fd < 0) {
- debug("%s: %s open failed: %s", __func__, name, strerror(errno));
- return (-1);
+ if (fd == -1) {
+ debug("%s: %s open: %s", __func__, name, strerror(errno));
+ return -1;
}
debug("%s: %s mode %d fd %d", __func__, name, mode, fd);
- /* Set the tunnel device operation mode */
- snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun);
+ /* Bring interface up if it is not already */
+ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun);
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
goto failed;
- if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
+ if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
+ debug("%s: get interface %s flags: %s", __func__,
+ ifr.ifr_name, strerror(errno));
goto failed;
+ }
- /* Set interface mode */
- ifr.ifr_flags &= ~IFF_UP;
- if (mode == SSH_TUNMODE_ETHERNET)
- ifr.ifr_flags |= IFF_LINK0;
- else
- ifr.ifr_flags &= ~IFF_LINK0;
- if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
- goto failed;
+ if (!(ifr.ifr_flags & IFF_UP)) {
+ ifr.ifr_flags |= IFF_UP;
+ if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
+ debug("%s: activate interface %s: %s", __func__,
+ ifr.ifr_name, strerror(errno));
+ goto failed;
+ }
+ }
- /* Bring interface up */
- ifr.ifr_flags |= IFF_UP;
- if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
- goto failed;
+ if (ifname != NULL)
+ *ifname = xstrdup(ifr.ifr_name);
close(sock);
- return (fd);
+ return fd;
failed:
if (fd >= 0)
close(fd);
if (sock >= 0)
close(sock);
- debug("%s: failed to set %s mode %d: %s", __func__, name,
- mode, strerror(errno));
- return (-1);
+ return -1;
#else
error("Tunnel interfaces are not supported on this platform");
return (-1);
@@ -725,16 +1212,16 @@ sanitise_stdfd(void)
strerror(errno));
exit(1);
}
- while (++dupfd <= 2) {
- /* Only clobber closed fds */
- if (fcntl(dupfd, F_GETFL, 0) >= 0)
- continue;
- if (dup2(nullfd, dupfd) == -1) {
- fprintf(stderr, "dup2: %s\n", strerror(errno));
- exit(1);
+ while (++dupfd <= STDERR_FILENO) {
+ /* Only populate closed fds. */
+ if (fcntl(dupfd, F_GETFL) == -1 && errno == EBADF) {
+ if (dup2(nullfd, dupfd) == -1) {
+ fprintf(stderr, "dup2: %s\n", strerror(errno));
+ exit(1);
+ }
}
}
- if (nullfd > 2)
+ if (nullfd > STDERR_FILENO)
close(nullfd);
}
@@ -757,6 +1244,33 @@ tohex(const void *vp, size_t l)
return (r);
}
+/*
+ * Extend string *sp by the specified format. If *sp is not NULL (or empty),
+ * then the separator 'sep' will be prepended before the formatted arguments.
+ * Extended strings are heap allocated.
+ */
+void
+xextendf(char **sp, const char *sep, const char *fmt, ...)
+{
+ va_list ap;
+ char *tmp1, *tmp2;
+
+ va_start(ap, fmt);
+ xvasprintf(&tmp1, fmt, ap);
+ va_end(ap);
+
+ if (*sp == NULL || **sp == '\0') {
+ free(*sp);
+ *sp = tmp1;
+ return;
+ }
+ xasprintf(&tmp2, "%s%s%s", *sp, sep == NULL ? "" : sep, tmp1);
+ free(tmp1);
+ free(*sp);
+ *sp = tmp2;
+}
+
+
u_int64_t
get_u64(const void *vp)
{
@@ -866,8 +1380,8 @@ ms_subtract_diff(struct timeval *start, int *ms)
{
struct timeval diff, finish;
- gettimeofday(&finish, NULL);
- timersub(&finish, start, &diff);
+ monotime_tv(&finish);
+ timersub(&finish, start, &diff);
*ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000);
}
@@ -880,29 +1394,63 @@ ms_to_timeval(struct timeval *tv, int ms)
tv->tv_usec = (ms % 1000) * 1000;
}
-time_t
-monotime(void)
+void
+monotime_ts(struct timespec *ts)
{
-#if defined(HAVE_CLOCK_GETTIME) && \
- (defined(CLOCK_MONOTONIC) || defined(CLOCK_BOOTTIME))
- struct timespec ts;
+ struct timeval tv;
+#if defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_BOOTTIME) || \
+ defined(CLOCK_MONOTONIC) || defined(CLOCK_REALTIME))
static int gettime_failed = 0;
if (!gettime_failed) {
-#if defined(CLOCK_BOOTTIME)
- if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0)
- return (ts.tv_sec);
-#endif
-#if defined(CLOCK_MONOTONIC)
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
- return (ts.tv_sec);
-#endif
+# ifdef CLOCK_BOOTTIME
+ if (clock_gettime(CLOCK_BOOTTIME, ts) == 0)
+ return;
+# endif /* CLOCK_BOOTTIME */
+# ifdef CLOCK_MONOTONIC
+ if (clock_gettime(CLOCK_MONOTONIC, ts) == 0)
+ return;
+# endif /* CLOCK_MONOTONIC */
+# ifdef CLOCK_REALTIME
+ /* Not monotonic, but we're almost out of options here. */
+ if (clock_gettime(CLOCK_REALTIME, ts) == 0)
+ return;
+# endif /* CLOCK_REALTIME */
debug3("clock_gettime: %s", strerror(errno));
gettime_failed = 1;
}
-#endif /* HAVE_CLOCK_GETTIME && (CLOCK_MONOTONIC || CLOCK_BOOTTIME */
+#endif /* HAVE_CLOCK_GETTIME && (BOOTTIME || MONOTONIC || REALTIME) */
+ gettimeofday(&tv, NULL);
+ ts->tv_sec = tv.tv_sec;
+ ts->tv_nsec = (long)tv.tv_usec * 1000;
+}
- return time(NULL);
+void
+monotime_tv(struct timeval *tv)
+{
+ struct timespec ts;
+
+ monotime_ts(&ts);
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+}
+
+time_t
+monotime(void)
+{
+ struct timespec ts;
+
+ monotime_ts(&ts);
+ return ts.tv_sec;
+}
+
+double
+monotime_double(void)
+{
+ struct timespec ts;
+
+ monotime_ts(&ts);
+ return ts.tv_sec + ((double)ts.tv_nsec / 1000000000);
}
void
@@ -910,11 +1458,11 @@ bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen)
{
bw->buflen = buflen;
bw->rate = kbps;
- bw->thresh = bw->rate;
+ bw->thresh = buflen;
bw->lamt = 0;
timerclear(&bw->bwstart);
timerclear(&bw->bwend);
-}
+}
/* Callback from read/write loop to insert bandwidth-limiting delays */
void
@@ -923,16 +1471,15 @@ bandwidth_limit(struct bwlimit *bw, size_t read_len)
u_int64_t waitlen;
struct timespec ts, rm;
+ bw->lamt += read_len;
if (!timerisset(&bw->bwstart)) {
- gettimeofday(&bw->bwstart, NULL);
+ monotime_tv(&bw->bwstart);
return;
}
-
- bw->lamt += read_len;
if (bw->lamt < bw->thresh)
return;
- gettimeofday(&bw->bwend, NULL);
+ monotime_tv(&bw->bwend);
timersub(&bw->bwend, &bw->bwstart, &bw->bwend);
if (!timerisset(&bw->bwend))
return;
@@ -966,7 +1513,7 @@ bandwidth_limit(struct bwlimit *bw, size_t read_len)
}
bw->lamt = 0;
- gettimeofday(&bw->bwstart, NULL);
+ monotime_tv(&bw->bwstart);
}
/* Make a template filename for mk[sd]temp() */
@@ -990,6 +1537,7 @@ static const struct {
const char *name;
int value;
} ipqos[] = {
+ { "none", INT_MAX }, /* can't use 0 here; that's CS0 */
{ "af11", IPTOS_DSCP_AF11 },
{ "af12", IPTOS_DSCP_AF12 },
{ "af13", IPTOS_DSCP_AF13 },
@@ -1011,6 +1559,7 @@ static const struct {
{ "cs6", IPTOS_DSCP_CS6 },
{ "cs7", IPTOS_DSCP_CS7 },
{ "ef", IPTOS_DSCP_EF },
+ { "le", IPTOS_DSCP_LE },
{ "lowdelay", IPTOS_LOWDELAY },
{ "throughput", IPTOS_THROUGHPUT },
{ "reliability", IPTOS_RELIABILITY },
@@ -1066,17 +1615,18 @@ unix_listener(const char *path, int backlog, int unlink_first)
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
- if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) {
- error("%s: \"%s\" too long for Unix domain socket", __func__,
- path);
+ if (strlcpy(sunaddr.sun_path, path,
+ sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) {
+ error("%s: path \"%s\" too long for Unix domain socket",
+ __func__, path);
errno = ENAMETOOLONG;
return -1;
}
sock = socket(PF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
+ if (sock == -1) {
saved_errno = errno;
- error("socket: %.100s", strerror(errno));
+ error("%s: socket: %.100s", __func__, strerror(errno));
errno = saved_errno;
return -1;
}
@@ -1084,20 +1634,20 @@ unix_listener(const char *path, int backlog, int unlink_first)
if (unlink(path) != 0 && errno != ENOENT)
error("unlink(%s): %.100s", path, strerror(errno));
}
- if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
+ if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) {
saved_errno = errno;
- error("bind: %.100s", strerror(errno));
+ error("%s: cannot bind to path %s: %s",
+ __func__, path, strerror(errno));
close(sock);
- error("%s: cannot bind to path: %s", __func__, path);
errno = saved_errno;
return -1;
}
- if (listen(sock, backlog) < 0) {
+ if (listen(sock, backlog) == -1) {
saved_errno = errno;
- error("listen: %.100s", strerror(errno));
+ error("%s: cannot listen on path %s: %s",
+ __func__, path, strerror(errno));
close(sock);
unlink(path);
- error("%s: cannot listen on path: %s", __func__, path);
errno = saved_errno;
return -1;
}
@@ -1107,7 +1657,7 @@ unix_listener(const char *path, int backlog, int unlink_first)
void
sock_set_v6only(int s)
{
-#ifdef IPV6_V6ONLY
+#if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
int on = 1;
debug3("%s: set socket %d IPV6_V6ONLY", __func__, s);
@@ -1115,3 +1665,611 @@ sock_set_v6only(int s)
error("setsockopt IPV6_V6ONLY: %s", strerror(errno));
#endif
}
+
+/*
+ * Compares two strings that maybe be NULL. Returns non-zero if strings
+ * are both NULL or are identical, returns zero otherwise.
+ */
+static int
+strcmp_maybe_null(const char *a, const char *b)
+{
+ if ((a == NULL && b != NULL) || (a != NULL && b == NULL))
+ return 0;
+ if (a != NULL && strcmp(a, b) != 0)
+ return 0;
+ return 1;
+}
+
+/*
+ * Compare two forwards, returning non-zero if they are identical or
+ * zero otherwise.
+ */
+int
+forward_equals(const struct Forward *a, const struct Forward *b)
+{
+ if (strcmp_maybe_null(a->listen_host, b->listen_host) == 0)
+ return 0;
+ if (a->listen_port != b->listen_port)
+ return 0;
+ if (strcmp_maybe_null(a->listen_path, b->listen_path) == 0)
+ return 0;
+ if (strcmp_maybe_null(a->connect_host, b->connect_host) == 0)
+ return 0;
+ if (a->connect_port != b->connect_port)
+ return 0;
+ if (strcmp_maybe_null(a->connect_path, b->connect_path) == 0)
+ return 0;
+ /* allocated_port and handle are not checked */
+ return 1;
+}
+
+/* returns 1 if process is already daemonized, 0 otherwise */
+int
+daemonized(void)
+{
+ int fd;
+
+ if ((fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY)) >= 0) {
+ close(fd);
+ return 0; /* have controlling terminal */
+ }
+ if (getppid() != 1)
+ return 0; /* parent is not init */
+ if (getsid(0) != getpid())
+ return 0; /* not session leader */
+ debug3("already daemonized");
+ return 1;
+}
+
+
+/*
+ * Splits 's' into an argument vector. Handles quoted string and basic
+ * escape characters (\\, \", \'). Caller must free the argument vector
+ * and its members.
+ */
+int
+argv_split(const char *s, int *argcp, char ***argvp)
+{
+ int r = SSH_ERR_INTERNAL_ERROR;
+ int argc = 0, quote, i, j;
+ char *arg, **argv = xcalloc(1, sizeof(*argv));
+
+ *argvp = NULL;
+ *argcp = 0;
+
+ for (i = 0; s[i] != '\0'; i++) {
+ /* Skip leading whitespace */
+ if (s[i] == ' ' || s[i] == '\t')
+ continue;
+
+ /* Start of a token */
+ quote = 0;
+ if (s[i] == '\\' &&
+ (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\'))
+ i++;
+ else if (s[i] == '\'' || s[i] == '"')
+ quote = s[i++];
+
+ argv = xreallocarray(argv, (argc + 2), sizeof(*argv));
+ arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1);
+ argv[argc] = NULL;
+
+ /* Copy the token in, removing escapes */
+ for (j = 0; s[i] != '\0'; i++) {
+ if (s[i] == '\\') {
+ if (s[i + 1] == '\'' ||
+ s[i + 1] == '\"' ||
+ s[i + 1] == '\\') {
+ i++; /* Skip '\' */
+ arg[j++] = s[i];
+ } else {
+ /* Unrecognised escape */
+ arg[j++] = s[i];
+ }
+ } else if (quote == 0 && (s[i] == ' ' || s[i] == '\t'))
+ break; /* done */
+ else if (quote != 0 && s[i] == quote)
+ break; /* done */
+ else
+ arg[j++] = s[i];
+ }
+ if (s[i] == '\0') {
+ if (quote != 0) {
+ /* Ran out of string looking for close quote */
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ break;
+ }
+ }
+ /* Success */
+ *argcp = argc;
+ *argvp = argv;
+ argc = 0;
+ argv = NULL;
+ r = 0;
+ out:
+ if (argc != 0 && argv != NULL) {
+ for (i = 0; i < argc; i++)
+ free(argv[i]);
+ free(argv);
+ }
+ return r;
+}
+
+/*
+ * Reassemble an argument vector into a string, quoting and escaping as
+ * necessary. Caller must free returned string.
+ */
+char *
+argv_assemble(int argc, char **argv)
+{
+ int i, j, ws, r;
+ char c, *ret;
+ struct sshbuf *buf, *arg;
+
+ if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+
+ for (i = 0; i < argc; i++) {
+ ws = 0;
+ sshbuf_reset(arg);
+ for (j = 0; argv[i][j] != '\0'; j++) {
+ r = 0;
+ c = argv[i][j];
+ switch (c) {
+ case ' ':
+ case '\t':
+ ws = 1;
+ r = sshbuf_put_u8(arg, c);
+ break;
+ case '\\':
+ case '\'':
+ case '"':
+ if ((r = sshbuf_put_u8(arg, '\\')) != 0)
+ break;
+ /* FALLTHROUGH */
+ default:
+ r = sshbuf_put_u8(arg, c);
+ break;
+ }
+ if (r != 0)
+ fatal("%s: sshbuf_put_u8: %s",
+ __func__, ssh_err(r));
+ }
+ if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) ||
+ (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) ||
+ (r = sshbuf_putb(buf, arg)) != 0 ||
+ (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0))
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ }
+ if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL)
+ fatal("%s: malloc failed", __func__);
+ memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf));
+ ret[sshbuf_len(buf)] = '\0';
+ sshbuf_free(buf);
+ sshbuf_free(arg);
+ return ret;
+}
+
+/* Returns 0 if pid exited cleanly, non-zero otherwise */
+int
+exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet)
+{
+ int status;
+
+ while (waitpid(pid, &status, 0) == -1) {
+ if (errno != EINTR) {
+ error("%s: waitpid: %s", tag, strerror(errno));
+ return -1;
+ }
+ }
+ if (WIFSIGNALED(status)) {
+ error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status));
+ return -1;
+ } else if (WEXITSTATUS(status) != 0) {
+ do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO,
+ "%s %s failed, status %d", tag, cmd, WEXITSTATUS(status));
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Check a given path for security. This is defined as all components
+ * of the path to the file must be owned by either the owner of
+ * of the file or root and no directories must be group or world writable.
+ *
+ * XXX Should any specific check be done for sym links ?
+ *
+ * Takes a file name, its stat information (preferably from fstat() to
+ * avoid races), the uid of the expected owner, their home directory and an
+ * error buffer plus max size as arguments.
+ *
+ * Returns 0 on success and -1 on failure
+ */
+int
+safe_path(const char *name, struct stat *stp, const char *pw_dir,
+ uid_t uid, char *err, size_t errlen)
+{
+ char buf[PATH_MAX], homedir[PATH_MAX];
+ char *cp;
+ int comparehome = 0;
+#if !defined(ANDROID)
+ struct stat st;
+#endif
+
+ if (realpath(name, buf) == NULL) {
+ snprintf(err, errlen, "realpath %s failed: %s", name,
+ strerror(errno));
+ return -1;
+ }
+ if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
+ comparehome = 1;
+
+ if (!S_ISREG(stp->st_mode)) {
+ snprintf(err, errlen, "%s is not a regular file", buf);
+ return -1;
+ }
+ if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
+ (stp->st_mode & 022) != 0) {
+ snprintf(err, errlen, "bad ownership or modes for file %s",
+ buf);
+ return -1;
+ }
+
+ /* for each component of the canonical path, walking upwards */
+ for (;;) {
+ if ((cp = dirname(buf)) == NULL) {
+ snprintf(err, errlen, "dirname() failed");
+ return -1;
+ }
+ strlcpy(buf, cp, sizeof(buf));
+
+#if !defined(ANDROID)
+ /* /data is owned by system user, which causes this check to fail */
+ if (stat(buf, &st) == -1 ||
+ (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
+ (st.st_mode & 022) != 0) {
+ snprintf(err, errlen,
+ "bad ownership or modes for directory %s", buf);
+ return -1;
+ }
+#endif
+
+ /* If are past the homedir then we can stop */
+ if (comparehome && strcmp(homedir, buf) == 0)
+ break;
+
+ /*
+ * dirname should always complete with a "/" path,
+ * but we can be paranoid and check for "." too
+ */
+ if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Version of safe_path() that accepts an open file descriptor to
+ * avoid races.
+ *
+ * Returns 0 on success and -1 on failure
+ */
+int
+safe_path_fd(int fd, const char *file, struct passwd *pw,
+ char *err, size_t errlen)
+{
+ struct stat st;
+
+ /* check the open file to avoid races */
+ if (fstat(fd, &st) == -1) {
+ snprintf(err, errlen, "cannot stat file %s: %s",
+ file, strerror(errno));
+ return -1;
+ }
+ return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
+}
+
+/*
+ * Sets the value of the given variable in the environment. If the variable
+ * already exists, its value is overridden.
+ */
+void
+child_set_env(char ***envp, u_int *envsizep, const char *name,
+ const char *value)
+{
+ char **env;
+ u_int envsize;
+ u_int i, namelen;
+
+ if (strchr(name, '=') != NULL) {
+ error("Invalid environment variable \"%.100s\"", name);
+ return;
+ }
+
+ /*
+ * If we're passed an uninitialized list, allocate a single null
+ * entry before continuing.
+ */
+ if (*envp == NULL && *envsizep == 0) {
+ *envp = xmalloc(sizeof(char *));
+ *envp[0] = NULL;
+ *envsizep = 1;
+ }
+
+ /*
+ * Find the slot where the value should be stored. If the variable
+ * already exists, we reuse the slot; otherwise we append a new slot
+ * at the end of the array, expanding if necessary.
+ */
+ env = *envp;
+ namelen = strlen(name);
+ for (i = 0; env[i]; i++)
+ if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
+ break;
+ if (env[i]) {
+ /* Reuse the slot. */
+ free(env[i]);
+ } else {
+ /* New variable. Expand if necessary. */
+ envsize = *envsizep;
+ if (i >= envsize - 1) {
+ if (envsize >= 1000)
+ fatal("child_set_env: too many env vars");
+ envsize += 50;
+ env = (*envp) = xreallocarray(env, envsize, sizeof(char *));
+ *envsizep = envsize;
+ }
+ /* Need to set the NULL pointer at end of array beyond the new slot. */
+ env[i + 1] = NULL;
+ }
+
+ /* Allocate space and format the variable in the appropriate slot. */
+ /* XXX xasprintf */
+ env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
+ snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
+}
+
+/*
+ * Check and optionally lowercase a domain name, also removes trailing '.'
+ * Returns 1 on success and 0 on failure, storing an error message in errstr.
+ */
+int
+valid_domain(char *name, int makelower, const char **errstr)
+{
+ size_t i, l = strlen(name);
+ u_char c, last = '\0';
+ static char errbuf[256];
+
+ if (l == 0) {
+ strlcpy(errbuf, "empty domain name", sizeof(errbuf));
+ goto bad;
+ }
+ if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0])) {
+ snprintf(errbuf, sizeof(errbuf), "domain name \"%.100s\" "
+ "starts with invalid character", name);
+ goto bad;
+ }
+ for (i = 0; i < l; i++) {
+ c = tolower((u_char)name[i]);
+ if (makelower)
+ name[i] = (char)c;
+ if (last == '.' && c == '.') {
+ snprintf(errbuf, sizeof(errbuf), "domain name "
+ "\"%.100s\" contains consecutive separators", name);
+ goto bad;
+ }
+ if (c != '.' && c != '-' && !isalnum(c) &&
+ c != '_') /* technically invalid, but common */ {
+ snprintf(errbuf, sizeof(errbuf), "domain name "
+ "\"%.100s\" contains invalid characters", name);
+ goto bad;
+ }
+ last = c;
+ }
+ if (name[l - 1] == '.')
+ name[l - 1] = '\0';
+ if (errstr != NULL)
+ *errstr = NULL;
+ return 1;
+bad:
+ if (errstr != NULL)
+ *errstr = errbuf;
+ return 0;
+}
+
+/*
+ * Verify that a environment variable name (not including initial '$') is
+ * valid; consisting of one or more alphanumeric or underscore characters only.
+ * Returns 1 on valid, 0 otherwise.
+ */
+int
+valid_env_name(const char *name)
+{
+ const char *cp;
+
+ if (name[0] == '\0')
+ return 0;
+ for (cp = name; *cp != '\0'; cp++) {
+ if (!isalnum((u_char)*cp) && *cp != '_')
+ return 0;
+ }
+ return 1;
+}
+
+const char *
+atoi_err(const char *nptr, int *val)
+{
+ const char *errstr = NULL;
+ long long num;
+
+ if (nptr == NULL || *nptr == '\0')
+ return "missing";
+ num = strtonum(nptr, 0, INT_MAX, &errstr);
+ if (errstr == NULL)
+ *val = (int)num;
+ return errstr;
+}
+
+int
+parse_absolute_time(const char *s, uint64_t *tp)
+{
+ struct tm tm;
+ time_t tt;
+ char buf[32], *fmt;
+
+ *tp = 0;
+
+ /*
+ * POSIX strptime says "The application shall ensure that there
+ * is white-space or other non-alphanumeric characters between
+ * any two conversion specifications" so arrange things this way.
+ */
+ switch (strlen(s)) {
+ case 8: /* YYYYMMDD */
+ fmt = "%Y-%m-%d";
+ snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6);
+ break;
+ case 12: /* YYYYMMDDHHMM */
+ fmt = "%Y-%m-%dT%H:%M";
+ snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s",
+ s, s + 4, s + 6, s + 8, s + 10);
+ break;
+ case 14: /* YYYYMMDDHHMMSS */
+ fmt = "%Y-%m-%dT%H:%M:%S";
+ snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s",
+ s, s + 4, s + 6, s + 8, s + 10, s + 12);
+ break;
+ default:
+ return SSH_ERR_INVALID_FORMAT;
+ }
+
+ memset(&tm, 0, sizeof(tm));
+ if (strptime(buf, fmt, &tm) == NULL)
+ return SSH_ERR_INVALID_FORMAT;
+ if ((tt = mktime(&tm)) < 0)
+ return SSH_ERR_INVALID_FORMAT;
+ /* success */
+ *tp = (uint64_t)tt;
+ return 0;
+}
+
+void
+format_absolute_time(uint64_t t, char *buf, size_t len)
+{
+ time_t tt = t > INT_MAX ? INT_MAX : t; /* XXX revisit in 2038 :P */
+ struct tm tm;
+
+ localtime_r(&tt, &tm);
+ strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);
+}
+
+/* check if path is absolute */
+int
+path_absolute(const char *path)
+{
+ return (*path == '/') ? 1 : 0;
+}
+
+void
+skip_space(char **cpp)
+{
+ char *cp;
+
+ for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+ *cpp = cp;
+}
+
+/* authorized_key-style options parsing helpers */
+
+/*
+ * Match flag 'opt' in *optsp, and if allow_negate is set then also match
+ * 'no-opt'. Returns -1 if option not matched, 1 if option matches or 0
+ * if negated option matches.
+ * If the option or negated option matches, then *optsp is updated to
+ * point to the first character after the option.
+ */
+int
+opt_flag(const char *opt, int allow_negate, const char **optsp)
+{
+ size_t opt_len = strlen(opt);
+ const char *opts = *optsp;
+ int negate = 0;
+
+ if (allow_negate && strncasecmp(opts, "no-", 3) == 0) {
+ opts += 3;
+ negate = 1;
+ }
+ if (strncasecmp(opts, opt, opt_len) == 0) {
+ *optsp = opts + opt_len;
+ return negate ? 0 : 1;
+ }
+ return -1;
+}
+
+char *
+opt_dequote(const char **sp, const char **errstrp)
+{
+ const char *s = *sp;
+ char *ret;
+ size_t i;
+
+ *errstrp = NULL;
+ if (*s != '"') {
+ *errstrp = "missing start quote";
+ return NULL;
+ }
+ s++;
+ if ((ret = malloc(strlen((s)) + 1)) == NULL) {
+ *errstrp = "memory allocation failed";
+ return NULL;
+ }
+ for (i = 0; *s != '\0' && *s != '"';) {
+ if (s[0] == '\\' && s[1] == '"')
+ s++;
+ ret[i++] = *s++;
+ }
+ if (*s == '\0') {
+ *errstrp = "missing end quote";
+ free(ret);
+ return NULL;
+ }
+ ret[i] = '\0';
+ s++;
+ *sp = s;
+ return ret;
+}
+
+int
+opt_match(const char **opts, const char *term)
+{
+ if (strncasecmp((*opts), term, strlen(term)) == 0 &&
+ (*opts)[strlen(term)] == '=') {
+ *opts += strlen(term) + 1;
+ return 1;
+ }
+ return 0;
+}
+
+sshsig_t
+ssh_signal(int signum, sshsig_t handler)
+{
+ struct sigaction sa, osa;
+
+ /* mask all other signals while in handler */
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = handler;
+ sigfillset(&sa.sa_mask);
+#if defined(SA_RESTART) && !defined(NO_SA_RESTART)
+ if (signum != SIGALRM)
+ sa.sa_flags = SA_RESTART;
+#endif
+ if (sigaction(signum, &sa, &osa) == -1) {
+ debug3("sigaction(%s): %s", strsignal(signum), strerror(errno));
+ return SIG_ERR;
+ }
+ return osa.sa_handler;
+}
diff --git a/misc.h b/misc.h
index 374c33ce..4a05db2d 100644
--- a/misc.h
+++ b/misc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.h,v 1.54 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: misc.h,v 1.84 2020/01/24 23:54:40 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -15,6 +15,10 @@
#ifndef _MISC_H
#define _MISC_H
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
/* Data structure for representing a forwarding request. */
struct Forward {
char *listen_host; /* Host (address) to listen on. */
@@ -27,6 +31,9 @@ struct Forward {
int handle; /* Handle for dynamic listen ports */
};
+int forward_equals(const struct Forward *, const struct Forward *);
+int daemonized(void);
+
/* Common server and client forwarding options. */
struct ForwardOptions {
int gateway_ports; /* Allow remote connects to forwarded ports. */
@@ -37,26 +44,48 @@ struct ForwardOptions {
/* misc.c */
char *chop(char *);
+void skip_space(char **);
char *strdelim(char **);
+char *strdelimw(char **);
int set_nonblock(int);
int unset_nonblock(int);
void set_nodelay(int);
+int set_reuseaddr(int);
+char *get_rdomain(int);
+int set_rdomain(int, const char *);
+int waitrfd(int, int *);
+int timeout_connect(int, const struct sockaddr *, socklen_t, int *);
int a2port(const char *);
int a2tun(const char *, int *);
char *put_host_port(const char *, u_short);
+char *hpdelim2(char **, char *);
char *hpdelim(char **);
char *cleanhostname(char *);
char *colon(char *);
+int parse_user_host_path(const char *, char **, char **, char **);
+int parse_user_host_port(const char *, char **, char **, int *);
+int parse_uri(const char *, const char *, char **, char **, int *, char **);
long convtime(const char *);
char *tilde_expand_filename(const char *, uid_t);
char *percent_expand(const char *, ...) __attribute__((__sentinel__));
char *tohex(const void *, size_t);
+void xextendf(char **s, const char *sep, const char *fmt, ...)
+ __attribute__((__format__ (printf, 3, 4))) __attribute__((__nonnull__ (3)));
void sanitise_stdfd(void);
void ms_subtract_diff(struct timeval *, int *);
void ms_to_timeval(struct timeval *, int);
+void monotime_ts(struct timespec *);
+void monotime_tv(struct timeval *);
time_t monotime(void);
+double monotime_double(void);
void lowercase(char *s);
int unix_listener(const char *, int, int);
+int valid_domain(char *, int, const char **);
+int valid_env_name(const char *);
+const char *atoi_err(const char *, int *);
+int parse_absolute_time(const char *, uint64_t *);
+void format_absolute_time(uint64_t, char *, size_t);
+int path_absolute(const char *);
void sock_set_v6only(int);
@@ -75,7 +104,7 @@ void replacearg(arglist *, u_int, char *, ...)
__attribute__((format(printf, 3, 4)));
void freeargs(arglist *);
-int tun_open(int, int);
+int tun_open(int, int, char **);
/* Common definitions for ssh tunnel device forwarding */
#define SSH_TUNMODE_NO 0x00
@@ -113,7 +142,9 @@ void put_u32_le(void *, u_int32_t)
struct bwlimit {
size_t buflen;
- u_int64_t rate, thresh, lamt;
+ u_int64_t rate; /* desired rate in kbit/s */
+ u_int64_t thresh; /* threshold after which we'll check timers */
+ u_int64_t lamt; /* amount written in last timer interval */
struct timeval bwstart, bwend;
};
@@ -124,6 +155,24 @@ int parse_ipqos(const char *);
const char *iptos2str(int);
void mktemp_proto(char *, size_t);
+void child_set_env(char ***envp, u_int *envsizep, const char *name,
+ const char *value);
+
+int argv_split(const char *, int *, char ***);
+char *argv_assemble(int, char **argv);
+int exited_cleanly(pid_t, const char *, const char *, int);
+
+struct stat;
+int safe_path(const char *, struct stat *, const char *, uid_t,
+ char *, size_t);
+int safe_path_fd(int, const char *, struct passwd *,
+ char *err, size_t errlen);
+
+/* 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);
+
/* readpass.c */
#define RP_ECHO 0x0001
@@ -131,8 +180,18 @@ void mktemp_proto(char *, size_t);
#define RP_ALLOW_EOF 0x0004
#define RP_USE_ASKPASS 0x0008
+struct notifier_ctx;
+
char *read_passphrase(const char *, int);
int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
-int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
+struct notifier_ctx *notify_start(int, const char *, ...)
+ __attribute__((format(printf, 2, 3)));
+void notify_complete(struct notifier_ctx *);
+
+#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
+#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
+#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
+typedef void (*sshsig_t)(int);
+sshsig_t ssh_signal(int, sshsig_t);
#endif /* _MISC_H */
diff --git a/mkinstalldirs b/mkinstalldirs
index 47d5f43f..399f4092 100755
--- a/mkinstalldirs
+++ b/mkinstalldirs
@@ -4,8 +4,6 @@
# Created: 1993-05-16
# Public domain
-# $Id: mkinstalldirs,v 1.2 2003/11/21 12:48:55 djm Exp $
-
errstatus=0
for file
diff --git a/moduli b/moduli
index 49f76ee9..10e85440 100644
--- a/moduli
+++ b/moduli
@@ -1,262 +1,415 @@
-# $OpenBSD: moduli,v 1.8 2012/08/29 05:06:54 dtucker Exp $
+# $OpenBSD: moduli,v 1.26 2020/02/20 05:41:50 dtucker Exp $
# Time Type Tests Tries Size Generator Modulus
-20120821044040 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A770E2EC9F
-20120821044046 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A7711F2C6B
-20120821044047 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A771225323
-20120821044048 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A7712507AB
-20120821044050 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A7712A2DB3
-20120821044051 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A7712CACEF
-20120821044053 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A7713959C3
-20120821044057 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A7715BBA13
-20120821044103 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A77191592F
-20120821044104 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A771938E1F
-20120821044106 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A771A1E127
-20120821044108 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A771B3CDFB
-20120821044109 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A771B71913
-20120821044111 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A771C2759F
-20120821044113 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A771CF8ABF
-20120821044114 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A771D2B49B
-20120821044116 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A771DF6193
-20120821044117 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A771E67E33
-20120821044120 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A771FA581B
-20120821044121 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A772027DDB
-20120821044123 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A772093F8B
-20120821044124 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A7720EEF6F
-20120821044125 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A77216CAD7
-20120821044126 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A77219A90B
-20120821044129 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A7722A0103
-20120821044130 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A772343DBF
-20120821044133 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A772460C3F
-20120821044137 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A7726A4E0F
-20120821044138 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A772716D8B
-20120821044141 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A7728D719B
-20120821044143 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A77297AA8B
-20120821044145 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A772A8794B
-20120821044147 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A772B4D6AB
-20120821044149 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A772BD325F
-20120821044150 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A772BDAE07
-20120821044151 2 6 100 1023 2 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E693548310244937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F8551E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A772C95CE3
-20120821044502 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F96361507
-20120821044515 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F965885BF
-20120821044519 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F966006C7
-20120821044528 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9674A0EB
-20120821044539 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F969457F3
-20120821044544 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F969BE79B
-20120821044606 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F96E1E827
-20120821044623 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9714284B
-20120821044630 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F97231CB7
-20120821044636 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F972E01DF
-20120821044647 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F974BCED3
-20120821044650 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F974C3A43
-20120821044653 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F974E8F73
-20120821044701 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9763403B
-20120821044705 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9767666B
-20120821044708 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9768D81F
-20120821044726 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F979FD437
-20120821044729 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F97A29BC7
-20120821044732 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F97A56447
-20120821044737 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F97AEDBDB
-20120821044740 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F97B187F3
-20120821044746 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F97BC6EE3
-20120821044757 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F97DCCDEB
-20120821044817 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F981975F7
-20120821044831 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F983EC267
-20120821044841 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F985A032F
-20120821044846 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9863B0AB
-20120821044852 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F986E5C7F
-20120821044911 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F98A8FF6B
-20120821044917 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F98B40E4B
-20120821044924 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F98C5840F
-20120821044940 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F98F22CEB
-20120821044947 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F99040FFF
-20120821044954 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F99139AE3
-20120821045010 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9940BEFB
-20120821045017 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9954379F
-20120821045020 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F99548C23
-20120821045023 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F99562FC3
-20120821045028 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9960CDCF
-20120821045038 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F997AC0B3
-20120821045045 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F998D9B6B
-20120821045050 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9994BB77
-20120821045059 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F99AC001B
-20120821045101 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F99AC5547
-20120821045107 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F99B86567
-20120821045110 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F99BA2677
-20120821045128 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F99EF4523
-20120821045154 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9A419DAB
-20120821045214 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9A7D1E67
-20120821045218 2 6 100 1535 2 D1391174233D315398FE2830AC6B2B66BCCD01B0A634899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2ABD1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073F0C21B8B54C3823DB2EF068927E5D747498F9A826443
-20120821045639 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293680B09D63
-20120821045830 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C6042936814C2FFB
-20120821050046 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C60429368214FC53
-20120821050054 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C60429368218E83F
-20120821050118 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293682361D5F
-20120821050218 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C6042936828ADA17
-20120821050243 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293682A8A7CB
-20120821050427 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C60429368341AC87
-20120821050515 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C6042936837F8657
-20120821050545 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293683A3DFD3
-20120821050554 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293683A9635F
-20120821050636 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293683DF582B
-20120821050648 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293683E86803
-20120821050758 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293684495A13
-20120821050807 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C6042936844FAB5B
-20120821050849 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C60429368486D99B
-20120821050916 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293684A776A7
-20120821050942 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293684C4FF73
-20120821051003 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293684DB980F
-20120821051010 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293684DD4FBF
-20120821051158 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293685721537
-20120821051206 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293685768253
-20120821051231 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293685930F13
-20120821051240 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293685987B0B
-20120821051324 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293685D5E36B
-20120821051349 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293685F3AB7F
-20120821051424 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293686206187
-20120821051516 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C60429368668EB4B
-20120821051540 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C60429368686EB87
-20120821051622 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293686BCCF13
-20120821051703 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293686F13B9F
-20120821051715 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293686FB2D4F
-20120821051837 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C6042936876ED7DF
-20120821051843 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C6042936876F05DB
-20120821051930 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293687AEDE8F
-20120821052131 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293688637CFF
-20120821053137 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF942284EA9F
-20120821053209 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF94228B7F67
-20120821053317 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9422A2B3C7
-20120821053841 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF94232DEF87
-20120821054039 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF942359AB7B
-20120821054334 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9423A371A7
-20120821054455 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9423C1CEEF
-20120821054844 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9424273F1F
-20120821055307 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9424987667
-20120821055436 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9424B90BAB
-20120821055700 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9424F6C7CF
-20120821060224 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF94258ADCEF
-20120821060334 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9425A1FCEB
-20120821060420 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9425AEBF43
-20120821060927 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF942634C34F
-20120821061829 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF94272F0D4F
-20120821062020 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF94275B00B7
-20120821062241 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9427941F5F
-20120821063416 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9428D5E367
-20120821063648 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF942917E127
-20120821064052 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9429825A2B
-20120821064951 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF942A74C4EB
-20120821065736 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF942B4640D3
-20120821071146 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF942CCD6D1B
-20120821071337 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF942CF9321B
-20120821072545 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF942E48654F
-20120821075022 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9430F1B6A3
-20120821080229 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9432356F63
-20120821081230 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF94333D9363
-20120821081746 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9433C6A7A7
-20120821081811 2 6 100 3071 2 DFAA35D35531E0F524F0099877A482D2AC8D589F374394A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62DF5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15DC537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530FD3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B66757BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C764826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF9433C94C93
-20120821084945 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA45B27D047
-20120821091240 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA45C370A33
-20120821092428 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA45CBB9FBB
-20120821093047 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA45D001E73
-20120821095420 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA45E104D6F
-20120821095624 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA45E21E2BF
-20120821102749 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA45F9B1B7B
-20120821105854 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA4610E205F
-20120821110658 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA461631FBF
-20120821110744 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA461635E3B
-20120821115206 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA4636E0DF7
-20120821121256 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA4645F38B3
-20120821121421 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA46467609B
-20120821122649 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA464F87D6B
-20120821122854 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA46508F94B
-20120821125200 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA4661CBC5B
-20120821130613 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA466BC6B33
-20120821131115 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA466ED9CC7
-20120821132817 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA467B278B3
-20120821135349 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA468D8351B
-20120821141206 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA469A817A7
-20120821144909 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA46B488EF7
-20120821150021 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA46BC5D5E7
-20120821153843 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA46D774723
-20120821162006 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA46F5488DB
-20120821170404 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA47157A067
-20120821173305 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA472A1E94B
-20120821173936 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA472E0E57F
-20120821174533 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA4731F7433
-20120821180053 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA473C7CE3F
-20120821180952 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA4742A8237
-20120821181124 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA474343C5B
-20120821183540 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA4754D89DB
-20120821183852 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA47569B47F
-20120821184512 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA475AC57DB
-20120821184603 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA475AD78CB
-20120821184701 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA475B0038F
-20120821185939 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA4763BD72F
-20120821190630 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA476853BB7
-20120821190945 2 6 100 4095 2 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA476A47843
-20120821195501 2 6 100 4095 5 EF07B0F39662DC8600224E46AB8BE8CB72E552D52E88013D20EC039A0697ED9AAD018B16F0B910D4AD54437B8585AAA4EAE0CE216E31F50EDF0CD05DAF5E02A73D399C91B38220EC3B62C42D1CF6BF06378533A70C1F8F4F4416DD542213D3432412125FDBFF7B9473CE6F8812D860E66282C9F34C1774D1EA57D54DADDF7E37A12C4A6AD5B4A30128C29D27D03B6535C0F7A8AF857E18ECAB992984E6D546918AAACB971A2AC2C2E7AF79A9547979E6342DB7443985E5F7EDF6F9F22B600EEB42CB84A5F1ACD76E213C52E3052DAE1A9119801CFA28E6EFD4F6BC35FA06C8724D78A96AF054826C0BF865D0EC5F6F4D31C1D3F7CF2FE6F16AF267A7BA04753AEF420D4D8C36BCE8D9694814B9E9C3DF468064EB5636405C71CA9D8D50D36570B42639C9C2C02FB3A3D0C6B28DD200B0AF164C621D60B12E35E4D00129C8900F6EFDBB49FF34DD64CB13CD4087A7F84FEFD77D4E8099C2B804BA643EAFCA66D1F02BD09AE44AC83A5149F60711B7B108C01D53FF15FA59B36BE62A870F163F5063CEE103B377808343AFBD32271199E26D93734011BED2305EDE2E841EAD512E23B8C9B8CD4D398C7B4C8B76B355CC150B66B8EB7779E2CA519E10E45D0FB138676850C56F23DB135F546D364B92BC1C9423E089D30D4D57D27D7885EE14AE135A488C0542C3719FBEF46F4BB5FB53A28DA26DDF84C8BC55348A8AA478A96AEF
-20120705232031 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B241215BB
-20120705233800 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B246EC93B
-20120706002709 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B2582B477
-20120706013826 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B271419A3
-20120706014732 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B273FB1BB
-20120706021008 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B27B7E59F
-20120705225552 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B29C4E81B
-20120705233754 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B2AB07037
-20120705234834 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B2AE25CBB
-20120706024556 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B2EDFAA6F
-20120705233556 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B30EE83EB
-20120706002117 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B31E6F727
-20120705233808 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B37267537
-20120706001148 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B3DF98C1F
-20120706013155 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B3FBB98EB
-20120706025705 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B418898A7
-20120706022948 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B4707179B
-20120705233534 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B4F3D25C7
-20120706014542 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B520205CB
-20120706030026 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B539518DB
-20120706003519 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B566E0243
-20120706032218 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B59E508EF
-20120706033523 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B5A254F5F
-20120705235242 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B5B60C48F
-20120706022615 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B646A1B3B
-20120706032540 2 6 100 6143 5 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B6594B14F
-20120706001843 2 6 100 6143 2 EEBCAD36F686DDEB790C1EBDF6C6355A4EEB95435785FAC26C1DDBBD0D3C284AB5B4A1D5BA22131604AAE087D8B9431038CDA76DAA9E1C8D10793F53374FDF26489D38FF13188B6961B86E44A065D2FADEFC6C9496350AFA4129C9FD1B6B321E6053A6C645978C151D623C1106FE6669C220690B637F6259522F88250CC2B1B7F170706E9CE741F6E26BB4E86FB6822B13D8A7CE99FEF5CD66EF08310ECE5CC86648BD90E1DC59332505579116D3F3C8314065DC1319BEA133ED809903CA4949905C3D21619217816465E964768FFE76BC962AACBC8FF13477990A81C8759BBE95DFFA22E299F7C0F79A0EA7C44B28E8AB96149CC213E7C886E3D0A2230D7A4176749D6EDD6FCA2F5F3E2BD10392BC818CFB25C696C1EC14CE6F23CDB6C3DA2ED77E098A874799EB65F82A4EAF85CA0C9E68278381AF964AA5816B2CDA8E1ABB2954C02F641E1F374563B0F9DBF2F1B6D8168558BB971C8F48668A8034F82908D45D4D9A9072375D00AE0D5D442C6E6B6B2E7280C104C7675FDB0795DD0D3273E74BDC7B243B7604447502EB1572A273ABA0032CDB754345B1ACDF17B5AEDA45B661DBEFDA084B1427F94C8EA62BAB6A1E05DED8F2F706445879F15FB096996765238B6B546FDE5F219B5B85B31E804A989C4959600998A03572FB59DC150714BDB0C71A236497AE79871FBEFCAFFF34D2DF0142F2AF3C9C5D92F5FC7A61A27FF9AA1EADDF3552A2BED2CC4D19FB0F67DCC02744947A42FE10B338A3A8E634B413AE46C4E644DD5934D5820C9714656171A02BBCA25AED1CCD9EB9BEF9C63E7E966B0E2E47146191ECA452588FA2AFF50AF25FABAF83E143D47A651BD9B9C37CF5D6319FDCBC2F5D4B76D07B52D857FDE48FD983F06B531F7D316E2961E17D358FE6556C82C2E78C1D9CCF68760EFD8CC692E8912914781651D834C0C766B3D71C07C91AB93619E0C06385CFAC6FA18E1DEC7F3C5EE92C906CC49A4786D24CDB4F5656DE60F1F4412367B16BDA68DA368218C16E30C48366A8C0FDFA6E708E3353B8471402A42E594903774A65EA7AB5A83D08AD10D34DB38201B44B677C3593
-20120705054703 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234453518A0F7
-20120705060217 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445353B291F
-20120705100916 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE2344537DF8F1B
-20120705112627 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE2344538AF7C7B
-20120705121419 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445392BB61F
-20120705162623 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234453BD5FE03
-20120705171958 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234453C6257EF
-20120705222541 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234453FBF1073
-20120705120012 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE2344544BA2363
-20120705143238 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445464ED33B
-20120705175610 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445486B9E93
-20120705143839 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE2344551AEBB1B
-20120705164833 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE2344553053057
-20120705195911 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE2344560200E33
-20120705051445 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445620DCB9B
-20120705090103 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234456453E2C3
-20120705102457 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234456520F7B3
-20120705045958 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234456CC34FE7
-20120705064048 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234456DBB1643
-20120705100057 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234456FACFC3F
-20120705130216 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445716EEFD3
-20120705184211 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE2344574BD3B0F
-20120705075506 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234457918ED6F
-20120705111016 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445857E1707
-20120705051124 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234458C6078E3
-20120705054255 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234458CA4E313
-20120705155949 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234459281E7B3
-20120705065517 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE2344597A57CB3
-20120705082307 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445987253DB
-20120705182442 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234459E124B2F
-20120705184956 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE234459E442F5B
-20120705071209 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445A1E0FD83
-20120705155527 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445A6BDA473
-20120705103912 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445ADCE429F
-20120705115451 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445AE75FB83
-20120705133531 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445AF5813A3
-20120705144902 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445AFF92FDF
-20120705160631 2 6 100 8191 5 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445B0A9AF9F
-20120705194100 2 6 100 8191 2 DA2167F01CB32874E032B38C40FEC5F2557C9C4411B3A4B3D38C889A8BEED4EB7EF08A9A1E1EAAEEC22C2A46891D3CA84517FDFCDFA2BACBCDE2FC8EA87182542F5C8D3897B6C8A6DB951256F3DDBA7C5D6E7060925AD1F3046F49D00B433770B412DAA2A74E539EB81E3266DDDA82781BB21B19695FB925FA8BB6D249B5C33401C5D9E5C6B1719A36F1EB36E7CCD28AD98AA74DFD453D343BD189C968EB8F459809E87F77C6BA985B82B960A46660C7A277970E016EBD183CE7D6232F56EB06ECC0931024B9333879EF063F976C3603649AB9DCBE9714753E0A865020C3EF22BABF2F473F771CFC70A7C43FE320640D6E2816E88B6CA501A85A34F88EFF26AD8FFA0D11B0A21CB1A4FC7F90DB97B11BD5367302CBB45A390D2CB28CE83D50156A161D0080FD5F3961872ABC56FBCB973C517F6D7205E6CCF44E22E5DF8793D5037A9E779A52628D258CEA6B45CA4AC604CD69875D51145EE4C3D8856E24F9DBCA0134D54A734320A46A0AF52E20DD604AD465508172D4185C0D5C720B325ABC1760B1680B7BDFBAA1AE845A84AC3C7BBC53CD01C000B2186DC3915A1879224DD703E817C58F5FFCFBDF0189BB4B5033769F49852F3C48A88B88FB659B4AC96EE9DFC1D7E1760194EE4E1B6A8052BA17C827BE8A74C9F3FA7EA3236171F3DF9ACF19C40636825F1C49EFAAB12CEAD24F4585FE7C466FDE7ACF7E1FC91C8D473A8AB12C652AF568227E7CE3421256F83084D8E82DC977309E5B8C73EB8D92B71B9DAF6A53D13539D55C1A67BAC646358352529958AA3599DF0D882B8640ABFF17031C3F246A3E07F86AEB29CEACACF3B3EB931C40D292D09F4B99E08E4C68D811F9425DA30AC456107454AAC470DBD627C3EE2132E7C6FCEB61C2BA1CBE4FE6F07A2A4E398FDFBECC0283E9CF440F9F8F6893D019A98EFE992BA7433951DF341A3B3A8E879B090FB0E11907382853FBD6FA79B5B3FFF4EBE286F92A99D24C548949209867B1116BDBE1F104230EE26CCA0A12602A328B9B7A86D18415881AEFC9527AD4BB563CC330F29DF51199E1E9F0317EE6F3768C0849351FC1F95D47A1DE90484BE923ADC004D8287A90168C1D1491AD9A9B3266A826F966AA964E814F171FF9F3BA755DF83961182D95317844D6064D8BDED2DDB9AB4D74C325C1748036103690D88D85B532B692B74ED199253CB77E3BA57A2369BD9DD3B4FE68A66A1EFE507BA1F1A0164B6EDF397DF550EAC7FA155F7DED564A34DA73BC1F72E2D56CBABADAF3ED6B03C56FE00CA51548604403757ACAE67C71C564D4F688BA44465C7D3FFC84DB2BA142E06A967181CA0806E732134D795AD6E936BB25C00A14FE0DA5A83A7095D0271B380E802CD9E6E601C582EAC20CB6AC0C670108376302BA364FFD30E78D0CAB72BADB15F282CD256BC3B365896D80DC170BE23445B296E223
+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
diff --git a/moduli.0 b/moduli.0
deleted file mode 100644
index 1c580d46..00000000
--- a/moduli.0
+++ /dev/null
@@ -1,74 +0,0 @@
-MODULI(5) File Formats Manual MODULI(5)
-
-NAME
- moduli M-bM-^@M-^S Diffie-Hellman moduli
-
-DESCRIPTION
- The /etc/moduli file contains prime numbers and generators for use by
- sshd(8) in the Diffie-Hellman Group Exchange key exchange method.
-
- New moduli may be generated with ssh-keygen(1) using a two-step process.
- An initial candidate generation pass, using ssh-keygen -G, calculates
- numbers that are likely to be useful. A second primality testing pass,
- using ssh-keygen -T, provides a high degree of assurance that the numbers
- are prime and are safe for use in Diffie-Hellman operations by sshd(8).
- This moduli format is used as the output from each pass.
-
- The file consists of newline-separated records, one per modulus,
- containing seven space-separated fields. These fields are as follows:
-
- timestamp The time that the modulus was last processed as
- YYYYMMDDHHMMSS.
-
- type Decimal number specifying the internal structure of
- the prime modulus. Supported types are:
-
- 0 Unknown, not tested.
- 2 "Safe" prime; (p-1)/2 is also prime.
- 4 Sophie Germain; 2p+1 is also prime.
-
- Moduli candidates initially produced by ssh-keygen(1)
- are Sophie Germain primes (type 4). Further primality
- testing with ssh-keygen(1) produces safe prime moduli
- (type 2) that are ready for use in sshd(8). Other
- types are not used by OpenSSH.
-
- tests Decimal number indicating the type of primality tests
- that the number has been subjected to represented as a
- bitmask of the following values:
-
- 0x00 Not tested.
- 0x01 Composite number M-bM-^@M-^S not prime.
- 0x02 Sieve of Eratosthenes.
- 0x04 Probabilistic Miller-Rabin primality tests.
-
- The ssh-keygen(1) moduli candidate generation uses the
- Sieve of Eratosthenes (flag 0x02). Subsequent
- ssh-keygen(1) primality tests are Miller-Rabin tests
- (flag 0x04).
-
- trials Decimal number indicating the number of primality
- trials that have been performed on the modulus.
-
- size Decimal number indicating the size of the prime in
- bits.
-
- generator The recommended generator for use with this modulus
- (hexadecimal).
-
- modulus The modulus itself in hexadecimal.
-
- When performing Diffie-Hellman Group Exchange, sshd(8) first estimates
- the size of the modulus required to produce enough Diffie-Hellman output
- to sufficiently key the selected symmetric cipher. sshd(8) then randomly
- selects a modulus from /etc/moduli that best meets the size requirement.
-
-SEE ALSO
- ssh-keygen(1), sshd(8)
-
-STANDARDS
- M. Friedl, N. Provos, and W. Simpson, Diffie-Hellman Group Exchange for
- the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006,
- 2006.
-
-OpenBSD 5.7 September 26, 2012 OpenBSD 5.7
diff --git a/moduli.c b/moduli.c
index ed1bdc94..8dd36b1c 100644
--- a/moduli.c
+++ b/moduli.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: moduli.c,v 1.30 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: moduli.c,v 1.37 2019/11/15 06:00:20 djm Exp $ */
/*
* Copyright 1994 Phil Karn <karn@qualcomm.com>
* Copyright 1996-1998, 2003 William Allen Simpson <wsimpson@greendragon.com>
@@ -41,7 +41,6 @@
#ifdef WITH_OPENSSL
-#include <sys/param.h> /* MAX */
#include <sys/types.h>
#include <openssl/bn.h>
@@ -160,6 +159,8 @@ qfileout(FILE * ofile, u_int32_t otype, u_int32_t otests, u_int32_t otries,
time(&time_now);
gtm = gmtime(&time_now);
+ if (gtm == NULL)
+ return -1;
res = fprintf(ofile, "%04d%02d%02d%02d%02d%02d %u %u %u %u %x ",
gtm->tm_year + 1900, gtm->tm_mon + 1, gtm->tm_mday,
@@ -413,8 +414,8 @@ gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start)
time(&time_stop);
- logit("%.24s Sieved with %u small primes in %ld seconds",
- ctime(&time_stop), largetries, (long) (time_stop - time_start));
+ logit("%.24s Sieved with %u small primes in %lld seconds",
+ ctime(&time_stop), largetries, (long long)(time_stop - time_start));
for (j = r = 0; j < largebits; j++) {
if (BIT_TEST(LargeSieve, j))
@@ -454,7 +455,7 @@ write_checkpoint(char *cpfile, u_int32_t lineno)
int r;
r = snprintf(tmp, sizeof(tmp), "%s.XXXXXXXXXX", cpfile);
- if (r == -1 || r >= PATH_MAX) {
+ if (r < 0 || r >= PATH_MAX) {
logit("write_checkpoint: temp pathname too long");
return;
}
@@ -577,13 +578,12 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted,
char *checkpoint_file, unsigned long start_lineno, unsigned long num_lines)
{
BIGNUM *q, *p, *a;
- BN_CTX *ctx;
char *cp, *lp;
u_int32_t count_in = 0, count_out = 0, count_possible = 0;
u_int32_t generator_known, in_tests, in_tries, in_type, in_size;
unsigned long last_processed = 0, end_lineno;
time_t time_start, time_stop;
- int res;
+ int res, is_prime;
if (trials < TRIAL_MINIMUM) {
error("Minimum primality trials is %d", TRIAL_MINIMUM);
@@ -601,15 +601,13 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted,
fatal("BN_new failed");
if ((q = BN_new()) == NULL)
fatal("BN_new failed");
- if ((ctx = BN_CTX_new()) == NULL)
- fatal("BN_CTX_new failed");
debug2("%.24s Final %u Miller-Rabin trials (%x generator)",
ctime(&time_start), trials, generator_wanted);
if (checkpoint_file != NULL)
last_processed = read_checkpoint(checkpoint_file);
- last_processed = start_lineno = MAX(last_processed, start_lineno);
+ last_processed = start_lineno = MAXIMUM(last_processed, start_lineno);
if (end_lineno == ULONG_MAX)
debug("process from line %lu from pipe", last_processed);
else
@@ -717,8 +715,6 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted,
if (generator_known == 0) {
if (BN_mod_word(p, 24) == 11)
generator_known = 2;
- else if (BN_mod_word(p, 12) == 5)
- generator_known = 3;
else {
u_int32_t r = BN_mod_word(p, 10);
@@ -754,7 +750,10 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted,
* that p is also prime. A single pass will weed out the
* vast majority of composite q's.
*/
- if (BN_is_prime_ex(q, 1, ctx, NULL) <= 0) {
+ is_prime = BN_is_prime_ex(q, 1, NULL, NULL);
+ if (is_prime < 0)
+ fatal("BN_is_prime_ex failed");
+ if (is_prime == 0) {
debug("%10u: q failed first possible prime test",
count_in);
continue;
@@ -767,14 +766,20 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted,
* will show up on the first Rabin-Miller iteration so it
* doesn't hurt to specify a high iteration count.
*/
- if (!BN_is_prime_ex(p, trials, ctx, NULL)) {
+ is_prime = BN_is_prime_ex(p, trials, NULL, NULL);
+ if (is_prime < 0)
+ fatal("BN_is_prime_ex failed");
+ if (is_prime == 0) {
debug("%10u: p is not prime", count_in);
continue;
}
debug("%10u: p is almost certainly prime", count_in);
/* recheck q more rigorously */
- if (!BN_is_prime_ex(q, trials - 1, ctx, NULL)) {
+ is_prime = BN_is_prime_ex(q, trials - 1, NULL, NULL);
+ if (is_prime < 0)
+ fatal("BN_is_prime_ex failed");
+ if (is_prime == 0) {
debug("%10u: q is not prime", count_in);
continue;
}
@@ -794,7 +799,6 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted,
free(lp);
BN_free(p);
BN_free(q);
- BN_CTX_free(ctx);
if (checkpoint_file != NULL)
unlink(checkpoint_file);
diff --git a/monitor.c b/monitor.c
index 2947eb0c..b454cc16 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.145 2015/02/20 22:17:21 djm Exp $ */
+/* $OpenBSD: monitor.c,v 1.210 2020/03/13 03:17:07 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -29,18 +29,18 @@
#include <sys/types.h>
#include <sys/socket.h>
-#include "openbsd-compat/sys-tree.h"
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#include <pwd.h>
#include <signal.h>
#ifdef HAVE_STDINT_H
-#include <stdint.h>
+# include <stdint.h>
#endif
#include <stdlib.h>
#include <string.h>
@@ -55,32 +55,25 @@
# endif
#endif
-#ifdef SKEY
-#include <skey.h>
-#endif
-
#ifdef WITH_OPENSSL
#include <openssl/dh.h>
#endif
+#include "openbsd-compat/sys-tree.h"
#include "openbsd-compat/sys-queue.h"
+#include "openbsd-compat/openssl-compat.h"
+
#include "atomicio.h"
#include "xmalloc.h"
#include "ssh.h"
-#include "key.h"
-#include "buffer.h"
+#include "sshkey.h"
+#include "sshbuf.h"
#include "hostfile.h"
#include "auth.h"
#include "cipher.h"
#include "kex.h"
#include "dh.h"
-#ifdef TARGET_OS_MAC /* XXX Broken krb5 headers on Mac */
-#undef TARGET_OS_MAC
-#include "zlib.h"
-#define TARGET_OS_MAC 1
-#else
-#include "zlib.h"
-#endif
+#include "auth-pam.h"
#include "packet.h"
#include "auth-options.h"
#include "sshpty.h"
@@ -92,7 +85,6 @@
#include "misc.h"
#include "servconf.h"
#include "monitor.h"
-#include "monitor_mm.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
@@ -100,10 +92,10 @@
#include "monitor_fdpass.h"
#include "compat.h"
#include "ssh2.h"
-#include "roaming.h"
#include "authfd.h"
#include "match.h"
#include "ssherr.h"
+#include "sk-api.h"
#ifdef GSSAPI
static Gssctxt *gsscontext = NULL;
@@ -113,69 +105,63 @@ static Gssctxt *gsscontext = NULL;
extern ServerOptions options;
extern u_int utmp_len;
extern u_char session_id[];
-extern Buffer auth_debug;
-extern int auth_debug_init;
-extern Buffer loginmsg;
+extern struct sshbuf *loginmsg;
+extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */
/* State exported from the child */
static struct sshbuf *child_state;
/* Functions on the monitor that answer unprivileged requests */
-int mm_answer_moduli(int, Buffer *);
-int mm_answer_sign(int, Buffer *);
-int mm_answer_pwnamallow(int, Buffer *);
-int mm_answer_auth2_read_banner(int, Buffer *);
-int mm_answer_authserv(int, Buffer *);
-int mm_answer_authpassword(int, Buffer *);
-int mm_answer_bsdauthquery(int, Buffer *);
-int mm_answer_bsdauthrespond(int, Buffer *);
-int mm_answer_skeyquery(int, Buffer *);
-int mm_answer_skeyrespond(int, Buffer *);
-int mm_answer_keyallowed(int, Buffer *);
-int mm_answer_keyverify(int, Buffer *);
-int mm_answer_pty(int, Buffer *);
-int mm_answer_pty_cleanup(int, Buffer *);
-int mm_answer_term(int, Buffer *);
-int mm_answer_rsa_keyallowed(int, Buffer *);
-int mm_answer_rsa_challenge(int, Buffer *);
-int mm_answer_rsa_response(int, Buffer *);
-int mm_answer_sesskey(int, Buffer *);
-int mm_answer_sessid(int, Buffer *);
+int mm_answer_moduli(struct ssh *, int, struct sshbuf *);
+int mm_answer_sign(struct ssh *, int, struct sshbuf *);
+int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *);
+int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);
+int mm_answer_authserv(struct ssh *, int, struct sshbuf *);
+int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);
+int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);
+int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);
+int mm_answer_skeyquery(struct ssh *, int, struct sshbuf *);
+int mm_answer_skeyrespond(struct ssh *, int, struct sshbuf *);
+int mm_answer_keyallowed(struct ssh *, int, struct sshbuf *);
+int mm_answer_keyverify(struct ssh *, int, struct sshbuf *);
+int mm_answer_pty(struct ssh *, int, struct sshbuf *);
+int mm_answer_pty_cleanup(struct ssh *, int, struct sshbuf *);
+int mm_answer_term(struct ssh *, int, struct sshbuf *);
+int mm_answer_rsa_keyallowed(struct ssh *, int, struct sshbuf *);
+int mm_answer_rsa_challenge(struct ssh *, int, struct sshbuf *);
+int mm_answer_rsa_response(struct ssh *, int, struct sshbuf *);
+int mm_answer_sesskey(struct ssh *, int, struct sshbuf *);
+int mm_answer_sessid(struct ssh *, int, struct sshbuf *);
#ifdef USE_PAM
-int mm_answer_pam_start(int, Buffer *);
-int mm_answer_pam_account(int, Buffer *);
-int mm_answer_pam_init_ctx(int, Buffer *);
-int mm_answer_pam_query(int, Buffer *);
-int mm_answer_pam_respond(int, Buffer *);
-int mm_answer_pam_free_ctx(int, Buffer *);
+int mm_answer_pam_start(struct ssh *, int, struct sshbuf *);
+int mm_answer_pam_account(struct ssh *, int, struct sshbuf *);
+int mm_answer_pam_init_ctx(struct ssh *, int, struct sshbuf *);
+int mm_answer_pam_query(struct ssh *, int, struct sshbuf *);
+int mm_answer_pam_respond(struct ssh *, int, struct sshbuf *);
+int mm_answer_pam_free_ctx(struct ssh *, int, struct sshbuf *);
#endif
#ifdef GSSAPI
-int mm_answer_gss_setup_ctx(int, Buffer *);
-int mm_answer_gss_accept_ctx(int, Buffer *);
-int mm_answer_gss_userok(int, Buffer *);
-int mm_answer_gss_checkmic(int, Buffer *);
+int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *);
+int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *);
+int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *);
+int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *);
#endif
#ifdef SSH_AUDIT_EVENTS
-int mm_answer_audit_event(int, Buffer *);
-int mm_answer_audit_command(int, Buffer *);
+int mm_answer_audit_event(struct ssh *, int, struct sshbuf *);
+int mm_answer_audit_command(struct ssh *, int, struct sshbuf *);
#endif
-static int monitor_read_log(struct monitor *);
-
static Authctxt *authctxt;
-#ifdef WITH_SSH1
-static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */
-#endif
-
/* local state for key verify */
static u_char *key_blob = NULL;
-static u_int key_bloblen = 0;
+static size_t key_bloblen = 0;
static int key_blobtype = MM_NOKEY;
+static struct sshauthopt *key_opts = NULL;
static char *hostbased_cuser = NULL;
static char *hostbased_chost = NULL;
static char *auth_method = "unknown";
@@ -187,7 +173,7 @@ static pid_t monitor_child_pid;
struct mon_table {
enum monitor_reqtype type;
int flags;
- int (*f)(int, Buffer *);
+ int (*f)(struct ssh *, int, struct sshbuf *);
};
#define MON_ISAUTH 0x0004 /* Required for Authentication */
@@ -199,6 +185,10 @@ struct mon_table {
#define MON_PERMIT 0x1000 /* Request is permitted */
+static int monitor_read(struct ssh *, struct monitor *, struct mon_table *,
+ struct mon_table **);
+static int monitor_read_log(struct monitor *);
+
struct mon_table mon_dispatch_proto20[] = {
#ifdef WITH_OPENSSL
{MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
@@ -211,9 +201,9 @@ struct mon_table mon_dispatch_proto20[] = {
#ifdef USE_PAM
{MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
{MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
- {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
- {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
- {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
+ {MONITOR_REQ_PAM_INIT_CTX, MON_ONCE, mm_answer_pam_init_ctx},
+ {MONITOR_REQ_PAM_QUERY, 0, mm_answer_pam_query},
+ {MONITOR_REQ_PAM_RESPOND, MON_ONCE, mm_answer_pam_respond},
{MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
#endif
#ifdef SSH_AUDIT_EVENTS
@@ -223,17 +213,13 @@ struct mon_table mon_dispatch_proto20[] = {
{MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
{MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
#endif
-#ifdef SKEY
- {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
- {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
-#endif
{MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
{MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
#ifdef GSSAPI
{MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
- {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
- {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
- {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
+ {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
+ {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok},
+ {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic},
#endif
{0, 0, NULL}
};
@@ -253,56 +239,9 @@ struct mon_table mon_dispatch_postauth20[] = {
{0, 0, NULL}
};
-struct mon_table mon_dispatch_proto15[] = {
-#ifdef WITH_SSH1
- {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
- {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
- {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
- {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
- {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_rsa_keyallowed},
- {MONITOR_REQ_KEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_keyallowed},
- {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge},
- {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response},
-#ifdef BSD_AUTH
- {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
- {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
-#endif
-#ifdef SKEY
- {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
- {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
-#endif
-#ifdef USE_PAM
- {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
- {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
- {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
- {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
- {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
- {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
-#endif
-#ifdef SSH_AUDIT_EVENTS
- {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
-#endif
-#endif /* WITH_SSH1 */
- {0, 0, NULL}
-};
-
-struct mon_table mon_dispatch_postauth15[] = {
-#ifdef WITH_SSH1
- {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
- {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
- {MONITOR_REQ_TERM, 0, mm_answer_term},
-#ifdef SSH_AUDIT_EVENTS
- {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
- {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command},
-#endif
-#endif /* WITH_SSH1 */
- {0, 0, NULL}
-};
-
struct mon_table *mon_dispatch;
/* Specifies if a certain message is allowed at the moment */
-
static void
monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit)
{
@@ -331,46 +270,42 @@ monitor_permit_authentications(int permit)
}
void
-monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
+monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor)
{
struct mon_table *ent;
int authenticated = 0, partial = 0;
debug3("preauth child monitor started");
- close(pmonitor->m_recvfd);
- close(pmonitor->m_log_sendfd);
+ if (pmonitor->m_recvfd >= 0)
+ close(pmonitor->m_recvfd);
+ if (pmonitor->m_log_sendfd >= 0)
+ close(pmonitor->m_log_sendfd);
pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;
- authctxt = _authctxt;
+ authctxt = (Authctxt *)ssh->authctxt;
memset(authctxt, 0, sizeof(*authctxt));
+ ssh->authctxt = authctxt;
- authctxt->loginmsg = &loginmsg;
+ authctxt->loginmsg = loginmsg;
- if (compat20) {
- mon_dispatch = mon_dispatch_proto20;
-
- /* Permit requests for moduli and signatures */
- monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
- monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
- } else {
- mon_dispatch = mon_dispatch_proto15;
-
- monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
- }
+ mon_dispatch = mon_dispatch_proto20;
+ /* Permit requests for moduli and signatures */
+ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
/* The first few requests do not require asynchronous access */
while (!authenticated) {
partial = 0;
auth_method = "unknown";
auth_submethod = NULL;
- authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
+ auth2_authctxt_reset_info(authctxt);
+
+ authenticated = (monitor_read(ssh, pmonitor,
+ mon_dispatch, &ent) == 1);
/* Special handling for multiple required authentications */
if (options.num_auth_methods != 0) {
- if (!compat20)
- fatal("AuthenticationMethods is not supported"
- "with SSH protocol 1");
if (authenticated &&
!auth2_update_methods_lists(authctxt,
auth_method, auth_submethod)) {
@@ -386,26 +321,33 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
fatal("%s: unexpected authentication from %d",
__func__, ent->type);
if (authctxt->pw->pw_uid == 0 &&
- !auth_root_allowed(auth_method))
+ !auth_root_allowed(ssh, auth_method))
authenticated = 0;
#ifdef USE_PAM
/* PAM needs to perform account checks after auth */
if (options.use_pam && authenticated) {
- Buffer m;
+ struct sshbuf *m;
- buffer_init(&m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed",
+ __func__);
mm_request_receive_expect(pmonitor->m_sendfd,
- MONITOR_REQ_PAM_ACCOUNT, &m);
- authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m);
- buffer_free(&m);
+ MONITOR_REQ_PAM_ACCOUNT, m);
+ authenticated = mm_answer_pam_account(
+ ssh, pmonitor->m_sendfd, m);
+ sshbuf_free(m);
}
#endif
}
if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
- auth_log(authctxt, authenticated, partial,
+ auth_log(ssh, authenticated, partial,
auth_method, auth_submethod);
- if (!authenticated)
+ if (!partial && !authenticated)
authctxt->failures++;
+ if (authenticated || partial) {
+ auth2_update_session_info(authctxt,
+ auth_method, auth_submethod);
+ }
}
}
@@ -416,15 +358,19 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
debug("%s: %s has been authenticated by privileged process",
__func__, authctxt->user);
+ ssh->authctxt = NULL;
+ ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
- mm_get_keystate(pmonitor);
+ mm_get_keystate(ssh, pmonitor);
/* Drain any buffered messages from the child */
while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
;
- close(pmonitor->m_sendfd);
- close(pmonitor->m_log_recvfd);
+ if (pmonitor->m_recvfd >= 0)
+ close(pmonitor->m_recvfd);
+ if (pmonitor->m_log_sendfd >= 0)
+ close(pmonitor->m_log_sendfd);
pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
}
@@ -441,84 +387,53 @@ monitor_child_handler(int sig)
}
void
-monitor_child_postauth(struct monitor *pmonitor)
+monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor)
{
close(pmonitor->m_recvfd);
pmonitor->m_recvfd = -1;
monitor_set_child_handler(pmonitor->m_pid);
- signal(SIGHUP, &monitor_child_handler);
- signal(SIGTERM, &monitor_child_handler);
- signal(SIGINT, &monitor_child_handler);
+ ssh_signal(SIGHUP, &monitor_child_handler);
+ ssh_signal(SIGTERM, &monitor_child_handler);
+ ssh_signal(SIGINT, &monitor_child_handler);
#ifdef SIGXFSZ
- signal(SIGXFSZ, SIG_IGN);
+ ssh_signal(SIGXFSZ, SIG_IGN);
#endif
- if (compat20) {
- mon_dispatch = mon_dispatch_postauth20;
+ mon_dispatch = mon_dispatch_postauth20;
- /* Permit requests for moduli and signatures */
- monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
- monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
- monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
- } else {
- mon_dispatch = mon_dispatch_postauth15;
- monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
- }
- if (!no_pty_flag) {
+ /* Permit requests for moduli and signatures */
+ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+
+ if (auth_opts->permit_pty_flag) {
monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
}
for (;;)
- monitor_read(pmonitor, mon_dispatch, NULL);
-}
-
-void
-monitor_sync(struct monitor *pmonitor)
-{
- if (options.compression) {
- /* The member allocation is not visible, so sync it */
- mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback);
- }
-}
-
-/* Allocation functions for zlib */
-static void *
-mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
-{
- size_t len = (size_t) size * ncount;
- void *address;
-
- if (len == 0 || ncount > SIZE_MAX / size)
- fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size);
-
- address = mm_malloc(mm, len);
-
- return (address);
-}
-
-static void
-mm_zfree(struct mm_master *mm, void *address)
-{
- mm_free(mm, address);
+ monitor_read(ssh, pmonitor, mon_dispatch, NULL);
}
static int
monitor_read_log(struct monitor *pmonitor)
{
- Buffer logmsg;
+ struct sshbuf *logmsg;
u_int len, level;
char *msg;
+ u_char *p;
+ int r;
- buffer_init(&logmsg);
+ if ((logmsg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
/* Read length */
- buffer_append_space(&logmsg, 4);
- if (atomicio(read, pmonitor->m_log_recvfd,
- buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) {
+ if ((r = sshbuf_reserve(logmsg, 4, &p)) != 0)
+ fatal("%s: reserve: %s", __func__, ssh_err(r));
+ if (atomicio(read, pmonitor->m_log_recvfd, p, 4) != 4) {
if (errno == EPIPE) {
- buffer_free(&logmsg);
+ sshbuf_free(logmsg);
debug("%s: child log fd closed", __func__);
close(pmonitor->m_log_recvfd);
pmonitor->m_log_recvfd = -1;
@@ -526,37 +441,39 @@ monitor_read_log(struct monitor *pmonitor)
}
fatal("%s: log fd read: %s", __func__, strerror(errno));
}
- len = buffer_get_int(&logmsg);
+ if ((r = sshbuf_get_u32(logmsg, &len)) != 0)
+ fatal("%s: get len: %s", __func__, ssh_err(r));
if (len <= 4 || len > 8192)
fatal("%s: invalid log message length %u", __func__, len);
/* Read severity, message */
- buffer_clear(&logmsg);
- buffer_append_space(&logmsg, len);
- if (atomicio(read, pmonitor->m_log_recvfd,
- buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg))
+ sshbuf_reset(logmsg);
+ if ((r = sshbuf_reserve(logmsg, len, &p)) != 0)
+ fatal("%s: reserve: %s", __func__, ssh_err(r));
+ if (atomicio(read, pmonitor->m_log_recvfd, p, len) != len)
fatal("%s: log fd read: %s", __func__, strerror(errno));
+ if ((r = sshbuf_get_u32(logmsg, &level)) != 0 ||
+ (r = sshbuf_get_cstring(logmsg, &msg, NULL)) != 0)
+ fatal("%s: decode: %s", __func__, ssh_err(r));
/* Log it */
- level = buffer_get_int(&logmsg);
- msg = buffer_get_string(&logmsg, NULL);
if (log_level_name(level) == NULL)
fatal("%s: invalid log level %u (corrupted message?)",
__func__, level);
do_log2(level, "%s [preauth]", msg);
- buffer_free(&logmsg);
+ sshbuf_free(logmsg);
free(msg);
return 0;
}
-int
-monitor_read(struct monitor *pmonitor, struct mon_table *ent,
+static int
+monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent,
struct mon_table **pent)
{
- Buffer m;
- int ret;
+ struct sshbuf *m;
+ int r, ret;
u_char type;
struct pollfd pfd[2];
@@ -583,10 +500,12 @@ monitor_read(struct monitor *pmonitor, struct mon_table *ent,
break; /* Continues below */
}
- buffer_init(&m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
- mm_request_receive(pmonitor->m_sendfd, &m);
- type = buffer_get_char(&m);
+ mm_request_receive(pmonitor->m_sendfd, m);
+ if ((r = sshbuf_get_u8(m, &type)) != 0)
+ fatal("%s: decode: %s", __func__, ssh_err(r));
debug3("%s: checking request %d", __func__, type);
@@ -600,8 +519,8 @@ monitor_read(struct monitor *pmonitor, struct mon_table *ent,
if (!(ent->flags & MON_PERMIT))
fatal("%s: unpermitted request %d", __func__,
type);
- ret = (*ent->f)(pmonitor->m_sendfd, &m);
- buffer_free(&m);
+ ret = (*ent->f)(ssh, pmonitor->m_sendfd, m);
+ sshbuf_free(m);
/* The child may use this request only once, disable it */
if (ent->flags & MON_ONCE) {
@@ -624,7 +543,7 @@ monitor_read(struct monitor *pmonitor, struct mon_table *ent,
/* allowed key state */
static int
-monitor_allowed_key(u_char *blob, u_int bloblen)
+monitor_allowed_key(const u_char *blob, u_int bloblen)
{
/* make sure key is allowed */
if (key_blob == NULL || key_bloblen != bloblen ||
@@ -640,23 +559,28 @@ monitor_reset_key_state(void)
free(key_blob);
free(hostbased_cuser);
free(hostbased_chost);
+ sshauthopt_free(key_opts);
key_blob = NULL;
key_bloblen = 0;
key_blobtype = MM_NOKEY;
+ key_opts = NULL;
hostbased_cuser = NULL;
hostbased_chost = NULL;
}
#ifdef WITH_OPENSSL
int
-mm_answer_moduli(int sock, Buffer *m)
+mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m)
{
DH *dh;
- int min, want, max;
+ const BIGNUM *dh_p, *dh_g;
+ int r;
+ u_int min, want, max;
- min = buffer_get_int(m);
- want = buffer_get_int(m);
- max = buffer_get_int(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));
debug3("%s: got parameters: %d %d %d",
__func__, min, want, max);
@@ -665,17 +589,20 @@ mm_answer_moduli(int sock, Buffer *m)
fatal("%s: bad parameters: %d %d %d",
__func__, min, want, max);
- buffer_clear(m);
+ sshbuf_reset(m);
dh = choose_dh(min, want, max);
if (dh == NULL) {
- buffer_put_char(m, 0);
+ if ((r = sshbuf_put_u8(m, 0)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
return (0);
} else {
/* Send first bignum */
- buffer_put_char(m, 1);
- buffer_put_bignum2(m, dh->p);
- buffer_put_bignum2(m, dh->g);
+ DH_get0_pqg(dh, &dh_p, NULL, &dh_g);
+ if ((r = sshbuf_put_u8(m, 1)) != 0 ||
+ (r = sshbuf_put_bignum2(m, dh_p)) != 0 ||
+ (r = sshbuf_put_bignum2(m, dh_g)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
DH_free(dh);
}
@@ -685,23 +612,27 @@ mm_answer_moduli(int sock, Buffer *m)
#endif
int
-mm_answer_sign(int sock, Buffer *m)
+mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
{
- struct ssh *ssh = active_state; /* XXX */
extern int auth_sock; /* XXX move to state struct? */
struct sshkey *key;
- struct sshbuf *sigbuf;
- u_char *p;
- u_char *signature;
- size_t datlen, siglen;
- int r, keyid, is_proof = 0;
+ struct sshbuf *sigbuf = NULL;
+ u_char *p = NULL, *signature = NULL;
+ char *alg = NULL;
+ size_t datlen, siglen, alglen;
+ int r, is_proof = 0;
+ u_int keyid, compat;
const char proof_req[] = "hostkeys-prove-00@openssh.com";
debug3("%s", __func__);
if ((r = sshbuf_get_u32(m, &keyid)) != 0 ||
- (r = sshbuf_get_string(m, &p, &datlen)) != 0)
+ (r = sshbuf_get_string(m, &p, &datlen)) != 0 ||
+ (r = sshbuf_get_cstring(m, &alg, &alglen)) != 0 ||
+ (r = sshbuf_get_u32(m, &compat)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (keyid > INT_MAX)
+ fatal("%s: invalid key ID", __func__);
/*
* Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes),
@@ -727,7 +658,7 @@ mm_answer_sign(int sock, Buffer *m)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 ||
(r = sshbuf_put_string(sigbuf, session_id2,
- session_id2_len) != 0) ||
+ session_id2_len)) != 0 ||
(r = sshkey_puts(key, sigbuf)) != 0)
fatal("%s: couldn't prepare private key "
"proof buffer: %s", __func__, ssh_err(r));
@@ -747,14 +678,14 @@ mm_answer_sign(int sock, Buffer *m)
}
if ((key = get_hostkey_by_index(keyid)) != NULL) {
- if ((r = sshkey_sign(key, &signature, &siglen, p, datlen,
- datafellows)) != 0)
+ 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));
} 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, datafellows)) != 0) {
+ p, datlen, alg, compat)) != 0) {
fatal("%s: ssh_agent_sign failed: %s",
__func__, ssh_err(r));
}
@@ -762,12 +693,13 @@ mm_answer_sign(int sock, Buffer *m)
fatal("%s: no hostkey from index %d", __func__, keyid);
debug3("%s: %s signature %p(%zu)", __func__,
- is_proof ? "KEX" : "hostkey proof", signature, siglen);
+ is_proof ? "hostkey proof" : "KEX", signature, siglen);
sshbuf_reset(m);
if ((r = sshbuf_put_string(m, signature, siglen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ free(alg);
free(p);
free(signature);
@@ -782,11 +714,11 @@ mm_answer_sign(int sock, Buffer *m)
/* Retrieves the password entry and also checks if the user is permitted */
int
-mm_answer_pwnamallow(int sock, Buffer *m)
+mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
{
char *username;
struct passwd *pwent;
- int allowed = 0;
+ int r, allowed = 0;
u_int i;
debug3("%s", __func__);
@@ -794,18 +726,20 @@ mm_answer_pwnamallow(int sock, Buffer *m)
if (authctxt->attempt++ != 0)
fatal("%s: multiple attempts for getpwnam", __func__);
- username = buffer_get_string(m, NULL);
+ if ((r = sshbuf_get_cstring(m, &username, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- pwent = getpwnamallow(username);
+ pwent = getpwnamallow(ssh, username);
authctxt->user = xstrdup(username);
setproctitle("%s [priv]", pwent ? username : "unknown");
free(username);
- buffer_clear(m);
+ sshbuf_reset(m);
if (pwent == NULL) {
- buffer_put_char(m, 0);
+ if ((r = sshbuf_put_u8(m, 0)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
authctxt->pw = fakepw();
goto out;
}
@@ -814,29 +748,40 @@ mm_answer_pwnamallow(int sock, Buffer *m)
authctxt->pw = pwent;
authctxt->valid = 1;
- buffer_put_char(m, 1);
- buffer_put_string(m, pwent, sizeof(struct passwd));
- buffer_put_cstring(m, pwent->pw_name);
- buffer_put_cstring(m, "*");
+ /* XXX don't sent pwent to unpriv; send fake class/dir/shell too */
+ if ((r = sshbuf_put_u8(m, 1)) != 0 ||
+ (r = sshbuf_put_string(m, pwent, sizeof(*pwent))) != 0 ||
+ (r = sshbuf_put_cstring(m, pwent->pw_name)) != 0 ||
+ (r = sshbuf_put_cstring(m, "*")) != 0 ||
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
- buffer_put_cstring(m, pwent->pw_gecos);
+ (r = sshbuf_put_cstring(m, pwent->pw_gecos)) != 0 ||
#endif
#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
- buffer_put_cstring(m, pwent->pw_class);
+ (r = sshbuf_put_cstring(m, pwent->pw_class)) != 0 ||
#endif
- buffer_put_cstring(m, pwent->pw_dir);
- buffer_put_cstring(m, pwent->pw_shell);
+ (r = sshbuf_put_cstring(m, pwent->pw_dir)) != 0 ||
+ (r = sshbuf_put_cstring(m, pwent->pw_shell)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
out:
- buffer_put_string(m, &options, sizeof(options));
+ ssh_packet_set_log_preamble(ssh, "%suser %s",
+ authctxt->valid ? "authenticating" : "invalid ", authctxt->user);
+ if ((r = sshbuf_put_string(m, &options, sizeof(options))) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
#define M_CP_STROPT(x) do { \
- if (options.x != NULL) \
- buffer_put_cstring(m, options.x); \
+ if (options.x != NULL) { \
+ if ((r = sshbuf_put_cstring(m, options.x)) != 0) \
+ fatal("%s: buffer error: %s", \
+ __func__, ssh_err(r)); \
+ } \
} while (0)
#define M_CP_STRARRAYOPT(x, nx) do { \
- for (i = 0; i < options.nx; i++) \
- buffer_put_cstring(m, options.x[i]); \
+ for (i = 0; i < options.nx; i++) { \
+ if ((r = sshbuf_put_cstring(m, options.x[i])) != 0) \
+ fatal("%s: buffer error: %s", \
+ __func__, ssh_err(r)); \
+ } \
} while (0)
/* See comment in servconf.h */
COPY_MATCH_STRING_OPTS();
@@ -844,7 +789,7 @@ mm_answer_pwnamallow(int sock, Buffer *m)
#undef M_CP_STRARRAYOPT
/* Create valid auth method lists */
- if (compat20 && auth2_setup_methods_lists(authctxt) != 0) {
+ if (auth2_setup_methods_lists(authctxt) != 0) {
/*
* The monitor will continue long enough to let the child
* run to it's packet_disconnect(), but it must not allow any
@@ -856,14 +801,10 @@ mm_answer_pwnamallow(int sock, Buffer *m)
debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
mm_request_send(sock, MONITOR_ANS_PWNAM, m);
- /* For SSHv1 allow authentication now */
- if (!compat20)
- monitor_permit_authentications(1);
- else {
- /* Allow service/style information on the auth context */
- monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
- monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
- }
+ /* Allow service/style information on the auth context */
+ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
+
#ifdef USE_PAM
if (options.use_pam)
monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
@@ -872,13 +813,15 @@ mm_answer_pwnamallow(int sock, Buffer *m)
return (0);
}
-int mm_answer_auth2_read_banner(int sock, Buffer *m)
+int mm_answer_auth2_read_banner(struct ssh *ssh, int sock, struct sshbuf *m)
{
char *banner;
+ int r;
- buffer_clear(m);
+ sshbuf_reset(m);
banner = auth2_read_banner();
- buffer_put_cstring(m, banner != NULL ? banner : "");
+ if ((r = sshbuf_put_cstring(m, banner != NULL ? banner : "")) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m);
free(banner);
@@ -886,12 +829,15 @@ int mm_answer_auth2_read_banner(int sock, Buffer *m)
}
int
-mm_answer_authserv(int sock, Buffer *m)
+mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m)
{
+ int r;
+
monitor_permit_authentications(1);
- authctxt->service = buffer_get_string(m, NULL);
- authctxt->style = buffer_get_string(m, NULL);
+ 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);
@@ -903,28 +849,66 @@ mm_answer_authserv(int sock, Buffer *m)
return (0);
}
+/*
+ * Check that the key type appears in the supplied pattern list, ignoring
+ * mismatches in the signature algorithm. (Signature algorithm checks are
+ * performed in the unprivileged authentication code).
+ * Returns 1 on success, 0 otherwise.
+ */
+static int
+key_base_type_match(const char *method, const struct sshkey *key,
+ const char *list)
+{
+ char *s, *l, *ol = xstrdup(list);
+ int found = 0;
+
+ l = ol;
+ for ((s = strsep(&l, ",")); s && *s != '\0'; (s = strsep(&l, ","))) {
+ if (sshkey_type_from_name(s) == key->type) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ error("%s key type %s is not in permitted list %s", method,
+ sshkey_ssh_name(key), list);
+ }
+
+ free(ol);
+ return found;
+}
+
int
-mm_answer_authpassword(int sock, Buffer *m)
+mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m)
{
static int call_count;
+#if !defined(ANDROID)
char *passwd;
- int authenticated;
- u_int plen;
+#endif
+ int r, authenticated;
+ size_t plen = 0;
- passwd = buffer_get_string(m, &plen);
+ if (!options.password_authentication)
+ fatal("%s: password authentication not enabled", __func__);
#if !defined(ANDROID)
+ if ((r = sshbuf_get_cstring(m, &passwd, &plen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* Only authenticate if the context is valid */
authenticated = options.password_authentication &&
- auth_password(authctxt, passwd);
+ auth_password(ssh, passwd);
+ freezero(passwd, plen);
#else
/* no password authentication in Android. */
authenticated = 0;
#endif
- explicit_bzero(passwd, strlen(passwd));
- free(passwd);
- buffer_clear(m);
- buffer_put_int(m, authenticated);
+ sshbuf_reset(m);
+ if ((r = sshbuf_put_u32(m, authenticated)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+#ifdef USE_PAM
+ if ((r = sshbuf_put_u32(m, sshpam_get_maxtries_reached())) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+#endif
debug3("%s: sending result %d", __func__, authenticated);
mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m);
@@ -941,21 +925,25 @@ mm_answer_authpassword(int sock, Buffer *m)
#ifdef BSD_AUTH
int
-mm_answer_bsdauthquery(int sock, Buffer *m)
+mm_answer_bsdauthquery(struct ssh *ssh, int sock, struct sshbuf *m)
{
char *name, *infotxt;
- u_int numprompts;
- u_int *echo_on;
+ u_int numprompts, *echo_on, success;
char **prompts;
- u_int success;
+ int r;
+ if (!options.kbd_interactive_authentication)
+ fatal("%s: kbd-int authentication not enabled", __func__);
success = bsdauth_query(authctxt, &name, &infotxt, &numprompts,
&prompts, &echo_on) < 0 ? 0 : 1;
- buffer_clear(m);
- buffer_put_int(m, success);
- if (success)
- buffer_put_cstring(m, prompts[0]);
+ sshbuf_reset(m);
+ if ((r = sshbuf_put_u32(m, success)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (success) {
+ if ((r = sshbuf_put_cstring(m, prompts[0])) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ }
debug3("%s: sending challenge success: %u", __func__, success);
mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m);
@@ -971,81 +959,33 @@ mm_answer_bsdauthquery(int sock, Buffer *m)
}
int
-mm_answer_bsdauthrespond(int sock, Buffer *m)
+mm_answer_bsdauthrespond(struct ssh *ssh, int sock, struct sshbuf *m)
{
char *response;
- int authok;
+ int r, authok;
- if (authctxt->as == 0)
+ if (!options.kbd_interactive_authentication)
+ fatal("%s: kbd-int authentication not enabled", __func__);
+ if (authctxt->as == NULL)
fatal("%s: no bsd auth session", __func__);
- response = buffer_get_string(m, NULL);
+ if ((r = sshbuf_get_cstring(m, &response, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
authok = options.challenge_response_authentication &&
auth_userresponse(authctxt->as, response, 0);
authctxt->as = NULL;
debug3("%s: <%s> = <%d>", __func__, response, authok);
free(response);
- buffer_clear(m);
- buffer_put_int(m, authok);
+ sshbuf_reset(m);
+ if ((r = sshbuf_put_u32(m, authok)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("%s: sending authenticated: %d", __func__, authok);
mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m);
- if (compat20) {
- auth_method = "keyboard-interactive";
- auth_submethod = "bsdauth";
- } else
- auth_method = "bsdauth";
-
- return (authok != 0);
-}
-#endif
-
-#ifdef SKEY
-int
-mm_answer_skeyquery(int sock, Buffer *m)
-{
- struct skey skey;
- char challenge[1024];
- u_int success;
-
- success = _compat_skeychallenge(&skey, authctxt->user, challenge,
- sizeof(challenge)) < 0 ? 0 : 1;
-
- buffer_clear(m);
- buffer_put_int(m, success);
- if (success)
- buffer_put_cstring(m, challenge);
-
- debug3("%s: sending challenge success: %u", __func__, success);
- mm_request_send(sock, MONITOR_ANS_SKEYQUERY, m);
-
- return (0);
-}
-
-int
-mm_answer_skeyrespond(int sock, Buffer *m)
-{
- char *response;
- int authok;
-
- response = buffer_get_string(m, NULL);
-
- authok = (options.challenge_response_authentication &&
- authctxt->valid &&
- skey_haskey(authctxt->pw->pw_name) == 0 &&
- skey_passcheck(authctxt->pw->pw_name, response) != -1);
-
- free(response);
-
- buffer_clear(m);
- buffer_put_int(m, authok);
-
- debug3("%s: sending authenticated: %d", __func__, authok);
- mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m);
-
- auth_method = "skey";
+ auth_method = "keyboard-interactive";
+ auth_submethod = "bsdauth";
return (authok != 0);
}
@@ -1053,30 +993,34 @@ mm_answer_skeyrespond(int sock, Buffer *m)
#ifdef USE_PAM
int
-mm_answer_pam_start(int sock, Buffer *m)
+mm_answer_pam_start(struct ssh *ssh, int sock, struct sshbuf *m)
{
if (!options.use_pam)
fatal("UsePAM not set, but ended up in %s anyway", __func__);
- start_pam(authctxt);
+ start_pam(ssh);
monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1);
+ if (options.kbd_interactive_authentication)
+ monitor_permit(mon_dispatch, MONITOR_REQ_PAM_INIT_CTX, 1);
return (0);
}
int
-mm_answer_pam_account(int sock, Buffer *m)
+mm_answer_pam_account(struct ssh *ssh, int sock, struct sshbuf *m)
{
u_int ret;
+ int r;
if (!options.use_pam)
- fatal("UsePAM not set, but ended up in %s anyway", __func__);
+ fatal("%s: PAM not enabled", __func__);
ret = do_pam_account();
- buffer_put_int(m, ret);
- buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg));
+ if ((r = sshbuf_put_u32(m, ret)) != 0 ||
+ (r = sshbuf_put_stringb(m, loginmsg)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m);
@@ -1087,49 +1031,62 @@ static void *sshpam_ctxt, *sshpam_authok;
extern KbdintDevice sshpam_device;
int
-mm_answer_pam_init_ctx(int sock, Buffer *m)
+mm_answer_pam_init_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
{
+ u_int ok = 0;
+ int r;
debug3("%s", __func__);
- authctxt->user = buffer_get_string(m, NULL);
+ if (!options.kbd_interactive_authentication)
+ fatal("%s: kbd-int authentication not enabled", __func__);
+ if (sshpam_ctxt != NULL)
+ fatal("%s: already called", __func__);
sshpam_ctxt = (sshpam_device.init_ctx)(authctxt);
sshpam_authok = NULL;
- buffer_clear(m);
+ sshbuf_reset(m);
if (sshpam_ctxt != NULL) {
monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1);
- buffer_put_int(m, 1);
- } else {
- buffer_put_int(m, 0);
+ monitor_permit(mon_dispatch, MONITOR_REQ_PAM_QUERY, 1);
+ ok = 1;
}
+ if ((r = sshbuf_put_u32(m, ok)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m);
return (0);
}
int
-mm_answer_pam_query(int sock, Buffer *m)
+mm_answer_pam_query(struct ssh *ssh, int sock, struct sshbuf *m)
{
char *name = NULL, *info = NULL, **prompts = NULL;
u_int i, num = 0, *echo_on = 0;
- int ret;
+ int r, ret;
debug3("%s", __func__);
sshpam_authok = NULL;
- ret = (sshpam_device.query)(sshpam_ctxt, &name, &info, &num, &prompts, &echo_on);
+ if (sshpam_ctxt == NULL)
+ fatal("%s: no context", __func__);
+ ret = (sshpam_device.query)(sshpam_ctxt, &name, &info,
+ &num, &prompts, &echo_on);
if (ret == 0 && num == 0)
sshpam_authok = sshpam_ctxt;
if (num > 1 || name == NULL || info == NULL)
- ret = -1;
- buffer_clear(m);
- buffer_put_int(m, ret);
- buffer_put_cstring(m, name);
+ fatal("sshpam_device.query failed");
+ monitor_permit(mon_dispatch, MONITOR_REQ_PAM_RESPOND, 1);
+ sshbuf_reset(m);
+ if ((r = sshbuf_put_u32(m, ret)) != 0 ||
+ (r = sshbuf_put_cstring(m, name)) != 0 ||
+ (r = sshbuf_put_cstring(m, info)) != 0 ||
+ (r = sshbuf_put_u32(m, sshpam_get_maxtries_reached())) != 0 ||
+ (r = sshbuf_put_u32(m, num)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(name);
- buffer_put_cstring(m, info);
free(info);
- buffer_put_int(m, num);
for (i = 0; i < num; ++i) {
- buffer_put_cstring(m, prompts[i]);
+ if ((r = sshbuf_put_cstring(m, prompts[i])) != 0 ||
+ (r = sshbuf_put_u32(m, echo_on[i])) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(prompts[i]);
- buffer_put_int(m, echo_on[i]);
}
free(prompts);
free(echo_on);
@@ -1140,19 +1097,25 @@ mm_answer_pam_query(int sock, Buffer *m)
}
int
-mm_answer_pam_respond(int sock, Buffer *m)
+mm_answer_pam_respond(struct ssh *ssh, int sock, struct sshbuf *m)
{
char **resp;
u_int i, num;
- int ret;
+ int r, ret;
debug3("%s", __func__);
+ if (sshpam_ctxt == NULL)
+ fatal("%s: no context", __func__);
sshpam_authok = NULL;
- num = buffer_get_int(m);
+ if ((r = sshbuf_get_u32(m, &num)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (num > 0) {
resp = xcalloc(num, sizeof(char *));
- for (i = 0; i < num; ++i)
- resp[i] = buffer_get_string(m, NULL);
+ for (i = 0; i < num; ++i) {
+ if ((r = sshbuf_get_cstring(m, &(resp[i]), NULL)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
+ }
ret = (sshpam_device.respond)(sshpam_ctxt, num, resp);
for (i = 0; i < num; ++i)
free(resp[i]);
@@ -1160,8 +1123,9 @@ mm_answer_pam_respond(int sock, Buffer *m)
} else {
ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL);
}
- buffer_clear(m);
- buffer_put_int(m, ret);
+ sshbuf_reset(m);
+ if ((r = sshbuf_put_u32(m, ret)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m);
auth_method = "keyboard-interactive";
auth_submethod = "pam";
@@ -1171,275 +1135,297 @@ mm_answer_pam_respond(int sock, Buffer *m)
}
int
-mm_answer_pam_free_ctx(int sock, Buffer *m)
+mm_answer_pam_free_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
{
+ int r = sshpam_authok != NULL && sshpam_authok == sshpam_ctxt;
debug3("%s", __func__);
+ if (sshpam_ctxt == NULL)
+ fatal("%s: no context", __func__);
(sshpam_device.free_ctx)(sshpam_ctxt);
- buffer_clear(m);
+ sshpam_ctxt = sshpam_authok = NULL;
+ sshbuf_reset(m);
mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m);
+ /* Allow another attempt */
+ monitor_permit(mon_dispatch, MONITOR_REQ_PAM_INIT_CTX, 1);
auth_method = "keyboard-interactive";
auth_submethod = "pam";
- return (sshpam_authok == sshpam_ctxt);
+ return r;
}
#endif
int
-mm_answer_keyallowed(int sock, Buffer *m)
+mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m)
{
- Key *key;
+ struct sshkey *key = NULL;
char *cuser, *chost;
- u_char *blob;
- u_int bloblen;
+ u_int pubkey_auth_attempt;
enum mm_keytype type = 0;
- int allowed = 0;
+ int r, allowed = 0;
+ struct sshauthopt *opts = NULL;
debug3("%s entering", __func__);
-
- type = buffer_get_int(m);
- cuser = buffer_get_string(m, NULL);
- chost = buffer_get_string(m, NULL);
- blob = buffer_get_string(m, &bloblen);
-
- key = key_from_blob(blob, bloblen);
-
- if ((compat20 && type == MM_RSAHOSTKEY) ||
- (!compat20 && type != MM_RSAHOSTKEY))
- fatal("%s: key type and protocol mismatch", __func__);
+ if ((r = sshbuf_get_u32(m, &type)) != 0 ||
+ (r = sshbuf_get_cstring(m, &cuser, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(m, &chost, NULL)) != 0 ||
+ (r = sshkey_froms(m, &key)) != 0 ||
+ (r = sshbuf_get_u32(m, &pubkey_auth_attempt)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("%s: key_from_blob: %p", __func__, key);
if (key != NULL && authctxt->valid) {
/* These should not make it past the privsep child */
- if (key_type_plain(key->type) == KEY_RSA &&
+ if (sshkey_type_plain(key->type) == KEY_RSA &&
(datafellows & SSH_BUG_RSASIGMD5) != 0)
fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__);
switch (type) {
case MM_USERKEY:
- allowed = options.pubkey_authentication &&
- !auth2_userkey_already_used(authctxt, key) &&
- match_pattern_list(sshkey_ssh_name(key),
- options.pubkey_key_types,
- strlen(options.pubkey_key_types), 0) == 1 &&
- user_key_allowed(authctxt->pw, key);
- pubkey_auth_info(authctxt, key, NULL);
auth_method = "publickey";
- if (options.pubkey_authentication && allowed != 1)
- auth_clear_options();
+ if (!options.pubkey_authentication)
+ break;
+ if (auth2_key_already_used(authctxt, key))
+ break;
+ if (!key_base_type_match(auth_method, key,
+ options.pubkey_key_types))
+ break;
+ allowed = user_key_allowed(ssh, authctxt->pw, key,
+ pubkey_auth_attempt, &opts);
break;
case MM_HOSTKEY:
- allowed = options.hostbased_authentication &&
- match_pattern_list(sshkey_ssh_name(key),
- options.hostbased_key_types,
- strlen(options.hostbased_key_types), 0) == 1 &&
- hostbased_key_allowed(authctxt->pw,
+ auth_method = "hostbased";
+ if (!options.hostbased_authentication)
+ break;
+ if (auth2_key_already_used(authctxt, key))
+ break;
+ if (!key_base_type_match(auth_method, key,
+ options.hostbased_key_types))
+ break;
+ allowed = hostbased_key_allowed(ssh, authctxt->pw,
cuser, chost, key);
- pubkey_auth_info(authctxt, key,
+ auth2_record_info(authctxt,
"client user \"%.100s\", client host \"%.100s\"",
cuser, chost);
- auth_method = "hostbased";
break;
-#ifdef WITH_SSH1
- case MM_RSAHOSTKEY:
- key->type = KEY_RSA1; /* XXX */
- allowed = options.rhosts_rsa_authentication &&
- auth_rhosts_rsa_key_allowed(authctxt->pw,
- cuser, chost, key);
- if (options.rhosts_rsa_authentication && allowed != 1)
- auth_clear_options();
- auth_method = "rsa";
- break;
-#endif
default:
fatal("%s: unknown key type %d", __func__, type);
break;
}
}
- if (key != NULL)
- key_free(key);
+
+ debug3("%s: %s authentication%s: %s key is %s", __func__,
+ auth_method, pubkey_auth_attempt ? "" : " test",
+ (key == NULL || !authctxt->valid) ? "invalid" : sshkey_type(key),
+ allowed ? "allowed" : "not allowed");
+
+ auth2_record_key(authctxt, 0, key);
/* clear temporarily storage (used by verify) */
monitor_reset_key_state();
if (allowed) {
/* Save temporarily for comparison in verify */
- key_blob = blob;
- key_bloblen = bloblen;
+ if ((r = sshkey_to_blob(key, &key_blob, &key_bloblen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
key_blobtype = type;
+ key_opts = opts;
hostbased_cuser = cuser;
hostbased_chost = chost;
} else {
/* Log failed attempt */
- auth_log(authctxt, 0, 0, auth_method, NULL);
- free(blob);
+ auth_log(ssh, 0, 0, auth_method, NULL);
free(cuser);
free(chost);
}
+ sshkey_free(key);
- debug3("%s: key %p is %s",
- __func__, key, allowed ? "allowed" : "not allowed");
-
- buffer_clear(m);
- buffer_put_int(m, allowed);
- buffer_put_int(m, forced_command != NULL);
-
+ sshbuf_reset(m);
+ if ((r = sshbuf_put_u32(m, allowed)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0)
+ fatal("%s: sshauthopt_serialise: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m);
- if (type == MM_RSAHOSTKEY)
- monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
+ if (!allowed)
+ sshauthopt_free(opts);
return (0);
}
static int
-monitor_valid_userblob(u_char *data, u_int datalen)
+monitor_valid_userblob(const u_char *data, u_int datalen)
{
- Buffer b;
- char *p, *userstyle;
- u_int len;
- int fail = 0;
+ struct sshbuf *b;
+ const u_char *p;
+ char *userstyle, *cp;
+ size_t len;
+ u_char type;
+ int r, fail = 0;
- buffer_init(&b);
- buffer_append(&b, data, datalen);
+ if ((b = sshbuf_from(data, datalen)) == NULL)
+ fatal("%s: sshbuf_from", __func__);
if (datafellows & SSH_OLD_SESSIONID) {
- p = buffer_ptr(&b);
- len = buffer_len(&b);
+ p = sshbuf_ptr(b);
+ len = sshbuf_len(b);
if ((session_id2 == NULL) ||
(len < session_id2_len) ||
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
fail++;
- buffer_consume(&b, session_id2_len);
+ if ((r = sshbuf_consume(b, session_id2_len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
} else {
- p = buffer_get_string(&b, &len);
+ if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if ((session_id2 == NULL) ||
(len != session_id2_len) ||
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
fail++;
- free(p);
}
- if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+ if ((r = sshbuf_get_u8(b, &type)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (type != SSH2_MSG_USERAUTH_REQUEST)
fail++;
- p = buffer_get_cstring(&b, NULL);
+ if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
xasprintf(&userstyle, "%s%s%s", authctxt->user,
authctxt->style ? ":" : "",
authctxt->style ? authctxt->style : "");
- if (strcmp(userstyle, p) != 0) {
- logit("wrong user name passed to monitor: expected %s != %.100s",
- userstyle, p);
+ if (strcmp(userstyle, cp) != 0) {
+ logit("wrong user name passed to monitor: "
+ "expected %s != %.100s", userstyle, cp);
fail++;
}
free(userstyle);
- free(p);
- buffer_skip_string(&b);
- if (datafellows & SSH_BUG_PKAUTH) {
- if (!buffer_get_char(&b))
- fail++;
- } else {
- p = buffer_get_cstring(&b, NULL);
- if (strcmp("publickey", p) != 0)
- fail++;
- free(p);
- if (!buffer_get_char(&b))
- fail++;
- buffer_skip_string(&b);
- }
- buffer_skip_string(&b);
- if (buffer_len(&b) != 0)
+ free(cp);
+ if ((r = sshbuf_skip_string(b)) != 0 || /* service */
+ (r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (strcmp("publickey", cp) != 0)
fail++;
- buffer_free(&b);
+ free(cp);
+ if ((r = sshbuf_get_u8(b, &type)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (type == 0)
+ fail++;
+ if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */
+ (r = sshbuf_skip_string(b)) != 0) /* pkblob */
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (sshbuf_len(b) != 0)
+ fail++;
+ sshbuf_free(b);
return (fail == 0);
}
static int
-monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
- char *chost)
+monitor_valid_hostbasedblob(const u_char *data, u_int datalen,
+ const char *cuser, const char *chost)
{
- Buffer b;
- char *p, *userstyle;
- u_int len;
- int fail = 0;
+ struct sshbuf *b;
+ const u_char *p;
+ char *cp, *userstyle;
+ size_t len;
+ int r, fail = 0;
+ u_char type;
- buffer_init(&b);
- buffer_append(&b, data, datalen);
+ if ((b = sshbuf_from(data, datalen)) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- p = buffer_get_string(&b, &len);
if ((session_id2 == NULL) ||
(len != session_id2_len) ||
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
fail++;
- free(p);
- if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+ if ((r = sshbuf_get_u8(b, &type)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (type != SSH2_MSG_USERAUTH_REQUEST)
fail++;
- p = buffer_get_cstring(&b, NULL);
+ if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
xasprintf(&userstyle, "%s%s%s", authctxt->user,
authctxt->style ? ":" : "",
authctxt->style ? authctxt->style : "");
- if (strcmp(userstyle, p) != 0) {
- logit("wrong user name passed to monitor: expected %s != %.100s",
- userstyle, p);
+ if (strcmp(userstyle, cp) != 0) {
+ logit("wrong user name passed to monitor: "
+ "expected %s != %.100s", userstyle, cp);
fail++;
}
free(userstyle);
- free(p);
- buffer_skip_string(&b); /* service */
- p = buffer_get_cstring(&b, NULL);
- if (strcmp(p, "hostbased") != 0)
+ free(cp);
+ if ((r = sshbuf_skip_string(b)) != 0 || /* service */
+ (r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (strcmp(cp, "hostbased") != 0)
fail++;
- free(p);
- buffer_skip_string(&b); /* pkalg */
- buffer_skip_string(&b); /* pkblob */
+ free(cp);
+ if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */
+ (r = sshbuf_skip_string(b)) != 0) /* pkblob */
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* verify client host, strip trailing dot if necessary */
- p = buffer_get_string(&b, NULL);
- if (((len = strlen(p)) > 0) && p[len - 1] == '.')
- p[len - 1] = '\0';
- if (strcmp(p, chost) != 0)
+ if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (((len = strlen(cp)) > 0) && cp[len - 1] == '.')
+ cp[len - 1] = '\0';
+ if (strcmp(cp, chost) != 0)
fail++;
- free(p);
+ free(cp);
/* verify client user */
- p = buffer_get_string(&b, NULL);
- if (strcmp(p, cuser) != 0)
+ if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (strcmp(cp, cuser) != 0)
fail++;
- free(p);
+ free(cp);
- if (buffer_len(&b) != 0)
+ if (sshbuf_len(b) != 0)
fail++;
- buffer_free(&b);
+ sshbuf_free(b);
return (fail == 0);
}
int
-mm_answer_keyverify(int sock, Buffer *m)
+mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
{
- Key *key;
- u_char *signature, *data, *blob;
- u_int signaturelen, datalen, bloblen;
- int verified = 0;
- int valid_data = 0;
-
- blob = buffer_get_string(m, &bloblen);
- signature = buffer_get_string(m, &signaturelen);
- data = buffer_get_string(m, &datalen);
+ struct sshkey *key;
+ 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;
+ 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));
if (hostbased_cuser == NULL || hostbased_chost == NULL ||
!monitor_allowed_key(blob, bloblen))
fatal("%s: bad key, not previously allowed", __func__);
- key = key_from_blob(blob, bloblen);
- if (key == NULL)
- fatal("%s: bad public key blob", __func__);
+ /* Empty signature algorithm means NULL. */
+ if (*sigalg == '\0') {
+ free(sigalg);
+ sigalg = NULL;
+ }
+
+ /* XXX use sshkey_froms here; need to change key_blob, etc. */
+ if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0)
+ fatal("%s: bad public key blob: %s", __func__, ssh_err(r));
switch (key_blobtype) {
case MM_USERKEY:
valid_data = monitor_valid_userblob(data, datalen);
+ auth_method = "publickey";
break;
case MM_HOSTKEY:
valid_data = monitor_valid_hostbasedblob(data, datalen,
hostbased_cuser, hostbased_chost);
+ auth_method = "hostbased";
break;
default:
valid_data = 0;
@@ -1448,33 +1434,62 @@ mm_answer_keyverify(int sock, Buffer *m)
if (!valid_data)
fatal("%s: bad signature data blob", __func__);
- verified = key_verify(key, signature, signaturelen, data, datalen);
- debug3("%s: key %p signature %s",
- __func__, key, (verified == 1) ? "verified" : "unverified");
-
- /* If auth was successful then record key to ensure it isn't reused */
- if (verified == 1)
- auth2_record_userkey(authctxt, key);
- else
- key_free(key);
-
- free(blob);
- free(signature);
- free(data);
-
- auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
+ if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
+ SSH_FP_DEFAULT)) == NULL)
+ fatal("%s: sshkey_fingerprint failed", __func__);
+
+ 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,
+ (ret == 0) ? "verified" : "unverified",
+ (ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : "");
+
+ if (ret == 0 && key_blobtype == MM_USERKEY && sig_details != NULL) {
+ req_presence = (options.pubkey_auth_options &
+ PUBKEYAUTH_TOUCH_REQUIRED) ||
+ !key_opts->no_require_user_presence;
+ if (req_presence &&
+ (sig_details->sk_flags & SSH_SK_USER_PRESENCE_REQD) == 0) {
+ error("public key %s %s signature for %s%s from %.128s "
+ "port %d rejected: user presence "
+ "(authenticator touch) requirement not met ",
+ sshkey_type(key), fp,
+ authctxt->valid ? "" : "invalid user ",
+ authctxt->user, ssh_remote_ipaddr(ssh),
+ ssh_remote_port(ssh));
+ ret = SSH_ERR_SIGNATURE_INVALID;
+ }
+ }
+ auth2_record_key(authctxt, ret == 0, key);
+ if (key_blobtype == MM_USERKEY)
+ auth_activate_options(ssh, key_opts);
monitor_reset_key_state();
- buffer_clear(m);
- buffer_put_int(m, verified);
+ sshbuf_reset(m);
+
+ /* encode ret != 0 as positive integer, since we're sending u32 */
+ encoded_ret = (ret != 0);
+ if ((r = sshbuf_put_u32(m, encoded_ret)) != 0 ||
+ (r = sshbuf_put_u8(m, sig_details != NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ 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));
+ }
+ sshkey_sig_details_free(sig_details);
mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
- return (verified == 1);
+ free(sigalg);
+ free(fp);
+ sshkey_free(key);
+
+ return ret == 0;
}
static void
-mm_record_login(Session *s, struct passwd *pw)
+mm_record_login(struct ssh *ssh, Session *s, struct passwd *pw)
{
socklen_t fromlen;
struct sockaddr_storage from;
@@ -1485,16 +1500,16 @@ mm_record_login(Session *s, struct passwd *pw)
*/
memset(&from, 0, sizeof(from));
fromlen = sizeof(from);
- if (packet_connection_is_on_socket()) {
- if (getpeername(packet_get_connection_in(),
- (struct sockaddr *)&from, &fromlen) < 0) {
+ if (ssh_packet_connection_is_on_socket(ssh)) {
+ if (getpeername(ssh_packet_get_connection_in(ssh),
+ (struct sockaddr *)&from, &fromlen) == -1) {
debug("getpeername: %.100s", strerror(errno));
cleanup_exit(255);
}
}
/* Record that there was a login on that tty from the remote host. */
record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
- get_remote_name_or_ip(utmp_len, options.use_dns),
+ session_get_remote_name_or_ip(ssh, utmp_len, options.use_dns),
(struct sockaddr *)&from, fromlen);
}
@@ -1510,15 +1525,15 @@ mm_session_close(Session *s)
}
int
-mm_answer_pty(int sock, Buffer *m)
+mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m)
{
extern struct monitor *pmonitor;
Session *s;
- int res, fd0;
+ int r, res, fd0;
debug3("%s entering", __func__);
- buffer_clear(m);
+ sshbuf_reset(m);
s = session_new();
if (s == NULL)
goto error;
@@ -1530,21 +1545,23 @@ mm_answer_pty(int sock, Buffer *m)
goto error;
pty_setowner(authctxt->pw, s->tty);
- buffer_put_int(m, 1);
- buffer_put_cstring(m, s->tty);
+ if ((r = sshbuf_put_u32(m, 1)) != 0 ||
+ (r = sshbuf_put_cstring(m, s->tty)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* We need to trick ttyslot */
if (dup2(s->ttyfd, 0) == -1)
fatal("%s: dup2", __func__);
- mm_record_login(s, authctxt->pw);
+ mm_record_login(ssh, s, authctxt->pw);
/* Now we can close the file descriptor again */
close(0);
/* send messages generated by record_login */
- buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg));
- buffer_clear(&loginmsg);
+ if ((r = sshbuf_put_stringb(m, loginmsg)) != 0)
+ fatal("%s: put login message: %s", __func__, ssh_err(r));
+ sshbuf_reset(loginmsg);
mm_request_send(sock, MONITOR_ANS_PTY, m);
@@ -1553,7 +1570,7 @@ mm_answer_pty(int sock, Buffer *m)
fatal("%s: send fds failed", __func__);
/* make sure nothing uses fd 0 */
- if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
+ if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) == -1)
fatal("%s: open(/dev/null): %s", __func__, strerror(errno));
if (fd0 != 0)
error("%s: fd0 %d != 0", __func__, fd0);
@@ -1571,209 +1588,32 @@ mm_answer_pty(int sock, Buffer *m)
error:
if (s != NULL)
mm_session_close(s);
- buffer_put_int(m, 0);
+ if ((r = sshbuf_put_u32(m, 0)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_PTY, m);
return (0);
}
int
-mm_answer_pty_cleanup(int sock, Buffer *m)
+mm_answer_pty_cleanup(struct ssh *ssh, int sock, struct sshbuf *m)
{
Session *s;
char *tty;
+ int r;
debug3("%s entering", __func__);
- tty = buffer_get_string(m, NULL);
+ if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if ((s = session_by_tty(tty)) != NULL)
mm_session_close(s);
- buffer_clear(m);
+ sshbuf_reset(m);
free(tty);
return (0);
}
-#ifdef WITH_SSH1
int
-mm_answer_sesskey(int sock, Buffer *m)
-{
- BIGNUM *p;
- int rsafail;
-
- /* Turn off permissions */
- monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 0);
-
- if ((p = BN_new()) == NULL)
- fatal("%s: BN_new", __func__);
-
- buffer_get_bignum2(m, p);
-
- rsafail = ssh1_session_key(p);
-
- buffer_clear(m);
- buffer_put_int(m, rsafail);
- buffer_put_bignum2(m, p);
-
- BN_clear_free(p);
-
- mm_request_send(sock, MONITOR_ANS_SESSKEY, m);
-
- /* Turn on permissions for sessid passing */
- monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1);
-
- return (0);
-}
-
-int
-mm_answer_sessid(int sock, Buffer *m)
-{
- int i;
-
- debug3("%s entering", __func__);
-
- if (buffer_len(m) != 16)
- fatal("%s: bad ssh1 session id", __func__);
- for (i = 0; i < 16; i++)
- session_id[i] = buffer_get_char(m);
-
- /* Turn on permissions for getpwnam */
- monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
-
- return (0);
-}
-
-int
-mm_answer_rsa_keyallowed(int sock, Buffer *m)
-{
- BIGNUM *client_n;
- Key *key = NULL;
- u_char *blob = NULL;
- u_int blen = 0;
- int allowed = 0;
-
- debug3("%s entering", __func__);
-
- auth_method = "rsa";
- if (options.rsa_authentication && authctxt->valid) {
- if ((client_n = BN_new()) == NULL)
- fatal("%s: BN_new", __func__);
- buffer_get_bignum2(m, client_n);
- allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key);
- BN_clear_free(client_n);
- }
- buffer_clear(m);
- buffer_put_int(m, allowed);
- buffer_put_int(m, forced_command != NULL);
-
- /* clear temporarily storage (used by generate challenge) */
- monitor_reset_key_state();
-
- if (allowed && key != NULL) {
- key->type = KEY_RSA; /* cheat for key_to_blob */
- if (key_to_blob(key, &blob, &blen) == 0)
- fatal("%s: key_to_blob failed", __func__);
- buffer_put_string(m, blob, blen);
-
- /* Save temporarily for comparison in verify */
- key_blob = blob;
- key_bloblen = blen;
- key_blobtype = MM_RSAUSERKEY;
- }
- if (key != NULL)
- key_free(key);
-
- mm_request_send(sock, MONITOR_ANS_RSAKEYALLOWED, m);
-
- monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
- monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0);
- return (0);
-}
-
-int
-mm_answer_rsa_challenge(int sock, Buffer *m)
-{
- Key *key = NULL;
- u_char *blob;
- u_int blen;
-
- debug3("%s entering", __func__);
-
- if (!authctxt->valid)
- fatal("%s: authctxt not valid", __func__);
- blob = buffer_get_string(m, &blen);
- if (!monitor_allowed_key(blob, blen))
- fatal("%s: bad key, not previously allowed", __func__);
- if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
- fatal("%s: key type mismatch", __func__);
- if ((key = key_from_blob(blob, blen)) == NULL)
- fatal("%s: received bad key", __func__);
- if (key->type != KEY_RSA)
- fatal("%s: received bad key type %d", __func__, key->type);
- key->type = KEY_RSA1;
- if (ssh1_challenge)
- BN_clear_free(ssh1_challenge);
- ssh1_challenge = auth_rsa_generate_challenge(key);
-
- buffer_clear(m);
- buffer_put_bignum2(m, ssh1_challenge);
-
- debug3("%s sending reply", __func__);
- mm_request_send(sock, MONITOR_ANS_RSACHALLENGE, m);
-
- monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1);
-
- free(blob);
- key_free(key);
- return (0);
-}
-
-int
-mm_answer_rsa_response(int sock, Buffer *m)
-{
- Key *key = NULL;
- u_char *blob, *response;
- u_int blen, len;
- int success;
-
- debug3("%s entering", __func__);
-
- if (!authctxt->valid)
- fatal("%s: authctxt not valid", __func__);
- if (ssh1_challenge == NULL)
- fatal("%s: no ssh1_challenge", __func__);
-
- blob = buffer_get_string(m, &blen);
- if (!monitor_allowed_key(blob, blen))
- fatal("%s: bad key, not previously allowed", __func__);
- if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
- fatal("%s: key type mismatch: %d", __func__, key_blobtype);
- if ((key = key_from_blob(blob, blen)) == NULL)
- fatal("%s: received bad key", __func__);
- response = buffer_get_string(m, &len);
- if (len != 16)
- fatal("%s: received bad response to challenge", __func__);
- success = auth_rsa_verify_response(key, ssh1_challenge, response);
-
- free(blob);
- key_free(key);
- free(response);
-
- auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa";
-
- /* reset state */
- BN_clear_free(ssh1_challenge);
- ssh1_challenge = NULL;
- monitor_reset_key_state();
-
- buffer_clear(m);
- buffer_put_int(m, success);
- mm_request_send(sock, MONITOR_ANS_RSARESPONSE, m);
-
- return (success);
-}
-#endif
-
-int
-mm_answer_term(int sock, Buffer *req)
+mm_answer_term(struct ssh *ssh, int sock, struct sshbuf *req)
{
extern struct monitor *pmonitor;
int res, status;
@@ -1781,7 +1621,7 @@ mm_answer_term(int sock, Buffer *req)
debug3("%s: tearing down sessions", __func__);
/* The child is terminating */
- session_destroy_all(&mm_session_close);
+ session_destroy_all(ssh, &mm_session_close);
#ifdef USE_PAM
if (options.use_pam)
@@ -1801,14 +1641,18 @@ mm_answer_term(int sock, Buffer *req)
#ifdef SSH_AUDIT_EVENTS
/* Report that an audit event occurred */
int
-mm_answer_audit_event(int socket, Buffer *m)
+mm_answer_audit_event(struct ssh *ssh, int socket, struct sshbuf *m)
{
+ u_int n;
ssh_audit_event_t event;
+ int r;
debug3("%s entering", __func__);
- event = buffer_get_int(m);
- switch(event) {
+ if ((r = sshbuf_get_u32(m, &n)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ event = (ssh_audit_event_t)n;
+ switch (event) {
case SSH_AUTH_FAIL_PUBKEY:
case SSH_AUTH_FAIL_HOSTBASED:
case SSH_AUTH_FAIL_GSSAPI:
@@ -1816,7 +1660,7 @@ mm_answer_audit_event(int socket, Buffer *m)
case SSH_LOGIN_ROOT_DENIED:
case SSH_CONNECTION_CLOSE:
case SSH_INVALID_USER:
- audit_event(event);
+ audit_event(ssh, event);
break;
default:
fatal("Audit event type %d not permitted", event);
@@ -1826,13 +1670,14 @@ mm_answer_audit_event(int socket, Buffer *m)
}
int
-mm_answer_audit_command(int socket, Buffer *m)
+mm_answer_audit_command(struct ssh *ssh, int socket, struct sshbuf *m)
{
- u_int len;
char *cmd;
+ int r;
debug3("%s entering", __func__);
- cmd = buffer_get_string(m, &len);
+ if ((r = sshbuf_get_cstring(m, &cmd, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* sanity check command, if so how? */
audit_run_command(cmd);
free(cmd);
@@ -1841,9 +1686,17 @@ mm_answer_audit_command(int socket, Buffer *m)
#endif /* SSH_AUDIT_EVENTS */
void
-monitor_apply_keystate(struct monitor *pmonitor)
+monitor_clear_keystate(struct ssh *ssh, struct monitor *pmonitor)
+{
+ ssh_clear_newkeys(ssh, MODE_IN);
+ ssh_clear_newkeys(ssh, MODE_OUT);
+ sshbuf_free(child_state);
+ child_state = NULL;
+}
+
+void
+monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor)
{
- struct ssh *ssh = active_state; /* XXX */
struct kex *kex;
int r;
@@ -1853,36 +1706,33 @@ monitor_apply_keystate(struct monitor *pmonitor)
sshbuf_free(child_state);
child_state = NULL;
- if ((kex = ssh->kex) != 0) {
+ if ((kex = ssh->kex) != NULL) {
/* XXX set callbacks */
#ifdef WITH_OPENSSL
- kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
- kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
+ kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
+ kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
+ kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
+ kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
+ kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
# ifdef OPENSSL_HAS_ECC
- kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+ kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
# endif
#endif /* WITH_OPENSSL */
- kex->kex[KEX_C25519_SHA256] = kexc25519_server;
+ kex->kex[KEX_C25519_SHA256] = kex_gen_server;
+ kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
kex->load_host_public_key=&get_hostkey_public_by_type;
kex->load_host_private_key=&get_hostkey_private_by_type;
kex->host_key_index=&get_hostkey_index;
kex->sign = sshd_hostkey_sign;
}
-
- /* Update with new address */
- if (options.compression) {
- ssh_packet_set_compress_hooks(ssh, pmonitor->m_zlib,
- (ssh_packet_comp_alloc_func *)mm_zalloc,
- (ssh_packet_comp_free_func *)mm_zfree);
- }
}
-/* This function requries careful sanity checking */
+/* This function requires careful sanity checking */
void
-mm_get_keystate(struct monitor *pmonitor)
+mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor)
{
debug3("%s: Waiting for new keys", __func__);
@@ -1905,9 +1755,18 @@ static void
monitor_openfds(struct monitor *mon, int do_logfds)
{
int pair[2];
+#ifdef SO_ZEROIZE
+ int on = 1;
+#endif
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
fatal("%s: socketpair: %s", __func__, strerror(errno));
+#ifdef SO_ZEROIZE
+ if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) == -1)
+ error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno));
+ if (setsockopt(pair[1], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) == -1)
+ error("setsockopt SO_ZEROIZE(1): %.100s", strerror(errno));
+#endif
FD_CLOSEONEXEC(pair[0]);
FD_CLOSEONEXEC(pair[1]);
mon->m_recvfd = pair[0];
@@ -1929,24 +1788,11 @@ monitor_openfds(struct monitor *mon, int do_logfds)
struct monitor *
monitor_init(void)
{
- struct ssh *ssh = active_state; /* XXX */
struct monitor *mon;
mon = xcalloc(1, sizeof(*mon));
-
monitor_openfds(mon, 1);
- /* Used to share zlib space across processes */
- if (options.compression) {
- mon->m_zback = mm_create(NULL, MM_MEMSIZE);
- mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE);
-
- /* Compression needs to share state across borders */
- ssh_packet_set_compress_hooks(ssh, mon->m_zlib,
- (ssh_packet_comp_alloc_func *)mm_zalloc,
- (ssh_packet_comp_free_func *)mm_zfree);
- }
-
return mon;
}
@@ -1958,21 +1804,29 @@ monitor_reinit(struct monitor *mon)
#ifdef GSSAPI
int
-mm_answer_gss_setup_ctx(int sock, Buffer *m)
+mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
{
gss_OID_desc goid;
OM_uint32 major;
- u_int len;
+ size_t len;
+ u_char *p;
+ int r;
+
+ if (!options.gss_authentication)
+ fatal("%s: GSSAPI authentication not enabled", __func__);
- goid.elements = buffer_get_string(m, &len);
+ if ((r = sshbuf_get_string(m, &p, &len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ goid.elements = p;
goid.length = len;
major = ssh_gssapi_server_ctx(&gsscontext, &goid);
free(goid.elements);
- buffer_clear(m);
- buffer_put_int(m, major);
+ sshbuf_reset(m);
+ if ((r = sshbuf_put_u32(m, major)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_GSSSETUP, m);
@@ -1983,23 +1837,27 @@ mm_answer_gss_setup_ctx(int sock, Buffer *m)
}
int
-mm_answer_gss_accept_ctx(int sock, Buffer *m)
+mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
{
gss_buffer_desc in;
gss_buffer_desc out = GSS_C_EMPTY_BUFFER;
OM_uint32 major, minor;
OM_uint32 flags = 0; /* GSI needs this */
- u_int len;
+ int r;
+
+ if (!options.gss_authentication)
+ fatal("%s: GSSAPI authentication not enabled", __func__);
- in.value = buffer_get_string(m, &len);
- in.length = len;
+ if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
free(in.value);
- buffer_clear(m);
- buffer_put_int(m, major);
- buffer_put_string(m, out.value, out.length);
- buffer_put_int(m, flags);
+ sshbuf_reset(m);
+ if ((r = sshbuf_put_u32(m, major)) != 0 ||
+ (r = sshbuf_put_string(m, out.value, out.length)) != 0 ||
+ (r = sshbuf_put_u32(m, flags)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_GSSSTEP, m);
gss_release_buffer(&minor, &out);
@@ -2013,24 +1871,27 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m)
}
int
-mm_answer_gss_checkmic(int sock, Buffer *m)
+mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m)
{
gss_buffer_desc gssbuf, mic;
OM_uint32 ret;
- u_int len;
+ int r;
- gssbuf.value = buffer_get_string(m, &len);
- gssbuf.length = len;
- mic.value = buffer_get_string(m, &len);
- mic.length = len;
+ if (!options.gss_authentication)
+ fatal("%s: GSSAPI authentication not enabled", __func__);
+
+ if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 ||
+ (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic);
free(gssbuf.value);
free(mic.value);
- buffer_clear(m);
- buffer_put_int(m, ret);
+ sshbuf_reset(m);
+ if ((r = sshbuf_put_u32(m, ret)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m);
@@ -2041,20 +1902,28 @@ mm_answer_gss_checkmic(int sock, Buffer *m)
}
int
-mm_answer_gss_userok(int sock, Buffer *m)
+mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m)
{
- int authenticated;
+ int r, authenticated;
+ const char *displayname;
+
+ if (!options.gss_authentication)
+ fatal("%s: GSSAPI authentication not enabled", __func__);
authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
- buffer_clear(m);
- buffer_put_int(m, authenticated);
+ sshbuf_reset(m);
+ if ((r = sshbuf_put_u32(m, authenticated)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("%s: sending result %d", __func__, authenticated);
mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m);
auth_method = "gssapi-with-mic";
+ if ((displayname = ssh_gssapi_displayname()) != NULL)
+ auth2_record_info(authctxt, "%s", displayname);
+
/* Monitor loop will terminate if authenticated */
return (authenticated);
}
diff --git a/monitor.h b/monitor.h
index 93b8b66d..683e5e07 100644
--- a/monitor.h
+++ b/monitor.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.h,v 1.19 2015/01/19 19:52:16 markus Exp $ */
+/* $OpenBSD: monitor.h,v 1.23 2019/01/19 21:43:56 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -39,8 +39,6 @@ enum monitor_reqtype {
MONITOR_REQ_AUTHPASSWORD = 12, MONITOR_ANS_AUTHPASSWORD = 13,
MONITOR_REQ_BSDAUTHQUERY = 14, MONITOR_ANS_BSDAUTHQUERY = 15,
MONITOR_REQ_BSDAUTHRESPOND = 16, MONITOR_ANS_BSDAUTHRESPOND = 17,
- MONITOR_REQ_SKEYQUERY = 18, MONITOR_ANS_SKEYQUERY = 19,
- MONITOR_REQ_SKEYRESPOND = 20, MONITOR_ANS_SKEYRESPOND = 21,
MONITOR_REQ_KEYALLOWED = 22, MONITOR_ANS_KEYALLOWED = 23,
MONITOR_REQ_KEYVERIFY = 24, MONITOR_ANS_KEYVERIFY = 25,
MONITOR_REQ_KEYEXPORT = 26,
@@ -67,32 +65,31 @@ enum monitor_reqtype {
};
-struct mm_master;
+struct ssh;
+
struct monitor {
int m_recvfd;
int m_sendfd;
int m_log_recvfd;
int m_log_sendfd;
- struct mm_master *m_zback;
- struct mm_master *m_zlib;
struct kex **m_pkex;
pid_t m_pid;
};
struct monitor *monitor_init(void);
void monitor_reinit(struct monitor *);
-void monitor_sync(struct monitor *);
struct Authctxt;
-void monitor_child_preauth(struct Authctxt *, struct monitor *);
-void monitor_child_postauth(struct monitor *);
+void monitor_child_preauth(struct ssh *, struct monitor *);
+void monitor_child_postauth(struct ssh *, struct monitor *);
-struct mon_table;
-int monitor_read(struct monitor*, struct mon_table *, struct mon_table **);
+void monitor_clear_keystate(struct ssh *, struct monitor *);
+void monitor_apply_keystate(struct ssh *, struct monitor *);
/* Prototypes for request sending and receiving */
-void mm_request_send(int, enum monitor_reqtype, Buffer *);
-void mm_request_receive(int, Buffer *);
-void mm_request_receive_expect(int, enum monitor_reqtype, Buffer *);
+void mm_request_send(int, enum monitor_reqtype, struct sshbuf *);
+void mm_request_receive(int, struct sshbuf *);
+void mm_request_receive_expect(int, enum monitor_reqtype, struct sshbuf *);
+void mm_get_keystate(struct ssh *, struct monitor *);
#endif /* _MONITOR_H_ */
diff --git a/monitor_fdpass.c b/monitor_fdpass.c
index 2ddd8073..d766edcf 100644
--- a/monitor_fdpass.c
+++ b/monitor_fdpass.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_fdpass.c,v 1.20 2015/02/25 23:05:47 djm Exp $ */
+/* $OpenBSD: monitor_fdpass.c,v 1.21 2016/02/29 20:22:36 jca Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -99,8 +99,7 @@ mm_send_fd(int sock, int fd)
}
if (n != 1) {
- error("%s: sendmsg: expected sent 1 got %ld",
- __func__, (long)n);
+ error("%s: sendmsg: expected sent 1 got %zd", __func__, n);
return -1;
}
return 0;
@@ -155,8 +154,7 @@ mm_receive_fd(int sock)
}
if (n != 1) {
- error("%s: recvmsg: expected received 1 got %ld",
- __func__, (long)n);
+ error("%s: recvmsg: expected received 1 got %zd", __func__, n);
return -1;
}
diff --git a/monitor_mm.c b/monitor_mm.c
deleted file mode 100644
index aa47b2ed..00000000
--- a/monitor_mm.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/* $OpenBSD: monitor_mm.c,v 1.21 2015/02/06 23:21:59 millert Exp $ */
-/*
- * Copyright 2002 Niels Provos <provos@citi.umich.edu>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-#include "openbsd-compat/sys-tree.h"
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stddef.h>
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
-
-#include "xmalloc.h"
-#include "ssh.h"
-#include "log.h"
-#include "monitor_mm.h"
-
-static int
-mm_compare(struct mm_share *a, struct mm_share *b)
-{
- ptrdiff_t diff = (char *)a->address - (char *)b->address;
-
- if (diff == 0)
- return (0);
- else if (diff < 0)
- return (-1);
- else
- return (1);
-}
-
-RB_GENERATE(mmtree, mm_share, next, mm_compare)
-
-static struct mm_share *
-mm_make_entry(struct mm_master *mm, struct mmtree *head,
- void *address, size_t size)
-{
- struct mm_share *tmp, *tmp2;
-
- if (mm->mmalloc == NULL)
- tmp = xcalloc(1, sizeof(struct mm_share));
- else
- tmp = mm_xmalloc(mm->mmalloc, sizeof(struct mm_share));
- tmp->address = address;
- tmp->size = size;
-
- tmp2 = RB_INSERT(mmtree, head, tmp);
- if (tmp2 != NULL)
- fatal("mm_make_entry(%p): double address %p->%p(%zu)",
- mm, tmp2, address, size);
-
- return (tmp);
-}
-
-/* Creates a shared memory area of a certain size */
-
-struct mm_master *
-mm_create(struct mm_master *mmalloc, size_t size)
-{
- void *address;
- struct mm_master *mm;
-
- if (mmalloc == NULL)
- mm = xcalloc(1, sizeof(struct mm_master));
- else
- mm = mm_xmalloc(mmalloc, sizeof(struct mm_master));
-
- /*
- * If the memory map has a mm_master it can be completely
- * shared including authentication between the child
- * and the client.
- */
- mm->mmalloc = mmalloc;
-
- address = xmmap(size);
- if (address == (void *)MAP_FAILED)
- fatal("mmap(%zu): %s", size, strerror(errno));
-
- mm->address = address;
- mm->size = size;
-
- RB_INIT(&mm->rb_free);
- RB_INIT(&mm->rb_allocated);
-
- mm_make_entry(mm, &mm->rb_free, address, size);
-
- return (mm);
-}
-
-/* Frees either the allocated or the free list */
-
-static void
-mm_freelist(struct mm_master *mmalloc, struct mmtree *head)
-{
- struct mm_share *mms, *next;
-
- for (mms = RB_ROOT(head); mms; mms = next) {
- next = RB_NEXT(mmtree, head, mms);
- RB_REMOVE(mmtree, head, mms);
- if (mmalloc == NULL)
- free(mms);
- else
- mm_free(mmalloc, mms);
- }
-}
-
-/* Destroys a memory mapped area */
-
-void
-mm_destroy(struct mm_master *mm)
-{
- mm_freelist(mm->mmalloc, &mm->rb_free);
- mm_freelist(mm->mmalloc, &mm->rb_allocated);
-
-#ifdef HAVE_MMAP
- if (munmap(mm->address, mm->size) == -1)
- fatal("munmap(%p, %zu): %s", mm->address, mm->size,
- strerror(errno));
-#else
- fatal("%s: UsePrivilegeSeparation=yes and Compression=yes not supported",
- __func__);
-#endif
- if (mm->mmalloc == NULL)
- free(mm);
- else
- mm_free(mm->mmalloc, mm);
-}
-
-void *
-mm_xmalloc(struct mm_master *mm, size_t size)
-{
- void *address;
-
- address = mm_malloc(mm, size);
- if (address == NULL)
- fatal("%s: mm_malloc(%zu)", __func__, size);
- memset(address, 0, size);
- return (address);
-}
-
-
-/* Allocates data from a memory mapped area */
-
-void *
-mm_malloc(struct mm_master *mm, size_t size)
-{
- struct mm_share *mms, *tmp;
-
- if (size == 0)
- fatal("mm_malloc: try to allocate 0 space");
- if (size > SIZE_MAX - MM_MINSIZE + 1)
- fatal("mm_malloc: size too big");
-
- size = ((size + (MM_MINSIZE - 1)) / MM_MINSIZE) * MM_MINSIZE;
-
- RB_FOREACH(mms, mmtree, &mm->rb_free) {
- if (mms->size >= size)
- break;
- }
-
- if (mms == NULL)
- return (NULL);
-
- /* Debug */
- memset(mms->address, 0xd0, size);
-
- tmp = mm_make_entry(mm, &mm->rb_allocated, mms->address, size);
-
- /* Does not change order in RB tree */
- mms->size -= size;
- mms->address = (char *)mms->address + size;
-
- if (mms->size == 0) {
- RB_REMOVE(mmtree, &mm->rb_free, mms);
- if (mm->mmalloc == NULL)
- free(mms);
- else
- mm_free(mm->mmalloc, mms);
- }
-
- return (tmp->address);
-}
-
-/* Frees memory in a memory mapped area */
-
-void
-mm_free(struct mm_master *mm, void *address)
-{
- struct mm_share *mms, *prev, tmp;
-
- tmp.address = address;
- mms = RB_FIND(mmtree, &mm->rb_allocated, &tmp);
- if (mms == NULL)
- fatal("mm_free(%p): can not find %p", mm, address);
-
- /* Debug */
- memset(mms->address, 0xd0, mms->size);
-
- /* Remove from allocated list and insert in free list */
- RB_REMOVE(mmtree, &mm->rb_allocated, mms);
- if (RB_INSERT(mmtree, &mm->rb_free, mms) != NULL)
- fatal("mm_free(%p): double address %p", mm, address);
-
- /* Find previous entry */
- prev = mms;
- if (RB_LEFT(prev, next)) {
- prev = RB_LEFT(prev, next);
- while (RB_RIGHT(prev, next))
- prev = RB_RIGHT(prev, next);
- } else {
- if (RB_PARENT(prev, next) &&
- (prev == RB_RIGHT(RB_PARENT(prev, next), next)))
- prev = RB_PARENT(prev, next);
- else {
- while (RB_PARENT(prev, next) &&
- (prev == RB_LEFT(RB_PARENT(prev, next), next)))
- prev = RB_PARENT(prev, next);
- prev = RB_PARENT(prev, next);
- }
- }
-
- /* Check if range does not overlap */
- if (prev != NULL && MM_ADDRESS_END(prev) > address)
- fatal("mm_free: memory corruption: %p(%zu) > %p",
- prev->address, prev->size, address);
-
- /* See if we can merge backwards */
- if (prev != NULL && MM_ADDRESS_END(prev) == address) {
- prev->size += mms->size;
- RB_REMOVE(mmtree, &mm->rb_free, mms);
- if (mm->mmalloc == NULL)
- free(mms);
- else
- mm_free(mm->mmalloc, mms);
- } else
- prev = mms;
-
- if (prev == NULL)
- return;
-
- /* Check if we can merge forwards */
- mms = RB_NEXT(mmtree, &mm->rb_free, prev);
- if (mms == NULL)
- return;
-
- if (MM_ADDRESS_END(prev) > mms->address)
- fatal("mm_free: memory corruption: %p < %p(%zu)",
- mms->address, prev->address, prev->size);
- if (MM_ADDRESS_END(prev) != mms->address)
- return;
-
- prev->size += mms->size;
- RB_REMOVE(mmtree, &mm->rb_free, mms);
-
- if (mm->mmalloc == NULL)
- free(mms);
- else
- mm_free(mm->mmalloc, mms);
-}
-
-static void
-mm_sync_list(struct mmtree *oldtree, struct mmtree *newtree,
- struct mm_master *mm, struct mm_master *mmold)
-{
- struct mm_master *mmalloc = mm->mmalloc;
- struct mm_share *mms, *new;
-
- /* Sync free list */
- RB_FOREACH(mms, mmtree, oldtree) {
- /* Check the values */
- mm_memvalid(mmold, mms, sizeof(struct mm_share));
- mm_memvalid(mm, mms->address, mms->size);
-
- new = mm_xmalloc(mmalloc, sizeof(struct mm_share));
- memcpy(new, mms, sizeof(struct mm_share));
- RB_INSERT(mmtree, newtree, new);
- }
-}
-
-void
-mm_share_sync(struct mm_master **pmm, struct mm_master **pmmalloc)
-{
- struct mm_master *mm;
- struct mm_master *mmalloc;
- struct mm_master *mmold;
- struct mmtree rb_free, rb_allocated;
-
- debug3("%s: Share sync", __func__);
-
- mm = *pmm;
- mmold = mm->mmalloc;
- mm_memvalid(mmold, mm, sizeof(*mm));
-
- mmalloc = mm_create(NULL, mm->size);
- mm = mm_xmalloc(mmalloc, sizeof(struct mm_master));
- memcpy(mm, *pmm, sizeof(struct mm_master));
- mm->mmalloc = mmalloc;
-
- rb_free = mm->rb_free;
- rb_allocated = mm->rb_allocated;
-
- RB_INIT(&mm->rb_free);
- RB_INIT(&mm->rb_allocated);
-
- mm_sync_list(&rb_free, &mm->rb_free, mm, mmold);
- mm_sync_list(&rb_allocated, &mm->rb_allocated, mm, mmold);
-
- mm_destroy(mmold);
-
- *pmm = mm;
- *pmmalloc = mmalloc;
-
- debug3("%s: Share sync end", __func__);
-}
-
-void
-mm_memvalid(struct mm_master *mm, void *address, size_t size)
-{
- void *end = (char *)address + size;
-
- if (address < mm->address)
- fatal("mm_memvalid: address too small: %p", address);
- if (end < address)
- fatal("mm_memvalid: end < address: %p < %p", end, address);
- if (end > MM_ADDRESS_END(mm))
- fatal("mm_memvalid: address too large: %p", address);
-}
diff --git a/monitor_mm.h b/monitor_mm.h
deleted file mode 100644
index f1fae7e3..00000000
--- a/monitor_mm.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* $OpenBSD: monitor_mm.h,v 1.6 2014/01/04 17:50:55 tedu Exp $ */
-
-/*
- * Copyright 2002 Niels Provos <provos@citi.umich.edu>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _MM_H_
-#define _MM_H_
-
-struct mm_share {
- RB_ENTRY(mm_share) next;
- void *address;
- size_t size;
-};
-
-struct mm_master {
- RB_HEAD(mmtree, mm_share) rb_free;
- struct mmtree rb_allocated;
- void *address;
- size_t size;
-
- struct mm_master *mmalloc; /* Used to completely share */
-};
-
-RB_PROTOTYPE(mmtree, mm_share, next, mm_compare)
-
-#define MM_MINSIZE 128
-
-#define MM_ADDRESS_END(x) (void *)((char *)(x)->address + (x)->size)
-
-struct mm_master *mm_create(struct mm_master *, size_t);
-void mm_destroy(struct mm_master *);
-
-void mm_share_sync(struct mm_master **, struct mm_master **);
-
-void *mm_malloc(struct mm_master *, size_t);
-void *mm_xmalloc(struct mm_master *, size_t);
-void mm_free(struct mm_master *, void *);
-
-void mm_memvalid(struct mm_master *, void *, size_t);
-#endif /* _MM_H_ */
diff --git a/monitor_wrap.c b/monitor_wrap.c
index b379f055..001a8fa1 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.c,v 1.84 2015/02/16 22:13:32 djm Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.117 2019/12/15 18:57:30 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -50,8 +50,8 @@
#ifdef WITH_OPENSSL
#include "dh.h"
#endif
-#include "buffer.h"
-#include "key.h"
+#include "sshbuf.h"
+#include "sshkey.h"
#include "cipher.h"
#include "kex.h"
#include "hostfile.h"
@@ -60,13 +60,7 @@
#include "packet.h"
#include "mac.h"
#include "log.h"
-#ifdef TARGET_OS_MAC /* XXX Broken krb5 headers on Mac */
-#undef TARGET_OS_MAC
-#include "zlib.h"
-#define TARGET_OS_MAC 1
-#else
-#include "zlib.h"
-#endif
+#include "auth-pam.h"
#include "monitor.h"
#ifdef GSSAPI
#include "ssh-gss.h"
@@ -75,47 +69,43 @@
#include "atomicio.h"
#include "monitor_fdpass.h"
#include "misc.h"
-#include "uuencode.h"
#include "channels.h"
#include "session.h"
#include "servconf.h"
-#include "roaming.h"
#include "ssherr.h"
/* Imports */
-extern int compat20;
-extern z_stream incoming_stream;
-extern z_stream outgoing_stream;
extern struct monitor *pmonitor;
-extern Buffer loginmsg;
+extern struct sshbuf *loginmsg;
extern ServerOptions options;
void
mm_log_handler(LogLevel level, const char *msg, void *ctx)
{
- Buffer log_msg;
+ struct sshbuf *log_msg;
struct monitor *mon = (struct monitor *)ctx;
+ int r;
+ size_t len;
if (mon->m_log_sendfd == -1)
fatal("%s: no log channel", __func__);
- buffer_init(&log_msg);
- /*
- * Placeholder for packet length. Will be filled in with the actual
- * packet length once the packet has been constucted. This saves
- * fragile math.
- */
- buffer_put_int(&log_msg, 0);
+ if ((log_msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
- buffer_put_int(&log_msg, level);
- buffer_put_cstring(&log_msg, msg);
- put_u32(buffer_ptr(&log_msg), buffer_len(&log_msg) - 4);
- if (atomicio(vwrite, mon->m_log_sendfd, buffer_ptr(&log_msg),
- buffer_len(&log_msg)) != buffer_len(&log_msg))
+ if ((r = sshbuf_put_u32(log_msg, 0)) != 0 || /* length; filled below */
+ (r = sshbuf_put_u32(log_msg, level)) != 0 ||
+ (r = sshbuf_put_cstring(log_msg, msg)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if ((len = sshbuf_len(log_msg)) < 4 || len > 0xffffffff)
+ fatal("%s: bad length %zu", __func__, len);
+ POKE_U32(sshbuf_mutable_ptr(log_msg), len - 4);
+ if (atomicio(vwrite, mon->m_log_sendfd,
+ sshbuf_mutable_ptr(log_msg), len) != len)
fatal("%s: write: %s", __func__, strerror(errno));
- buffer_free(&log_msg);
+ sshbuf_free(log_msg);
}
int
@@ -129,54 +119,58 @@ mm_is_monitor(void)
}
void
-mm_request_send(int sock, enum monitor_reqtype type, Buffer *m)
+mm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m)
{
- u_int mlen = buffer_len(m);
+ size_t mlen = sshbuf_len(m);
u_char buf[5];
debug3("%s entering: type %d", __func__, type);
- put_u32(buf, mlen + 1);
+ if (mlen >= 0xffffffff)
+ fatal("%s: bad length %zu", __func__, mlen);
+ POKE_U32(buf, mlen + 1);
buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */
if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
fatal("%s: write: %s", __func__, strerror(errno));
- if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen)
+ if (atomicio(vwrite, sock, sshbuf_mutable_ptr(m), mlen) != mlen)
fatal("%s: write: %s", __func__, strerror(errno));
}
void
-mm_request_receive(int sock, Buffer *m)
+mm_request_receive(int sock, struct sshbuf *m)
{
- u_char buf[4];
+ u_char buf[4], *p = NULL;
u_int msg_len;
+ int r;
debug3("%s entering", __func__);
if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
- if (errno == EPIPE) {
- error("%s: socket closed", __func__);
+ if (errno == EPIPE)
cleanup_exit(255);
- }
fatal("%s: read: %s", __func__, strerror(errno));
}
- msg_len = get_u32(buf);
+ msg_len = PEEK_U32(buf);
if (msg_len > 256 * 1024)
fatal("%s: read: bad msg_len %d", __func__, msg_len);
- buffer_clear(m);
- buffer_append_space(m, msg_len);
- if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len)
+ sshbuf_reset(m);
+ if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (atomicio(read, sock, p, msg_len) != msg_len)
fatal("%s: read: %s", __func__, strerror(errno));
}
void
-mm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m)
+mm_request_receive_expect(int sock, enum monitor_reqtype type, struct sshbuf *m)
{
u_char rtype;
+ int r;
debug3("%s entering: type %d", __func__, type);
mm_request_receive(sock, m);
- rtype = buffer_get_char(m);
+ if ((r = sshbuf_get_u8(m, &rtype)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (rtype != type)
fatal("%s: read: rtype %d != type %d", __func__,
rtype, type);
@@ -187,109 +181,145 @@ DH *
mm_choose_dh(int min, int nbits, int max)
{
BIGNUM *p, *g;
- int success = 0;
- Buffer m;
+ int r;
+ u_char success = 0;
+ struct sshbuf *m;
- buffer_init(&m);
- buffer_put_int(&m, min);
- buffer_put_int(&m, nbits);
- buffer_put_int(&m, max);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u32(m, min)) != 0 ||
+ (r = sshbuf_put_u32(m, nbits)) != 0 ||
+ (r = sshbuf_put_u32(m, max)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, m);
debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, m);
- success = buffer_get_char(&m);
+ if ((r = sshbuf_get_u8(m, &success)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (success == 0)
fatal("%s: MONITOR_ANS_MODULI failed", __func__);
- if ((p = BN_new()) == NULL)
- fatal("%s: BN_new failed", __func__);
- if ((g = BN_new()) == NULL)
- fatal("%s: BN_new failed", __func__);
- buffer_get_bignum2(&m, p);
- buffer_get_bignum2(&m, g);
+ if ((r = sshbuf_get_bignum2(m, &p)) != 0 ||
+ (r = sshbuf_get_bignum2(m, &g)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- debug3("%s: remaining %d", __func__, buffer_len(&m));
- buffer_free(&m);
+ debug3("%s: remaining %zu", __func__, sshbuf_len(m));
+ sshbuf_free(m);
return (dh_new_group(g, p));
}
#endif
int
-mm_key_sign(Key *key, u_char **sigp, u_int *lenp,
- const u_char *data, u_int datalen)
+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)
{
struct kex *kex = *pmonitor->m_pkex;
- Buffer m;
+ struct sshbuf *m;
+ u_int ndx = kex->host_key_index(key, 0, ssh);
+ int r;
debug3("%s entering", __func__);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u32(m, ndx)) != 0 ||
+ (r = sshbuf_put_string(m, data, datalen)) != 0 ||
+ (r = sshbuf_put_cstring(m, hostkey_alg)) != 0 ||
+ (r = sshbuf_put_u32(m, compat)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- buffer_init(&m);
- buffer_put_int(&m, kex->host_key_index(key, 0, active_state));
- buffer_put_string(&m, data, datalen);
-
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, m);
debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
- *sigp = buffer_get_string(&m, lenp);
- buffer_free(&m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, m);
+ if ((r = sshbuf_get_string(m, sigp, lenp)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
return (0);
}
struct passwd *
-mm_getpwnamallow(const char *username)
+mm_getpwnamallow(struct ssh *ssh, const char *username)
{
- Buffer m;
+ struct sshbuf *m;
struct passwd *pw;
- u_int len, i;
+ size_t len;
+ u_int i;
ServerOptions *newopts;
+ int r;
+ u_char ok;
+ const u_char *p;
debug3("%s entering", __func__);
- buffer_init(&m);
- buffer_put_cstring(&m, username);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_cstring(m, username)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, m);
debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, m);
- if (buffer_get_char(&m) == 0) {
+ if ((r = sshbuf_get_u8(m, &ok)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (ok == 0) {
pw = NULL;
goto out;
}
- pw = buffer_get_string(&m, &len);
- if (len != sizeof(struct passwd))
+
+ /* 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__);
- pw->pw_name = buffer_get_string(&m, NULL);
- pw->pw_passwd = buffer_get_string(&m, NULL);
+ memcpy(pw, p, sizeof(*pw));
+
+ if ((r = sshbuf_get_cstring(m, &pw->pw_name, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(m, &pw->pw_passwd, NULL)) != 0 ||
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
- pw->pw_gecos = buffer_get_string(&m, NULL);
+ (r = sshbuf_get_cstring(m, &pw->pw_gecos, NULL)) != 0 ||
#endif
#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
- pw->pw_class = buffer_get_string(&m, NULL);
+ (r = sshbuf_get_cstring(m, &pw->pw_class, NULL)) != 0 ||
#endif
- pw->pw_dir = buffer_get_string(&m, NULL);
- pw->pw_shell = buffer_get_string(&m, NULL);
+ (r = sshbuf_get_cstring(m, &pw->pw_dir, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(m, &pw->pw_shell, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
out:
/* copy options block as a Match directive may have changed some */
- newopts = buffer_get_string(&m, &len);
+ if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (len != sizeof(*newopts))
fatal("%s: option block size mismatch", __func__);
+ newopts = xcalloc(sizeof(*newopts), 1);
+ memcpy(newopts, p, sizeof(*newopts));
#define M_CP_STROPT(x) do { \
- if (newopts->x != NULL) \
- newopts->x = buffer_get_string(&m, NULL); \
+ if (newopts->x != NULL) { \
+ if ((r = sshbuf_get_cstring(m, \
+ &newopts->x, NULL)) != 0) \
+ fatal("%s: buffer error: %s", \
+ __func__, ssh_err(r)); \
+ } \
} while (0)
#define M_CP_STRARRAYOPT(x, nx) do { \
- for (i = 0; i < newopts->nx; i++) \
- newopts->x[i] = buffer_get_string(&m, NULL); \
+ newopts->x = newopts->nx == 0 ? \
+ NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \
+ for (i = 0; i < newopts->nx; i++) { \
+ if ((r = sshbuf_get_cstring(m, \
+ &newopts->x[i], NULL)) != 0) \
+ fatal("%s: buffer error: %s", \
+ __func__, ssh_err(r)); \
+ } \
} while (0)
/* See comment in servconf.h */
COPY_MATCH_STRING_OPTS();
@@ -297,9 +327,11 @@ out:
#undef M_CP_STRARRAYOPT
copy_set_server_options(&options, newopts, 1);
+ log_change_level(options.log_level);
+ process_permitopen(ssh, &options);
free(newopts);
- buffer_free(&m);
+ sshbuf_free(m);
return (pw);
}
@@ -307,19 +339,22 @@ out:
char *
mm_auth2_read_banner(void)
{
- Buffer m;
+ struct sshbuf *m;
char *banner;
+ int r;
debug3("%s entering", __func__);
- buffer_init(&m);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
- buffer_clear(&m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, m);
+ sshbuf_reset(m);
mm_request_receive_expect(pmonitor->m_recvfd,
- MONITOR_ANS_AUTH2_READ_BANNER, &m);
- banner = buffer_get_string(&m, NULL);
- buffer_free(&m);
+ MONITOR_ANS_AUTH2_READ_BANNER, m);
+ if ((r = sshbuf_get_cstring(m, &banner, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
/* treat empty banner as missing banner */
if (strlen(banner) == 0) {
@@ -334,38 +369,55 @@ mm_auth2_read_banner(void)
void
mm_inform_authserv(char *service, char *style)
{
- Buffer m;
+ struct sshbuf *m;
+ int r;
debug3("%s entering", __func__);
- buffer_init(&m);
- buffer_put_cstring(&m, service);
- buffer_put_cstring(&m, style ? style : "");
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_cstring(m, service)) != 0 ||
+ (r = sshbuf_put_cstring(m, style ? style : "")) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m);
- buffer_free(&m);
+ sshbuf_free(m);
}
/* Do the password authentication */
int
-mm_auth_password(Authctxt *authctxt, char *password)
+mm_auth_password(struct ssh *ssh, char *password)
{
- Buffer m;
- int authenticated = 0;
+ struct sshbuf *m;
+ int r, authenticated = 0;
+#ifdef USE_PAM
+ u_int maxtries = 0;
+#endif
debug3("%s entering", __func__);
- buffer_init(&m);
- buffer_put_cstring(&m, password);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_cstring(m, password)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, m);
debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_AUTHPASSWORD, m);
- authenticated = buffer_get_int(&m);
+ if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+#ifdef USE_PAM
+ if ((r = sshbuf_get_u32(m, &maxtries)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (maxtries > INT_MAX)
+ fatal("%s: bad maxtries %u", __func__, maxtries);
+ sshpam_set_maxtries_reached(maxtries);
+#endif
- buffer_free(&m);
+ sshbuf_free(m);
debug3("%s: user %sauthenticated",
__func__, authenticated ? "" : "not ");
@@ -373,66 +425,64 @@ mm_auth_password(Authctxt *authctxt, char *password)
}
int
-mm_user_key_allowed(struct passwd *pw, Key *key)
-{
- return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
-}
-
-int
-mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
- Key *key)
+mm_user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
+ int pubkey_auth_attempt, struct sshauthopt **authoptp)
{
- return (mm_key_allowed(MM_HOSTKEY, user, host, key));
+ return (mm_key_allowed(MM_USERKEY, NULL, NULL, key,
+ pubkey_auth_attempt, authoptp));
}
int
-mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
- char *host, Key *key)
+mm_hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
+ const char *user, const char *host, struct sshkey *key)
{
- int ret;
-
- key->type = KEY_RSA; /* XXX hack for key_to_blob */
- ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
- key->type = KEY_RSA1;
- return (ret);
+ return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0, NULL));
}
int
-mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
+mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
+ struct sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp)
{
- Buffer m;
- u_char *blob;
- u_int len;
- int allowed = 0, have_forced = 0;
+ struct sshbuf *m;
+ int r, allowed = 0;
+ struct sshauthopt *opts = NULL;
debug3("%s entering", __func__);
- /* Convert the key to a blob and the pass it over */
- if (!key_to_blob(key, &blob, &len))
- return (0);
+ if (authoptp != NULL)
+ *authoptp = NULL;
- buffer_init(&m);
- buffer_put_int(&m, type);
- buffer_put_cstring(&m, user ? user : "");
- buffer_put_cstring(&m, host ? host : "");
- buffer_put_string(&m, blob, len);
- free(blob);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u32(m, type)) != 0 ||
+ (r = sshbuf_put_cstring(m, user ? user : "")) != 0 ||
+ (r = sshbuf_put_cstring(m, host ? host : "")) != 0 ||
+ (r = sshkey_puts(key, m)) != 0 ||
+ (r = sshbuf_put_u32(m, pubkey_auth_attempt)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, m);
debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
-
- allowed = buffer_get_int(&m);
-
- /* fake forced command */
- auth_clear_options();
- have_forced = buffer_get_int(&m);
- forced_command = have_forced ? xstrdup("true") : NULL;
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_KEYALLOWED, m);
+
+ if ((r = sshbuf_get_u32(m, &allowed)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (allowed && type == MM_USERKEY) {
+ if ((r = sshauthopt_deserialise(m, &opts)) != 0)
+ fatal("%s: sshauthopt_deserialise: %s",
+ __func__, ssh_err(r));
+ }
+ sshbuf_free(m);
- buffer_free(&m);
+ if (authoptp != NULL) {
+ *authoptp = opts;
+ opts = NULL;
+ }
+ sshauthopt_free(opts);
- return (allowed);
+ return allowed;
}
/*
@@ -442,41 +492,58 @@ mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
*/
int
-mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
+mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
+ const u_char *data, size_t datalen, const char *sigalg, u_int compat,
+ struct sshkey_sig_details **sig_detailsp)
{
- Buffer m;
- u_char *blob;
- u_int len;
- int verified = 0;
+ struct sshbuf *m;
+ u_int encoded_ret = 0;
+ int r;
+ u_char sig_details_present, flags;
+ u_int counter;
debug3("%s entering", __func__);
- /* Convert the key to a blob and the pass it over */
- if (!key_to_blob(key, &blob, &len))
- return (0);
-
- buffer_init(&m);
- buffer_put_string(&m, blob, len);
- buffer_put_string(&m, sig, siglen);
- buffer_put_string(&m, data, datalen);
- free(blob);
+ if (sig_detailsp != NULL)
+ *sig_detailsp = NULL;
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshkey_puts(key, m)) != 0 ||
+ (r = sshbuf_put_string(m, sig, siglen)) != 0 ||
+ (r = sshbuf_put_string(m, data, datalen)) != 0 ||
+ (r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, m);
debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
-
- verified = buffer_get_int(&m);
+ 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));
+ 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));
+ if (sig_detailsp != NULL) {
+ *sig_detailsp = xcalloc(1, sizeof(**sig_detailsp));
+ (*sig_detailsp)->sk_counter = counter;
+ (*sig_detailsp)->sk_flags = flags;
+ }
+ }
- buffer_free(&m);
+ sshbuf_free(m);
- return (verified);
+ if (encoded_ret != 0)
+ return SSH_ERR_SIGNATURE_INVALID;
+ return 0;
}
void
-mm_send_keystate(struct monitor *monitor)
+mm_send_keystate(struct ssh *ssh, struct monitor *monitor)
{
- struct ssh *ssh = active_state; /* XXX */
struct sshbuf *m;
int r;
@@ -493,9 +560,9 @@ mm_send_keystate(struct monitor *monitor)
int
mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
{
- Buffer m;
+ struct sshbuf *m;
char *p, *msg;
- int success = 0, tmp1 = -1, tmp2 = -1;
+ int success = 0, tmp1 = -1, tmp2 = -1, r;
/* Kludge: ensure there are fds free to receive the pty/tty */
if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
@@ -510,26 +577,30 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
close(tmp1);
close(tmp2);
- buffer_init(&m);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, m);
debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, m);
- success = buffer_get_int(&m);
+ if ((r = sshbuf_get_u32(m, &success)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (success == 0) {
debug3("%s: pty alloc failed", __func__);
- buffer_free(&m);
+ sshbuf_free(m);
return (0);
}
- p = buffer_get_string(&m, NULL);
- msg = buffer_get_string(&m, NULL);
- buffer_free(&m);
+ if ((r = sshbuf_get_cstring(m, &p, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(m, &msg, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
strlcpy(namebuf, p, namebuflen); /* Possible truncation */
free(p);
- buffer_append(&loginmsg, msg, strlen(msg));
+ if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(msg);
if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
@@ -543,17 +614,20 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
void
mm_session_pty_cleanup2(Session *s)
{
- Buffer m;
+ struct sshbuf *m;
+ int r;
if (s->ttyfd == -1)
return;
- buffer_init(&m);
- buffer_put_cstring(&m, s->tty);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
- buffer_free(&m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_cstring(m, s->tty)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, m);
+ sshbuf_free(m);
/* closed dup'ed master */
- if (s->ptymaster != -1 && close(s->ptymaster) < 0)
+ if (s->ptymaster != -1 && close(s->ptymaster) == -1)
error("close(s->ptymaster/%d): %s",
s->ptymaster, strerror(errno));
@@ -563,42 +637,46 @@ mm_session_pty_cleanup2(Session *s)
#ifdef USE_PAM
void
-mm_start_pam(Authctxt *authctxt)
+mm_start_pam(struct ssh *ssh)
{
- Buffer m;
+ struct sshbuf *m;
debug3("%s entering", __func__);
if (!options.use_pam)
fatal("UsePAM=no, but ended up in %s anyway", __func__);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, m);
- buffer_init(&m);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m);
-
- buffer_free(&m);
+ sshbuf_free(m);
}
u_int
mm_do_pam_account(void)
{
- Buffer m;
+ struct sshbuf *m;
u_int ret;
char *msg;
+ size_t msglen;
+ int r;
debug3("%s entering", __func__);
if (!options.use_pam)
fatal("UsePAM=no, but ended up in %s anyway", __func__);
- buffer_init(&m);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, &m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, m);
mm_request_receive_expect(pmonitor->m_recvfd,
- MONITOR_ANS_PAM_ACCOUNT, &m);
- ret = buffer_get_int(&m);
- msg = buffer_get_string(&m, NULL);
- buffer_append(&loginmsg, msg, strlen(msg));
- free(msg);
+ MONITOR_ANS_PAM_ACCOUNT, m);
+ if ((r = sshbuf_get_u32(m, &ret)) != 0 ||
+ (r = sshbuf_get_cstring(m, &msg, &msglen)) != 0 ||
+ (r = sshbuf_put(loginmsg, msg, msglen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- buffer_free(&m);
+ free(msg);
+ sshbuf_free(m);
debug3("%s returning %d", __func__, ret);
@@ -608,22 +686,24 @@ mm_do_pam_account(void)
void *
mm_sshpam_init_ctx(Authctxt *authctxt)
{
- Buffer m;
- int success;
+ struct sshbuf *m;
+ int r, success;
debug3("%s", __func__);
- buffer_init(&m);
- buffer_put_cstring(&m, authctxt->user);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, &m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, m);
debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, &m);
- success = buffer_get_int(&m);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_PAM_INIT_CTX, m);
+ if ((r = sshbuf_get_u32(m, &success)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (success == 0) {
debug3("%s: pam_init_ctx failed", __func__);
- buffer_free(&m);
+ sshbuf_free(m);
return (NULL);
}
- buffer_free(&m);
+ sshbuf_free(m);
return (authctxt);
}
@@ -631,65 +711,79 @@ int
mm_sshpam_query(void *ctx, char **name, char **info,
u_int *num, char ***prompts, u_int **echo_on)
{
- Buffer m;
- u_int i;
- int ret;
+ struct sshbuf *m;
+ u_int i, n;
+ int r, ret;
debug3("%s", __func__);
- buffer_init(&m);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, &m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, m);
debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, &m);
- ret = buffer_get_int(&m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, m);
+ if ((r = sshbuf_get_u32(m, &ret)) != 0 ||
+ (r = sshbuf_get_cstring(m, name, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(m, info, NULL)) != 0 ||
+ (r = sshbuf_get_u32(m, &n)) != 0 ||
+ (r = sshbuf_get_u32(m, num)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("%s: pam_query returned %d", __func__, ret);
- *name = buffer_get_string(&m, NULL);
- *info = buffer_get_string(&m, NULL);
- *num = buffer_get_int(&m);
+ sshpam_set_maxtries_reached(n);
if (*num > PAM_MAX_NUM_MSG)
- fatal("%s: recieved %u PAM messages, expected <= %u",
+ fatal("%s: received %u PAM messages, expected <= %u",
__func__, *num, PAM_MAX_NUM_MSG);
*prompts = xcalloc((*num + 1), sizeof(char *));
*echo_on = xcalloc((*num + 1), sizeof(u_int));
for (i = 0; i < *num; ++i) {
- (*prompts)[i] = buffer_get_string(&m, NULL);
- (*echo_on)[i] = buffer_get_int(&m);
+ if ((r = sshbuf_get_cstring(m, &((*prompts)[i]), NULL)) != 0 ||
+ (r = sshbuf_get_u32(m, &((*echo_on)[i]))) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
- buffer_free(&m);
+ sshbuf_free(m);
return (ret);
}
int
mm_sshpam_respond(void *ctx, u_int num, char **resp)
{
- Buffer m;
- u_int i;
- int ret;
+ struct sshbuf *m;
+ u_int n, i;
+ int r, ret;
debug3("%s", __func__);
- buffer_init(&m);
- buffer_put_int(&m, num);
- for (i = 0; i < num; ++i)
- buffer_put_cstring(&m, resp[i]);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u32(m, num)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ for (i = 0; i < num; ++i) {
+ if ((r = sshbuf_put_cstring(m, resp[i])) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ }
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, m);
debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m);
- ret = buffer_get_int(&m);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_PAM_RESPOND, m);
+ if ((r = sshbuf_get_u32(m, &n)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ ret = (int)n; /* XXX */
debug3("%s: pam_respond returned %d", __func__, ret);
- buffer_free(&m);
+ sshbuf_free(m);
return (ret);
}
void
mm_sshpam_free_ctx(void *ctxtp)
{
- Buffer m;
+ struct sshbuf *m;
debug3("%s", __func__);
- buffer_init(&m);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, &m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, m);
debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, &m);
- buffer_free(&m);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_PAM_FREE_CTX, m);
+ sshbuf_free(m);
}
#endif /* USE_PAM */
@@ -698,35 +792,14 @@ mm_sshpam_free_ctx(void *ctxtp)
void
mm_terminate(void)
{
- Buffer m;
+ struct sshbuf *m;
- buffer_init(&m);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
- buffer_free(&m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, m);
+ sshbuf_free(m);
}
-#ifdef WITH_SSH1
-int
-mm_ssh1_session_key(BIGNUM *num)
-{
- int rsafail;
- Buffer m;
-
- buffer_init(&m);
- buffer_put_bignum2(&m, num);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
-
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
-
- rsafail = buffer_get_int(&m);
- buffer_get_bignum2(&m, num);
-
- buffer_free(&m);
-
- return (rsafail);
-}
-#endif
-
static void
mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
char ***prompts, u_int **echo_on)
@@ -743,27 +816,31 @@ int
mm_bsdauth_query(void *ctx, char **name, char **infotxt,
u_int *numprompts, char ***prompts, u_int **echo_on)
{
- Buffer m;
+ struct sshbuf *m;
u_int success;
char *challenge;
+ int r;
debug3("%s: entering", __func__);
- buffer_init(&m);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, m);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
- &m);
- success = buffer_get_int(&m);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_BSDAUTHQUERY, m);
+ if ((r = sshbuf_get_u32(m, &success)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (success == 0) {
debug3("%s: no challenge", __func__);
- buffer_free(&m);
+ sshbuf_free(m);
return (-1);
}
/* Get the challenge, and format the response */
- challenge = buffer_get_string(&m, NULL);
- buffer_free(&m);
+ if ((r = sshbuf_get_cstring(m, &challenge, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
(*prompts)[0] = challenge;
@@ -776,228 +853,62 @@ mm_bsdauth_query(void *ctx, char **name, char **infotxt,
int
mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
{
- Buffer m;
- int authok;
-
- debug3("%s: entering", __func__);
- if (numresponses != 1)
- return (-1);
-
- buffer_init(&m);
- buffer_put_cstring(&m, responses[0]);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
-
- mm_request_receive_expect(pmonitor->m_recvfd,
- MONITOR_ANS_BSDAUTHRESPOND, &m);
-
- authok = buffer_get_int(&m);
- buffer_free(&m);
-
- return ((authok == 0) ? -1 : 0);
-}
-
-#ifdef SKEY
-int
-mm_skey_query(void *ctx, char **name, char **infotxt,
- u_int *numprompts, char ***prompts, u_int **echo_on)
-{
- Buffer m;
- u_int success;
- char *challenge;
-
- debug3("%s: entering", __func__);
-
- buffer_init(&m);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
-
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
- &m);
- success = buffer_get_int(&m);
- if (success == 0) {
- debug3("%s: no challenge", __func__);
- buffer_free(&m);
- return (-1);
- }
-
- /* Get the challenge, and format the response */
- challenge = buffer_get_string(&m, NULL);
- buffer_free(&m);
-
- debug3("%s: received challenge: %s", __func__, challenge);
-
- mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
-
- xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT);
- free(challenge);
-
- return (0);
-}
-
-int
-mm_skey_respond(void *ctx, u_int numresponses, char **responses)
-{
- Buffer m;
- int authok;
+ struct sshbuf *m;
+ int r, authok;
debug3("%s: entering", __func__);
if (numresponses != 1)
return (-1);
- buffer_init(&m);
- buffer_put_cstring(&m, responses[0]);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_cstring(m, responses[0])) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, m);
mm_request_receive_expect(pmonitor->m_recvfd,
- MONITOR_ANS_SKEYRESPOND, &m);
+ MONITOR_ANS_BSDAUTHRESPOND, m);
- authok = buffer_get_int(&m);
- buffer_free(&m);
+ if ((r = sshbuf_get_u32(m, &authok)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
return ((authok == 0) ? -1 : 0);
}
-#endif /* SKEY */
-
-void
-mm_ssh1_session_id(u_char session_id[16])
-{
- Buffer m;
- int i;
-
- debug3("%s entering", __func__);
-
- buffer_init(&m);
- for (i = 0; i < 16; i++)
- buffer_put_char(&m, session_id[i]);
-
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m);
- buffer_free(&m);
-}
-
-#ifdef WITH_SSH1
-int
-mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
-{
- Buffer m;
- Key *key;
- u_char *blob;
- u_int blen;
- int allowed = 0, have_forced = 0;
-
- debug3("%s entering", __func__);
-
- buffer_init(&m);
- buffer_put_bignum2(&m, client_n);
-
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
-
- allowed = buffer_get_int(&m);
-
- /* fake forced command */
- auth_clear_options();
- have_forced = buffer_get_int(&m);
- forced_command = have_forced ? xstrdup("true") : NULL;
-
- if (allowed && rkey != NULL) {
- blob = buffer_get_string(&m, &blen);
- if ((key = key_from_blob(blob, blen)) == NULL)
- fatal("%s: key_from_blob failed", __func__);
- *rkey = key;
- free(blob);
- }
- buffer_free(&m);
-
- return (allowed);
-}
-
-BIGNUM *
-mm_auth_rsa_generate_challenge(Key *key)
-{
- Buffer m;
- BIGNUM *challenge;
- u_char *blob;
- u_int blen;
-
- debug3("%s entering", __func__);
-
- if ((challenge = BN_new()) == NULL)
- fatal("%s: BN_new failed", __func__);
-
- key->type = KEY_RSA; /* XXX cheat for key_to_blob */
- if (key_to_blob(key, &blob, &blen) == 0)
- fatal("%s: key_to_blob failed", __func__);
- key->type = KEY_RSA1;
-
- buffer_init(&m);
- buffer_put_string(&m, blob, blen);
- free(blob);
-
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
-
- buffer_get_bignum2(&m, challenge);
- buffer_free(&m);
-
- return (challenge);
-}
-
-int
-mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
-{
- Buffer m;
- u_char *blob;
- u_int blen;
- int success = 0;
-
- debug3("%s entering", __func__);
-
- key->type = KEY_RSA; /* XXX cheat for key_to_blob */
- if (key_to_blob(key, &blob, &blen) == 0)
- fatal("%s: key_to_blob failed", __func__);
- key->type = KEY_RSA1;
-
- buffer_init(&m);
- buffer_put_string(&m, blob, blen);
- buffer_put_string(&m, response, 16);
- free(blob);
-
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
-
- success = buffer_get_int(&m);
- buffer_free(&m);
-
- return (success);
-}
-#endif
#ifdef SSH_AUDIT_EVENTS
void
-mm_audit_event(ssh_audit_event_t event)
+mm_audit_event(struct ssh *ssh, ssh_audit_event_t event)
{
- Buffer m;
+ struct sshbuf *m;
+ int r;
debug3("%s entering", __func__);
- buffer_init(&m);
- buffer_put_int(&m, event);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u32(m, event)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, &m);
- buffer_free(&m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, m);
+ sshbuf_free(m);
}
void
mm_audit_run_command(const char *command)
{
- Buffer m;
+ struct sshbuf *m;
+ int r;
debug3("%s entering command %s", __func__, command);
- buffer_init(&m);
- buffer_put_cstring(&m, command);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_cstring(m, command)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
- buffer_free(&m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m);
+ sshbuf_free(m);
}
#endif /* SSH_AUDIT_EVENTS */
@@ -1005,45 +916,55 @@ mm_audit_run_command(const char *command)
OM_uint32
mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
{
- Buffer m;
+ struct sshbuf *m;
OM_uint32 major;
+ int r;
/* Client doesn't get to see the context */
*ctx = NULL;
- buffer_init(&m);
- buffer_put_string(&m, goid->elements, goid->length);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_string(m, goid->elements, goid->length)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, m);
- major = buffer_get_int(&m);
+ if ((r = sshbuf_get_u32(m, &major)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- buffer_free(&m);
+ sshbuf_free(m);
return (major);
}
OM_uint32
mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
- gss_buffer_desc *out, OM_uint32 *flags)
+ gss_buffer_desc *out, OM_uint32 *flagsp)
{
- Buffer m;
+ struct sshbuf *m;
OM_uint32 major;
- u_int len;
-
- buffer_init(&m);
- buffer_put_string(&m, in->value, in->length);
-
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
+ u_int flags;
+ int r;
- major = buffer_get_int(&m);
- out->value = buffer_get_string(&m, &len);
- out->length = len;
- if (flags)
- *flags = buffer_get_int(&m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_string(m, in->value, in->length)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, m);
+
+ if ((r = sshbuf_get_u32(m, &major)) != 0 ||
+ (r = ssh_gssapi_get_buffer_desc(m, out)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (flagsp != NULL) {
+ if ((r = sshbuf_get_u32(m, &flags)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ *flagsp = flags;
+ }
- buffer_free(&m);
+ sshbuf_free(m);
return (major);
}
@@ -1051,39 +972,44 @@ mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
OM_uint32
mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
{
- Buffer m;
+ struct sshbuf *m;
OM_uint32 major;
+ int r;
- buffer_init(&m);
- buffer_put_string(&m, gssbuf->value, gssbuf->length);
- buffer_put_string(&m, gssmic->value, gssmic->length);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_string(m, gssbuf->value, gssbuf->length)) != 0 ||
+ (r = sshbuf_put_string(m, gssmic->value, gssmic->length)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, &m);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSCHECKMIC,
- &m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, m);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_GSSCHECKMIC, m);
- major = buffer_get_int(&m);
- buffer_free(&m);
+ if ((r = sshbuf_get_u32(m, &major)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
return(major);
}
int
mm_ssh_gssapi_userok(char *user)
{
- Buffer m;
- int authenticated = 0;
+ struct sshbuf *m;
+ int r, authenticated = 0;
- buffer_init(&m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
- &m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_GSSUSEROK, m);
- authenticated = buffer_get_int(&m);
+ if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- buffer_free(&m);
+ sshbuf_free(m);
debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
return (authenticated);
}
#endif /* GSSAPI */
-
diff --git a/monitor_wrap.h b/monitor_wrap.h
index e18784ac..23ab096a 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.h,v 1.26 2015/02/16 22:13:32 djm Exp $ */
+/* $OpenBSD: monitor_wrap.h,v 1.44 2019/11/25 00:51:37 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -31,28 +31,34 @@
extern int use_privsep;
#define PRIVSEP(x) (use_privsep ? mm_##x : x)
-enum mm_keytype {MM_NOKEY, MM_HOSTKEY, MM_USERKEY, MM_RSAHOSTKEY, MM_RSAUSERKEY};
+enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY };
+struct ssh;
struct monitor;
-struct mm_master;
struct Authctxt;
+struct sshkey;
+struct sshauthopt;
+struct sshkey_sig_details;
void mm_log_handler(LogLevel, const char *, void *);
int mm_is_monitor(void);
+#ifdef WITH_OPENSSL
DH *mm_choose_dh(int, int, int);
-int mm_key_sign(Key *, u_char **, u_int *, const u_char *, u_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);
void mm_inform_authserv(char *, char *);
-struct passwd *mm_getpwnamallow(const char *);
+struct passwd *mm_getpwnamallow(struct ssh *, const char *);
char *mm_auth2_read_banner(void);
-int mm_auth_password(struct Authctxt *, char *);
-int mm_key_allowed(enum mm_keytype, char *, char *, Key *);
-int mm_user_key_allowed(struct passwd *, Key *);
-int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *);
-int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
-int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int);
-int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
-int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
-BIGNUM *mm_auth_rsa_generate_challenge(Key *);
+int mm_auth_password(struct ssh *, char *);
+int mm_key_allowed(enum mm_keytype, const char *, const char *, struct sshkey *,
+ int, struct sshauthopt **);
+int mm_user_key_allowed(struct ssh *, struct passwd *, struct sshkey *, int,
+ struct sshauthopt **);
+int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *,
+ const char *, struct sshkey *);
+int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t,
+ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **);
#ifdef GSSAPI
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
@@ -63,7 +69,7 @@ OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
#endif
#ifdef USE_PAM
-void mm_start_pam(struct Authctxt *);
+void mm_start_pam(struct ssh *ssh);
u_int mm_do_pam_account(void);
void *mm_sshpam_init_ctx(struct Authctxt *);
int mm_sshpam_query(void *, char **, char **, u_int *, char ***, u_int **);
@@ -73,7 +79,7 @@ void mm_sshpam_free_ctx(void *);
#ifdef SSH_AUDIT_EVENTS
#include "audit.h"
-void mm_audit_event(ssh_audit_event_t);
+void mm_audit_event(struct ssh *, ssh_audit_event_t);
void mm_audit_run_command(const char *);
#endif
@@ -82,27 +88,14 @@ void mm_terminate(void);
int mm_pty_allocate(int *, int *, char *, size_t);
void mm_session_pty_cleanup2(struct Session *);
-/* SSHv1 interfaces */
-void mm_ssh1_session_id(u_char *);
-int mm_ssh1_session_key(BIGNUM *);
-
/* Key export functions */
struct newkeys *mm_newkeys_from_blob(u_char *, int);
int mm_newkeys_to_blob(int, u_char **, u_int *);
-void monitor_apply_keystate(struct monitor *);
-void mm_get_keystate(struct monitor *);
-void mm_send_keystate(struct monitor*);
+void mm_send_keystate(struct ssh *, struct monitor*);
/* bsdauth */
int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
int mm_bsdauth_respond(void *, u_int, char **);
-/* skey */
-int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
-int mm_skey_respond(void *, u_int, char **);
-
-/* zlib allocation hooks */
-void mm_init_compression(struct mm_master *);
-
#endif /* _MM_WRAP_H_ */
diff --git a/msg.c b/msg.c
index 5a7b8ca9..99c25cd2 100644
--- a/msg.c
+++ b/msg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: msg.c,v 1.16 2015/01/15 09:40:00 djm Exp $ */
+/* $OpenBSD: msg.c,v 1.18 2020/01/22 04:49:16 djm Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
@@ -47,16 +47,16 @@ ssh_msg_send(int fd, u_char type, struct sshbuf *m)
u_char buf[5];
u_int mlen = sshbuf_len(m);
- debug3("ssh_msg_send: type %u", (unsigned int)type & 0xff);
+ debug3("%s: type %u", __func__, (unsigned int)type & 0xff);
put_u32(buf, mlen + 1);
buf[4] = type; /* 1st byte of payload is mesg-type */
if (atomicio(vwrite, fd, buf, sizeof(buf)) != sizeof(buf)) {
- error("ssh_msg_send: write");
+ error("%s: write: %s", __func__, strerror(errno));
return (-1);
}
- if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(m), mlen) != mlen) {
- error("ssh_msg_send: write");
+ if (atomicio(vwrite, fd, sshbuf_mutable_ptr(m), mlen) != mlen) {
+ error("%s: write: %s", __func__, strerror(errno));
return (-1);
}
return (0);
@@ -73,12 +73,12 @@ ssh_msg_recv(int fd, struct sshbuf *m)
if (atomicio(read, fd, buf, sizeof(buf)) != sizeof(buf)) {
if (errno != EPIPE)
- error("ssh_msg_recv: read: header");
+ error("%s: read header: %s", __func__, strerror(errno));
return (-1);
}
msg_len = get_u32(buf);
if (msg_len > 256 * 1024) {
- error("ssh_msg_recv: read: bad msg_len %u", msg_len);
+ error("%s: read: bad msg_len %u", __func__, msg_len);
return (-1);
}
sshbuf_reset(m);
@@ -87,7 +87,7 @@ ssh_msg_recv(int fd, struct sshbuf *m)
return -1;
}
if (atomicio(read, fd, p, msg_len) != msg_len) {
- error("ssh_msg_recv: read: %s", strerror(errno));
+ error("%s: read: %s", __func__, strerror(errno));
return (-1);
}
return (0);
diff --git a/mux.c b/mux.c
index f3faaeec..fb31ad44 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mux.c,v 1.50 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: mux.c,v 1.82 2020/04/30 17:12:20 markus Exp $ */
/*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
*
@@ -17,19 +17,6 @@
/* ssh session multiplexing support */
-/*
- * TODO:
- * - Better signalling from master to slave, especially passing of
- * error messages
- * - Better fall-back from mux slave error to new connection.
- * - ExitOnForwardingFailure
- * - Maybe extension mechanisms for multi-X11/multi-agent forwarding
- * - Support ~^Z in mux slaves.
- * - Inspect or control sessions in master.
- * - If we ever support the "signal" channel request, send signals on
- * sessions in master.
- */
-
#include "includes.h"
#include <sys/types.h>
@@ -70,15 +57,16 @@
#include "pathnames.h"
#include "misc.h"
#include "match.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "channels.h"
#include "msg.h"
#include "packet.h"
#include "monitor_fdpass.h"
#include "sshpty.h"
-#include "key.h"
+#include "sshkey.h"
#include "readconf.h"
#include "clientloop.h"
+#include "ssherr.h"
/* from ssh.c */
extern int tty_flag;
@@ -86,10 +74,8 @@ extern Options options;
extern int stdin_null_flag;
extern char *host;
extern int subsystem_flag;
-extern Buffer command;
+extern struct sshbuf *command;
extern volatile sig_atomic_t quit_pending;
-extern char *stdio_forward_host;
-extern int stdio_forward_port;
/* Context for session open confirmation callback */
struct mux_session_confirm_ctx {
@@ -97,7 +83,7 @@ struct mux_session_confirm_ctx {
u_int want_subsys;
u_int want_x_fwd;
u_int want_agent_fwd;
- Buffer cmd;
+ struct sshbuf *cmd;
char *term;
struct termios tio;
char **env;
@@ -146,6 +132,7 @@ struct mux_master_state {
#define MUX_C_CLOSE_FWD 0x10000007
#define MUX_C_NEW_STDIO_FWD 0x10000008
#define MUX_C_STOP_LISTENING 0x10000009
+#define MUX_C_PROXY 0x1000000f
#define MUX_S_OK 0x80000001
#define MUX_S_PERMISSION_DENIED 0x80000002
#define MUX_S_FAILURE 0x80000003
@@ -154,88 +141,103 @@ struct mux_master_state {
#define MUX_S_SESSION_OPENED 0x80000006
#define MUX_S_REMOTE_PORT 0x80000007
#define MUX_S_TTY_ALLOC_FAIL 0x80000008
+#define MUX_S_PROXY 0x8000000f
/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */
#define MUX_FWD_LOCAL 1
#define MUX_FWD_REMOTE 2
#define MUX_FWD_DYNAMIC 3
-static void mux_session_confirm(int, int, void *);
-static void mux_stdio_confirm(int, int, void *);
-
-static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *);
-static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *);
-static int process_mux_alive_check(u_int, Channel *, Buffer *, Buffer *);
-static int process_mux_terminate(u_int, Channel *, Buffer *, Buffer *);
-static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *);
-static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *);
-static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *);
-static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *);
+static void mux_session_confirm(struct ssh *, int, int, void *);
+static void mux_stdio_confirm(struct ssh *, int, int, void *);
+
+static int mux_master_process_hello(struct ssh *, u_int,
+ Channel *, struct sshbuf *, struct sshbuf *);
+static int mux_master_process_new_session(struct ssh *, u_int,
+ Channel *, struct sshbuf *, struct sshbuf *);
+static int mux_master_process_alive_check(struct ssh *, u_int,
+ Channel *, struct sshbuf *, struct sshbuf *);
+static int mux_master_process_terminate(struct ssh *, u_int,
+ Channel *, struct sshbuf *, struct sshbuf *);
+static int mux_master_process_open_fwd(struct ssh *, u_int,
+ Channel *, struct sshbuf *, struct sshbuf *);
+static int mux_master_process_close_fwd(struct ssh *, u_int,
+ Channel *, struct sshbuf *, struct sshbuf *);
+static int mux_master_process_stdio_fwd(struct ssh *, u_int,
+ Channel *, struct sshbuf *, struct sshbuf *);
+static int mux_master_process_stop_listening(struct ssh *, u_int,
+ Channel *, struct sshbuf *, struct sshbuf *);
+static int mux_master_process_proxy(struct ssh *, u_int,
+ Channel *, struct sshbuf *, struct sshbuf *);
static const struct {
u_int type;
- int (*handler)(u_int, Channel *, Buffer *, Buffer *);
+ int (*handler)(struct ssh *, u_int, Channel *,
+ struct sshbuf *, struct sshbuf *);
} mux_master_handlers[] = {
- { MUX_MSG_HELLO, process_mux_master_hello },
- { MUX_C_NEW_SESSION, process_mux_new_session },
- { MUX_C_ALIVE_CHECK, process_mux_alive_check },
- { MUX_C_TERMINATE, process_mux_terminate },
- { MUX_C_OPEN_FWD, process_mux_open_fwd },
- { MUX_C_CLOSE_FWD, process_mux_close_fwd },
- { MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd },
- { MUX_C_STOP_LISTENING, process_mux_stop_listening },
+ { MUX_MSG_HELLO, mux_master_process_hello },
+ { MUX_C_NEW_SESSION, mux_master_process_new_session },
+ { MUX_C_ALIVE_CHECK, mux_master_process_alive_check },
+ { MUX_C_TERMINATE, mux_master_process_terminate },
+ { MUX_C_OPEN_FWD, mux_master_process_open_fwd },
+ { MUX_C_CLOSE_FWD, mux_master_process_close_fwd },
+ { MUX_C_NEW_STDIO_FWD, mux_master_process_stdio_fwd },
+ { MUX_C_STOP_LISTENING, mux_master_process_stop_listening },
+ { MUX_C_PROXY, mux_master_process_proxy },
{ 0, NULL }
};
/* Cleanup callback fired on closure of mux slave _session_ channel */
/* ARGSUSED */
static void
-mux_master_session_cleanup_cb(int cid, void *unused)
+mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused)
{
- Channel *cc, *c = channel_by_id(cid);
+ Channel *cc, *c = channel_by_id(ssh, cid);
debug3("%s: entering for channel %d", __func__, cid);
if (c == NULL)
fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
if (c->ctl_chan != -1) {
- if ((cc = channel_by_id(c->ctl_chan)) == NULL)
+ if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d missing control channel %d",
__func__, c->self, c->ctl_chan);
c->ctl_chan = -1;
- cc->remote_id = -1;
- chan_rcvd_oclose(cc);
+ cc->remote_id = 0;
+ cc->have_remote_id = 0;
+ chan_rcvd_oclose(ssh, cc);
}
- channel_cancel_cleanup(c->self);
+ channel_cancel_cleanup(ssh, c->self);
}
/* Cleanup callback fired on closure of mux slave _control_ channel */
/* ARGSUSED */
static void
-mux_master_control_cleanup_cb(int cid, void *unused)
+mux_master_control_cleanup_cb(struct ssh *ssh, int cid, void *unused)
{
- Channel *sc, *c = channel_by_id(cid);
+ Channel *sc, *c = channel_by_id(ssh, cid);
debug3("%s: entering for channel %d", __func__, cid);
if (c == NULL)
fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
- if (c->remote_id != -1) {
- if ((sc = channel_by_id(c->remote_id)) == NULL)
- fatal("%s: channel %d missing session channel %d",
+ if (c->have_remote_id) {
+ if ((sc = channel_by_id(ssh, c->remote_id)) == NULL)
+ fatal("%s: channel %d missing session channel %u",
__func__, c->self, c->remote_id);
- c->remote_id = -1;
+ c->remote_id = 0;
+ c->have_remote_id = 0;
sc->ctl_chan = -1;
if (sc->type != SSH_CHANNEL_OPEN &&
sc->type != SSH_CHANNEL_OPENING) {
debug2("%s: channel %d: not open", __func__, sc->self);
- chan_mark_dead(sc);
+ chan_mark_dead(ssh, sc);
} else {
if (sc->istate == CHAN_INPUT_OPEN)
- chan_read_failed(sc);
+ chan_read_failed(ssh, sc);
if (sc->ostate == CHAN_OUTPUT_OPEN)
- chan_write_failed(sc);
+ chan_write_failed(ssh, sc);
}
}
- channel_cancel_cleanup(c->self);
+ channel_cancel_cleanup(ssh, c->self);
}
/* Check mux client environment variables before passing them to mux master. */
@@ -249,7 +251,7 @@ env_permitted(char *env)
return 0;
ret = snprintf(name, sizeof(name), "%.*s", (int)(cp - env), env);
if (ret <= 0 || (size_t)ret >= sizeof(name)) {
- error("env_permitted: name '%.100s...' too long", env);
+ error("%s: name '%.100s...' too long", __func__, env);
return 0;
}
@@ -263,10 +265,12 @@ env_permitted(char *env)
/* Mux master protocol message handlers */
static int
-process_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r)
+mux_master_process_hello(struct ssh *ssh, u_int rid,
+ Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
u_int ver;
struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
+ int r;
if (state == NULL)
fatal("%s: channel %d: c->mux_ctx == NULL", __func__, c->self);
@@ -274,63 +278,86 @@ process_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r)
error("%s: HELLO received twice", __func__);
return -1;
}
- if (buffer_get_int_ret(&ver, m) != 0) {
- malf:
- error("%s: malformed message", __func__);
+ if ((r = sshbuf_get_u32(m, &ver)) != 0) {
+ error("%s: malformed message: %s", __func__, ssh_err(r));
return -1;
}
if (ver != SSHMUX_VER) {
- error("Unsupported multiplexing protocol version %d "
- "(expected %d)", ver, SSHMUX_VER);
+ error("%s: unsupported multiplexing protocol version %u "
+ "(expected %u)", __func__, ver, SSHMUX_VER);
return -1;
}
debug2("%s: channel %d slave version %u", __func__, c->self, ver);
/* No extensions are presently defined */
- while (buffer_len(m) > 0) {
- char *name = buffer_get_string_ret(m, NULL);
- char *value = buffer_get_string_ret(m, NULL);
-
- if (name == NULL || value == NULL) {
- free(name);
- free(value);
- goto malf;
+ while (sshbuf_len(m) > 0) {
+ char *name = NULL;
+ size_t value_len = 0;
+
+ if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 ||
+ (r = sshbuf_get_string_direct(m, NULL, &value_len)) != 0) {
+ error("%s: malformed extension: %s",
+ __func__, ssh_err(r));
+ return -1;
}
- debug2("Unrecognised slave extension \"%s\"", name);
+ debug2("%s: Unrecognised extension \"%s\" length %zu",
+ __func__, name, value_len);
free(name);
- free(value);
}
state->hello_rcvd = 1;
return 0;
}
+/* Enqueue a "ok" response to the reply buffer */
+static void
+reply_ok(struct sshbuf *reply, u_int rid)
+{
+ int r;
+
+ if ((r = sshbuf_put_u32(reply, MUX_S_OK)) != 0 ||
+ (r = sshbuf_put_u32(reply, rid)) != 0)
+ fatal("%s: reply: %s", __func__, ssh_err(r));
+}
+
+/* Enqueue an error response to the reply buffer */
+static void
+reply_error(struct sshbuf *reply, u_int type, u_int rid, const char *msg)
+{
+ int r;
+
+ if ((r = sshbuf_put_u32(reply, type)) != 0 ||
+ (r = sshbuf_put_u32(reply, rid)) != 0 ||
+ (r = sshbuf_put_cstring(reply, msg)) != 0)
+ fatal("%s: reply: %s", __func__, ssh_err(r));
+}
+
static int
-process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
+mux_master_process_new_session(struct ssh *ssh, u_int rid,
+ Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
Channel *nc;
struct mux_session_confirm_ctx *cctx;
- char *reserved, *cmd, *cp;
- u_int i, j, len, env_len, escape_char, window, packetmax;
- int new_fd[3];
+ char *cmd, *cp;
+ u_int i, j, env_len, escape_char, window, packetmax;
+ int r, new_fd[3];
/* Reply for SSHMUX_COMMAND_OPEN */
cctx = xcalloc(1, sizeof(*cctx));
cctx->term = NULL;
cctx->rid = rid;
- cmd = reserved = NULL;
+ cmd = NULL;
cctx->env = NULL;
env_len = 0;
- if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
- buffer_get_int_ret(&cctx->want_tty, m) != 0 ||
- buffer_get_int_ret(&cctx->want_x_fwd, m) != 0 ||
- buffer_get_int_ret(&cctx->want_agent_fwd, m) != 0 ||
- buffer_get_int_ret(&cctx->want_subsys, m) != 0 ||
- buffer_get_int_ret(&escape_char, m) != 0 ||
- (cctx->term = buffer_get_string_ret(m, &len)) == NULL ||
- (cmd = buffer_get_string_ret(m, &len)) == NULL) {
+ if ((r = sshbuf_skip_string(m)) != 0 || /* reserved */
+ (r = sshbuf_get_u32(m, &cctx->want_tty)) != 0 ||
+ (r = sshbuf_get_u32(m, &cctx->want_x_fwd)) != 0 ||
+ (r = sshbuf_get_u32(m, &cctx->want_agent_fwd)) != 0 ||
+ (r = sshbuf_get_u32(m, &cctx->want_subsys)) != 0 ||
+ (r = sshbuf_get_u32(m, &escape_char)) != 0 ||
+ (r = sshbuf_get_cstring(m, &cctx->term, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(m, &cmd, NULL)) != 0) {
malf:
free(cmd);
- free(reserved);
for (j = 0; j < env_len; j++)
free(cctx->env[j]);
free(cctx->env);
@@ -339,24 +366,22 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
error("%s: malformed message", __func__);
return -1;
}
- free(reserved);
- reserved = NULL;
- while (buffer_len(m) > 0) {
#define MUX_MAX_ENV_VARS 4096
- if ((cp = buffer_get_string_ret(m, &len)) == NULL)
+ while (sshbuf_len(m) > 0) {
+ if ((r = sshbuf_get_cstring(m, &cp, NULL)) != 0)
goto malf;
if (!env_permitted(cp)) {
free(cp);
continue;
}
- cctx->env = xrealloc(cctx->env, env_len + 2,
+ cctx->env = xreallocarray(cctx->env, env_len + 2,
sizeof(*cctx->env));
cctx->env[env_len++] = cp;
cctx->env[env_len] = NULL;
if (env_len > MUX_MAX_ENV_VARS) {
- error(">%d environment variables received, ignoring "
- "additional", MUX_MAX_ENV_VARS);
+ error("%s: >%d environment variables received, "
+ "ignoring additional", __func__, MUX_MAX_ENV_VARS);
break;
}
}
@@ -366,8 +391,10 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
cctx->want_tty, cctx->want_x_fwd, cctx->want_agent_fwd,
cctx->want_subsys, cctx->term, cmd, env_len);
- buffer_init(&cctx->cmd);
- buffer_append(&cctx->cmd, cmd, strlen(cmd));
+ if ((cctx->cmd = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_put(cctx->cmd, cmd, strlen(cmd))) != 0)
+ fatal("%s: sshbuf_put: %s", __func__, ssh_err(r));
free(cmd);
cmd = NULL;
@@ -382,13 +409,9 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
free(cctx->env[j]);
free(cctx->env);
free(cctx->term);
- buffer_free(&cctx->cmd);
+ sshbuf_free(cctx->cmd);
free(cctx);
-
- /* prepare reply */
- buffer_put_int(r, MUX_S_FAILURE);
- buffer_put_int(r, rid);
- buffer_put_cstring(r,
+ reply_error(reply, MUX_S_FAILURE, rid,
"did not receive file descriptors");
return -1;
}
@@ -398,12 +421,10 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
new_fd[0], new_fd[1], new_fd[2]);
/* XXX support multiple child sessions in future */
- if (c->remote_id != -1) {
+ if (c->have_remote_id) {
debug2("%s: session already open", __func__);
- /* prepare reply */
- buffer_put_int(r, MUX_S_FAILURE);
- buffer_put_int(r, rid);
- buffer_put_cstring(r, "Multiple sessions not supported");
+ reply_error(reply, MUX_S_FAILURE, rid,
+ "Multiple sessions not supported");
cleanup:
close(new_fd[0]);
close(new_fd[1]);
@@ -414,7 +435,7 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
free(cctx->env[i]);
free(cctx->env);
}
- buffer_free(&cctx->cmd);
+ sshbuf_free(cctx->cmd);
free(cctx);
return 0;
}
@@ -423,10 +444,8 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Allow shared connection to %s? ", host)) {
debug2("%s: session refused by user", __func__);
- /* prepare reply */
- buffer_put_int(r, MUX_S_PERMISSION_DENIED);
- buffer_put_int(r, rid);
- buffer_put_cstring(r, "Permission denied");
+ reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
+ "Permission denied");
goto cleanup;
}
}
@@ -450,15 +469,16 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
packetmax >>= 1;
}
- nc = channel_new("session", SSH_CHANNEL_OPENING,
+ nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING,
new_fd[0], new_fd[1], new_fd[2], window, packetmax,
CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
nc->ctl_chan = c->self; /* link session -> control channel */
c->remote_id = nc->self; /* link control -> session channel */
+ c->have_remote_id = 1;
if (cctx->want_tty && escape_char != 0xffffffff) {
- channel_register_filter(nc->self,
+ channel_register_filter(ssh, nc->self,
client_simple_escape_filter, NULL,
client_filter_cleanup,
client_new_escape_filter_ctx((int)escape_char));
@@ -467,30 +487,36 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
debug2("%s: channel_new: %d linked to control channel %d",
__func__, nc->self, nc->ctl_chan);
- channel_send_open(nc->self);
- channel_register_open_confirm(nc->self, mux_session_confirm, cctx);
+ channel_send_open(ssh, nc->self);
+ channel_register_open_confirm(ssh, nc->self, mux_session_confirm, cctx);
c->mux_pause = 1; /* stop handling messages until open_confirm done */
- channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1);
+ channel_register_cleanup(ssh, nc->self,
+ mux_master_session_cleanup_cb, 1);
/* reply is deferred, sent by mux_session_confirm */
return 0;
}
static int
-process_mux_alive_check(u_int rid, Channel *c, Buffer *m, Buffer *r)
+mux_master_process_alive_check(struct ssh *ssh, u_int rid,
+ Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
+ int r;
+
debug2("%s: channel %d: alive check", __func__, c->self);
/* prepare reply */
- buffer_put_int(r, MUX_S_ALIVE);
- buffer_put_int(r, rid);
- buffer_put_int(r, (u_int)getpid());
+ if ((r = sshbuf_put_u32(reply, MUX_S_ALIVE)) != 0 ||
+ (r = sshbuf_put_u32(reply, rid)) != 0 ||
+ (r = sshbuf_put_u32(reply, (u_int)getpid())) != 0)
+ fatal("%s: reply: %s", __func__, ssh_err(r));
return 0;
}
static int
-process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r)
+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);
@@ -499,16 +525,14 @@ process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r)
if (!ask_permission("Terminate shared connection to %s? ",
host)) {
debug2("%s: termination refused by user", __func__);
- buffer_put_int(r, MUX_S_PERMISSION_DENIED);
- buffer_put_int(r, rid);
- buffer_put_cstring(r, "Permission denied");
+ reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
+ "Permission denied");
return 0;
}
}
quit_pending = 1;
- buffer_put_int(r, MUX_S_OK);
- buffer_put_int(r, rid);
+ reply_ok(reply, rid);
/* XXX exit happens too soon - message never makes it to client */
return 0;
}
@@ -579,21 +603,26 @@ compare_forward(struct Forward *a, struct Forward *b)
}
static void
-mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
+mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
{
struct mux_channel_confirm_ctx *fctx = ctxt;
char *failmsg = NULL;
struct Forward *rfwd;
Channel *c;
- Buffer out;
+ struct sshbuf *out;
+ u_int port;
+ int r;
- if ((c = channel_by_id(fctx->cid)) == NULL) {
+ if ((c = channel_by_id(ssh, fctx->cid)) == NULL) {
/* no channel for reply */
error("%s: unknown channel", __func__);
return;
}
- buffer_init(&out);
- if (fctx->fid >= options.num_remote_forwards) {
+ if ((out = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if (fctx->fid >= options.num_remote_forwards ||
+ (options.remote_forwards[fctx->fid].connect_path == NULL &&
+ options.remote_forwards[fctx->fid].connect_host == NULL)) {
xasprintf(&failmsg, "unknown forwarding id %d", fctx->fid);
goto fail;
}
@@ -604,60 +633,83 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
rfwd->connect_host, rfwd->connect_port);
if (type == SSH2_MSG_REQUEST_SUCCESS) {
if (rfwd->listen_port == 0) {
- rfwd->allocated_port = packet_get_int();
- logit("Allocated port %u for mux remote forward"
+ if ((r = sshpkt_get_u32(ssh, &port)) != 0)
+ fatal("%s: packet error: %s",
+ __func__, ssh_err(r));
+ if (port > 65535) {
+ fatal("Invalid allocated port %u for "
+ "mux remote forward to %s:%d", port,
+ rfwd->connect_host, rfwd->connect_port);
+ }
+ rfwd->allocated_port = (int)port;
+ debug("Allocated port %u for mux remote forward"
" to %s:%d", rfwd->allocated_port,
rfwd->connect_host, rfwd->connect_port);
- buffer_put_int(&out, MUX_S_REMOTE_PORT);
- buffer_put_int(&out, fctx->rid);
- buffer_put_int(&out, rfwd->allocated_port);
- channel_update_permitted_opens(rfwd->handle,
+ if ((r = sshbuf_put_u32(out,
+ MUX_S_REMOTE_PORT)) != 0 ||
+ (r = sshbuf_put_u32(out, fctx->rid)) != 0 ||
+ (r = sshbuf_put_u32(out,
+ rfwd->allocated_port)) != 0)
+ fatal("%s: reply: %s", __func__, ssh_err(r));
+ channel_update_permission(ssh, rfwd->handle,
rfwd->allocated_port);
} else {
- buffer_put_int(&out, MUX_S_OK);
- buffer_put_int(&out, fctx->rid);
+ reply_ok(out, fctx->rid);
}
goto out;
} else {
if (rfwd->listen_port == 0)
- channel_update_permitted_opens(rfwd->handle, -1);
+ channel_update_permission(ssh, rfwd->handle, -1);
if (rfwd->listen_path != NULL)
xasprintf(&failmsg, "remote port forwarding failed for "
"listen path %s", rfwd->listen_path);
else
xasprintf(&failmsg, "remote port forwarding failed for "
"listen port %d", rfwd->listen_port);
+
+ debug2("%s: clearing registered forwarding for listen %d, "
+ "connect %s:%d", __func__, rfwd->listen_port,
+ rfwd->connect_path ? rfwd->connect_path :
+ rfwd->connect_host, rfwd->connect_port);
+
+ free(rfwd->listen_host);
+ free(rfwd->listen_path);
+ free(rfwd->connect_host);
+ free(rfwd->connect_path);
+ memset(rfwd, 0, sizeof(*rfwd));
}
fail:
error("%s: %s", __func__, failmsg);
- buffer_put_int(&out, MUX_S_FAILURE);
- buffer_put_int(&out, fctx->rid);
- buffer_put_cstring(&out, failmsg);
+ reply_error(out, MUX_S_FAILURE, fctx->rid, failmsg);
free(failmsg);
out:
- buffer_put_string(&c->output, buffer_ptr(&out), buffer_len(&out));
- buffer_free(&out);
+ if ((r = sshbuf_put_stringb(c->output, out)) != 0)
+ fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
+ sshbuf_free(out);
if (c->mux_pause <= 0)
fatal("%s: mux_pause %d", __func__, c->mux_pause);
c->mux_pause = 0; /* start processing messages again */
}
static int
-process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
+mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
+ Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
struct Forward fwd;
char *fwd_desc = NULL;
char *listen_addr, *connect_addr;
u_int ftype;
u_int lport, cport;
- int i, ret = 0, freefwd = 1;
+ int r, i, ret = 0, freefwd = 1;
+
+ memset(&fwd, 0, sizeof(fwd));
/* XXX - lport/cport check redundant */
- if (buffer_get_int_ret(&ftype, m) != 0 ||
- (listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
- buffer_get_int_ret(&lport, m) != 0 ||
- (connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
- buffer_get_int_ret(&cport, m) != 0 ||
+ if ((r = sshbuf_get_u32(m, &ftype)) != 0 ||
+ (r = sshbuf_get_cstring(m, &listen_addr, NULL)) != 0 ||
+ (r = sshbuf_get_u32(m, &lport)) != 0 ||
+ (r = sshbuf_get_cstring(m, &connect_addr, NULL)) != 0 ||
+ (r = sshbuf_get_u32(m, &cport)) != 0 ||
(lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
error("%s: malformed message", __func__);
@@ -694,9 +746,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
invalid:
free(listen_addr);
free(connect_addr);
- buffer_put_int(r, MUX_S_FAILURE);
- buffer_put_int(r, rid);
- buffer_put_cstring(r, "Invalid forwarding request");
+ reply_error(reply, MUX_S_FAILURE, rid,
+ "Invalid forwarding request");
return 0;
}
if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) {
@@ -709,13 +760,16 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
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)) {
+ if ((fwd.connect_port != PORT_STREAMLOCAL &&
+ fwd.connect_port >= 65536) ||
+ (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE &&
+ fwd.connect_port == 0)) {
logit("%s: invalid connect port %u", __func__,
fwd.connect_port);
goto invalid;
}
- if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) {
+ if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL &&
+ fwd.connect_path == NULL) {
logit("%s: missing connect host", __func__);
goto invalid;
}
@@ -730,26 +784,25 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
exists:
debug2("%s: found existing forwarding",
__func__);
- buffer_put_int(r, MUX_S_OK);
- buffer_put_int(r, rid);
+ reply_ok(reply, rid);
goto out;
}
}
break;
case MUX_FWD_REMOTE:
for (i = 0; i < options.num_remote_forwards; i++) {
- if (compare_forward(&fwd,
- options.remote_forwards + i)) {
- if (fwd.listen_port != 0)
- goto exists;
- debug2("%s: found allocated port",
- __func__);
- buffer_put_int(r, MUX_S_REMOTE_PORT);
- buffer_put_int(r, rid);
- buffer_put_int(r,
- options.remote_forwards[i].allocated_port);
- goto out;
- }
+ if (!compare_forward(&fwd, options.remote_forwards + i))
+ continue;
+ if (fwd.listen_port != 0)
+ goto exists;
+ debug2("%s: found allocated port", __func__);
+ if ((r = sshbuf_put_u32(reply,
+ MUX_S_REMOTE_PORT)) != 0 ||
+ (r = sshbuf_put_u32(reply, rid)) != 0 ||
+ (r = sshbuf_put_u32(reply,
+ options.remote_forwards[i].allocated_port)) != 0)
+ fatal("%s: reply: %s", __func__, ssh_err(r));
+ goto out;
}
break;
}
@@ -758,21 +811,19 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Open %s on %s?", fwd_desc, host)) {
debug2("%s: forwarding refused by user", __func__);
- buffer_put_int(r, MUX_S_PERMISSION_DENIED);
- buffer_put_int(r, rid);
- buffer_put_cstring(r, "Permission denied");
+ reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
+ "Permission denied");
goto out;
}
}
if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
- if (!channel_setup_local_fwd_listener(&fwd,
+ if (!channel_setup_local_fwd_listener(ssh, &fwd,
&options.fwd_opts)) {
fail:
- logit("slave-requested %s failed", fwd_desc);
- buffer_put_int(r, MUX_S_FAILURE);
- buffer_put_int(r, rid);
- buffer_put_cstring(r, "Port forwarding failed");
+ logit("%s: requested %s failed", __func__, fwd_desc);
+ reply_error(reply, MUX_S_FAILURE, rid,
+ "Port forwarding failed");
goto out;
}
add_local_forward(&options, &fwd);
@@ -780,7 +831,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
} else {
struct mux_channel_confirm_ctx *fctx;
- fwd.handle = channel_request_remote_forwarding(&fwd);
+ fwd.handle = channel_request_remote_forwarding(ssh, &fwd);
if (fwd.handle < 0)
goto fail;
add_remote_forward(&options, &fwd);
@@ -795,8 +846,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
/* delayed reply in mux_confirm_remote_forward */
goto out;
}
- buffer_put_int(r, MUX_S_OK);
- buffer_put_int(r, rid);
+ reply_ok(reply, rid);
out:
free(fwd_desc);
if (freefwd) {
@@ -809,21 +859,24 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
}
static int
-process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
+mux_master_process_close_fwd(struct ssh *ssh, u_int rid,
+ Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
struct Forward fwd, *found_fwd;
char *fwd_desc = NULL;
const char *error_reason = NULL;
char *listen_addr = NULL, *connect_addr = NULL;
u_int ftype;
- int i, ret = 0;
+ int r, i, ret = 0;
u_int lport, cport;
- if (buffer_get_int_ret(&ftype, m) != 0 ||
- (listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
- buffer_get_int_ret(&lport, m) != 0 ||
- (connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
- buffer_get_int_ret(&cport, m) != 0 ||
+ memset(&fwd, 0, sizeof(fwd));
+
+ if ((r = sshbuf_get_u32(m, &ftype)) != 0 ||
+ (r = sshbuf_get_cstring(m, &listen_addr, NULL)) != 0 ||
+ (r = sshbuf_get_u32(m, &lport)) != 0 ||
+ (r = sshbuf_get_cstring(m, &connect_addr, NULL)) != 0 ||
+ (r = sshbuf_get_u32(m, &cport)) != 0 ||
(lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
error("%s: malformed message", __func__);
@@ -888,19 +941,19 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
* However, for dynamic allocated listen ports we need
* to use the actual listen port.
*/
- if (channel_request_rforward_cancel(found_fwd) == -1)
+ if (channel_request_rforward_cancel(ssh, found_fwd) == -1)
error_reason = "port not in permitted opens";
} else { /* local and dynamic forwards */
/* Ditto */
- if (channel_cancel_lport_listener(&fwd, fwd.connect_port,
+ if (channel_cancel_lport_listener(ssh, &fwd, fwd.connect_port,
&options.fwd_opts) == -1)
error_reason = "port not found";
}
- if (error_reason == NULL) {
- buffer_put_int(r, MUX_S_OK);
- buffer_put_int(r, rid);
-
+ if (error_reason != NULL)
+ reply_error(reply, MUX_S_FAILURE, rid, error_reason);
+ else {
+ reply_ok(reply, rid);
free(found_fwd->listen_host);
free(found_fwd->listen_path);
free(found_fwd->connect_host);
@@ -908,10 +961,6 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
found_fwd->listen_host = found_fwd->connect_host = NULL;
found_fwd->listen_path = found_fwd->connect_path = NULL;
found_fwd->listen_port = found_fwd->connect_port = 0;
- } else {
- buffer_put_int(r, MUX_S_FAILURE);
- buffer_put_int(r, rid);
- buffer_put_cstring(r, error_reason);
}
out:
free(fwd_desc);
@@ -922,24 +971,22 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
}
static int
-process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
+mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid,
+ Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
Channel *nc;
- char *reserved, *chost;
+ char *chost = NULL;
u_int cport, i, j;
- int new_fd[2];
+ int r, new_fd[2];
struct mux_stdio_confirm_ctx *cctx;
- chost = reserved = NULL;
- if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
- (chost = buffer_get_string_ret(m, NULL)) == NULL ||
- buffer_get_int_ret(&cport, m) != 0) {
- free(reserved);
+ if ((r = sshbuf_skip_string(m)) != 0 || /* reserved */
+ (r = sshbuf_get_cstring(m, &chost, NULL)) != 0 ||
+ (r = sshbuf_get_u32(m, &cport)) != 0) {
free(chost);
error("%s: malformed message", __func__);
return -1;
}
- free(reserved);
debug2("%s: channel %d: request stdio fwd to %s:%u",
__func__, c->self, chost, cport);
@@ -954,9 +1001,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
free(chost);
/* prepare reply */
- buffer_put_int(r, MUX_S_FAILURE);
- buffer_put_int(r, rid);
- buffer_put_cstring(r,
+ reply_error(reply, MUX_S_FAILURE, rid,
"did not receive file descriptors");
return -1;
}
@@ -966,12 +1011,10 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
new_fd[0], new_fd[1]);
/* XXX support multiple child sessions in future */
- if (c->remote_id != -1) {
+ if (c->have_remote_id) {
debug2("%s: session already open", __func__);
- /* prepare reply */
- buffer_put_int(r, MUX_S_FAILURE);
- buffer_put_int(r, rid);
- buffer_put_cstring(r, "Multiple sessions not supported");
+ reply_error(reply, MUX_S_FAILURE, rid,
+ "Multiple sessions not supported");
cleanup:
close(new_fd[0]);
close(new_fd[1]);
@@ -984,10 +1027,8 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
if (!ask_permission("Allow forward to %s:%u? ",
chost, cport)) {
debug2("%s: stdio fwd refused by user", __func__);
- /* prepare reply */
- buffer_put_int(r, MUX_S_PERMISSION_DENIED);
- buffer_put_int(r, rid);
- buffer_put_cstring(r, "Permission denied");
+ reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
+ "Permission denied");
goto cleanup;
}
}
@@ -998,19 +1039,22 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
if (!isatty(new_fd[1]))
set_nonblock(new_fd[1]);
- nc = channel_connect_stdio_fwd(chost, cport, new_fd[0], new_fd[1]);
+ nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1]);
+ free(chost);
nc->ctl_chan = c->self; /* link session -> control channel */
c->remote_id = nc->self; /* link control -> session channel */
+ c->have_remote_id = 1;
debug2("%s: channel_new: %d linked to control channel %d",
__func__, nc->self, nc->ctl_chan);
- channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1);
+ channel_register_cleanup(ssh, nc->self,
+ mux_master_session_cleanup_cb, 1);
cctx = xcalloc(1, sizeof(*cctx));
cctx->rid = rid;
- channel_register_open_confirm(nc->self, mux_stdio_confirm, cctx);
+ channel_register_open_confirm(ssh, nc->self, mux_stdio_confirm, cctx);
c->mux_pause = 1; /* stop handling messages until open_confirm done */
/* reply is deferred, sent by mux_session_confirm */
@@ -1019,41 +1063,43 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
/* Callback on open confirmation in mux master for a mux stdio fwd session. */
static void
-mux_stdio_confirm(int id, int success, void *arg)
+mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
{
struct mux_stdio_confirm_ctx *cctx = arg;
Channel *c, *cc;
- Buffer reply;
+ struct sshbuf *reply;
+ int r;
if (cctx == NULL)
fatal("%s: cctx == NULL", __func__);
- if ((c = channel_by_id(id)) == NULL)
+ if ((c = channel_by_id(ssh, id)) == NULL)
fatal("%s: no channel for id %d", __func__, id);
- if ((cc = channel_by_id(c->ctl_chan)) == NULL)
+ if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d lacks control channel %d", __func__,
id, c->ctl_chan);
+ if ((reply = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
if (!success) {
debug3("%s: sending failure reply", __func__);
+ reply_error(reply, MUX_S_FAILURE, cctx->rid,
+ "Session open refused by peer");
/* prepare reply */
- buffer_init(&reply);
- buffer_put_int(&reply, MUX_S_FAILURE);
- buffer_put_int(&reply, cctx->rid);
- buffer_put_cstring(&reply, "Session open refused by peer");
goto done;
}
debug3("%s: sending success reply", __func__);
/* prepare reply */
- buffer_init(&reply);
- buffer_put_int(&reply, MUX_S_SESSION_OPENED);
- buffer_put_int(&reply, cctx->rid);
- buffer_put_int(&reply, c->self);
+ if ((r = sshbuf_put_u32(reply, MUX_S_SESSION_OPENED)) != 0 ||
+ (r = sshbuf_put_u32(reply, cctx->rid)) != 0 ||
+ (r = sshbuf_put_u32(reply, c->self)) != 0)
+ fatal("%s: reply: %s", __func__, ssh_err(r));
done:
/* Send reply */
- buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply));
- buffer_free(&reply);
+ if ((r = sshbuf_put_stringb(cc->output, reply)) != 0)
+ fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
+ sshbuf_free(reply);
if (cc->mux_pause <= 0)
fatal("%s: mux_pause %d", __func__, cc->mux_pause);
@@ -1063,7 +1109,8 @@ mux_stdio_confirm(int id, int success, void *arg)
}
static int
-process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
+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);
@@ -1072,15 +1119,14 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
if (!ask_permission("Disable further multiplexing on shared "
"connection to %s? ", host)) {
debug2("%s: stop listen refused by user", __func__);
- buffer_put_int(r, MUX_S_PERMISSION_DENIED);
- buffer_put_int(r, rid);
- buffer_put_cstring(r, "Permission denied");
+ reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
+ "Permission denied");
return 0;
}
}
if (mux_listener_channel != NULL) {
- channel_free(mux_listener_channel);
+ channel_free(ssh, mux_listener_channel);
client_stop_mux();
free(options.control_path);
options.control_path = NULL;
@@ -1088,57 +1134,69 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
muxserver_sock = -1;
}
- /* prepare reply */
- buffer_put_int(r, MUX_S_OK);
- buffer_put_int(r, rid);
+ reply_ok(reply, rid);
+ return 0;
+}
+
+static int
+mux_master_process_proxy(struct ssh *ssh, u_int rid,
+ Channel *c, struct sshbuf *m, struct sshbuf *reply)
+{
+ int r;
+
+ debug("%s: channel %d: proxy request", __func__, c->self);
+
+ c->mux_rcb = channel_proxy_downstream;
+ if ((r = sshbuf_put_u32(reply, MUX_S_PROXY)) != 0 ||
+ (r = sshbuf_put_u32(reply, rid)) != 0)
+ fatal("%s: reply: %s", __func__, ssh_err(r));
return 0;
}
/* Channel callbacks fired on read/write from mux slave fd */
static int
-mux_master_read_cb(Channel *c)
+mux_master_read_cb(struct ssh *ssh, Channel *c)
{
struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
- Buffer in, out;
- const u_char *ptr;
- u_int type, rid, have, i;
- int ret = -1;
+ struct sshbuf *in = NULL, *out = NULL;
+ u_int type, rid, i;
+ int r, ret = -1;
+
+ if ((out = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
/* Setup ctx and */
if (c->mux_ctx == NULL) {
state = xcalloc(1, sizeof(*state));
c->mux_ctx = state;
- channel_register_cleanup(c->self,
+ channel_register_cleanup(ssh, c->self,
mux_master_control_cleanup_cb, 0);
/* Send hello */
- buffer_init(&out);
- buffer_put_int(&out, MUX_MSG_HELLO);
- buffer_put_int(&out, SSHMUX_VER);
+ if ((r = sshbuf_put_u32(out, MUX_MSG_HELLO)) != 0 ||
+ (r = sshbuf_put_u32(out, SSHMUX_VER)) != 0)
+ fatal("%s: reply: %s", __func__, ssh_err(r));
/* no extensions */
- buffer_put_string(&c->output, buffer_ptr(&out),
- buffer_len(&out));
- buffer_free(&out);
+ 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);
- return 0;
+ ret = 0;
+ goto out;
}
- buffer_init(&in);
- buffer_init(&out);
-
/* Channel code ensures that we receive whole packets */
- if ((ptr = buffer_get_string_ptr_ret(&c->input, &have)) == NULL) {
+ if ((r = sshbuf_froms(c->input, &in)) != 0) {
malf:
error("%s: malformed message", __func__);
goto out;
}
- buffer_append(&in, ptr, have);
- if (buffer_get_int_ret(&type, &in) != 0)
+ if ((r = sshbuf_get_u32(in, &type)) != 0)
goto malf;
- debug3("%s: channel %d packet type 0x%08x len %u",
- __func__, c->self, type, buffer_len(&in));
+ debug3("%s: channel %d packet type 0x%08x len %zu",
+ __func__, c->self, type, sshbuf_len(in));
if (type == MUX_MSG_HELLO)
rid = 0;
@@ -1148,81 +1206,85 @@ mux_master_read_cb(Channel *c)
"received 0x%08x", __func__, MUX_MSG_HELLO, type);
goto out;
}
- if (buffer_get_int_ret(&rid, &in) != 0)
+ if ((r = sshbuf_get_u32(in, &rid)) != 0)
goto malf;
}
for (i = 0; mux_master_handlers[i].handler != NULL; i++) {
if (type == mux_master_handlers[i].type) {
- ret = mux_master_handlers[i].handler(rid, c, &in, &out);
+ ret = mux_master_handlers[i].handler(ssh, rid,
+ c, in, out);
break;
}
}
if (mux_master_handlers[i].handler == NULL) {
error("%s: unsupported mux message 0x%08x", __func__, type);
- buffer_put_int(&out, MUX_S_FAILURE);
- buffer_put_int(&out, rid);
- buffer_put_cstring(&out, "unsupported request");
+ reply_error(out, MUX_S_FAILURE, rid, "unsupported request");
ret = 0;
}
/* Enqueue reply packet */
- if (buffer_len(&out) != 0) {
- buffer_put_string(&c->output, buffer_ptr(&out),
- buffer_len(&out));
+ if (sshbuf_len(out) != 0) {
+ if ((r = sshbuf_put_stringb(c->output, out)) != 0)
+ fatal("%s: sshbuf_put_stringb: %s",
+ __func__, ssh_err(r));
}
out:
- buffer_free(&in);
- buffer_free(&out);
+ sshbuf_free(in);
+ sshbuf_free(out);
return ret;
}
void
-mux_exit_message(Channel *c, int exitval)
+mux_exit_message(struct ssh *ssh, Channel *c, int exitval)
{
- Buffer m;
+ struct sshbuf *m;
Channel *mux_chan;
+ int r;
debug3("%s: channel %d: exit message, exitval %d", __func__, c->self,
exitval);
- if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL)
+ if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d missing mux channel %d",
__func__, c->self, c->ctl_chan);
/* Append exit message packet to control socket output queue */
- buffer_init(&m);
- buffer_put_int(&m, MUX_S_EXIT_MESSAGE);
- buffer_put_int(&m, c->self);
- buffer_put_int(&m, exitval);
-
- buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m));
- buffer_free(&m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_put_u32(m, MUX_S_EXIT_MESSAGE)) != 0 ||
+ (r = sshbuf_put_u32(m, c->self)) != 0 ||
+ (r = sshbuf_put_u32(m, exitval)) != 0 ||
+ (r = sshbuf_put_stringb(mux_chan->output, m)) != 0)
+ fatal("%s: reply: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
}
void
-mux_tty_alloc_failed(Channel *c)
+mux_tty_alloc_failed(struct ssh *ssh, Channel *c)
{
- Buffer m;
+ struct sshbuf *m;
Channel *mux_chan;
+ int r;
debug3("%s: channel %d: TTY alloc failed", __func__, c->self);
- if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL)
+ if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d missing mux channel %d",
__func__, c->self, c->ctl_chan);
/* Append exit message packet to control socket output queue */
- buffer_init(&m);
- buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL);
- buffer_put_int(&m, c->self);
-
- buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m));
- buffer_free(&m);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_put_u32(m, MUX_S_TTY_ALLOC_FAIL)) != 0 ||
+ (r = sshbuf_put_u32(m, c->self)) != 0 ||
+ (r = sshbuf_put_stringb(mux_chan->output, m)) != 0)
+ fatal("%s: reply: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
}
/* Prepare a mux master to listen on a Unix domain socket. */
void
-muxserver_listen(void)
+muxserver_listen(struct ssh *ssh)
{
mode_t old_umask;
char *orig_control_path = options.control_path;
@@ -1280,7 +1342,7 @@ muxserver_listen(void)
/* 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("%s: link mux listener %s => %s: %s", __func__,
options.control_path, orig_control_path,
strerror(errno));
}
@@ -1295,7 +1357,7 @@ muxserver_listen(void)
set_nonblock(muxserver_sock);
- mux_listener_channel = channel_new("mux listener",
+ mux_listener_channel = channel_new(ssh, "mux listener",
SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, options.control_path, 1);
@@ -1306,29 +1368,28 @@ muxserver_listen(void)
/* Callback on open confirmation in mux master for a mux client session. */
static void
-mux_session_confirm(int id, int success, void *arg)
+mux_session_confirm(struct ssh *ssh, int id, int success, void *arg)
{
struct mux_session_confirm_ctx *cctx = arg;
const char *display;
Channel *c, *cc;
- int i;
- Buffer reply;
+ int i, r;
+ struct sshbuf *reply;
if (cctx == NULL)
fatal("%s: cctx == NULL", __func__);
- if ((c = channel_by_id(id)) == NULL)
+ if ((c = channel_by_id(ssh, id)) == NULL)
fatal("%s: no channel for id %d", __func__, id);
- if ((cc = channel_by_id(c->ctl_chan)) == NULL)
+ if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d lacks control channel %d", __func__,
id, c->ctl_chan);
+ if ((reply = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
if (!success) {
debug3("%s: sending failure reply", __func__);
- /* prepare reply */
- buffer_init(&reply);
- buffer_put_int(&reply, MUX_S_FAILURE);
- buffer_put_int(&reply, cctx->rid);
- buffer_put_cstring(&reply, "Session open refused by peer");
+ reply_error(reply, MUX_S_FAILURE, cctx->rid,
+ "Session open refused by peer");
goto done;
}
@@ -1337,44 +1398,48 @@ mux_session_confirm(int id, int success, void *arg)
char *proto, *data;
/* Get reasonable local authentication information. */
- client_x11_get_proto(display, options.xauth_location,
+ if (client_x11_get_proto(ssh, display, options.xauth_location,
options.forward_x11_trusted, options.forward_x11_timeout,
- &proto, &data);
- /* Request forwarding with authentication spoofing. */
- debug("Requesting X11 forwarding with authentication "
- "spoofing.");
- x11_request_forwarding_with_spoofing(id, display, proto,
- data, 1);
- client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN);
- /* XXX exit_on_forward_failure */
+ &proto, &data) == 0) {
+ /* Request forwarding with authentication spoofing. */
+ debug("Requesting X11 forwarding with authentication "
+ "spoofing.");
+ x11_request_forwarding_with_spoofing(ssh, id,
+ display, proto, data, 1);
+ /* XXX exit_on_forward_failure */
+ client_expect_confirm(ssh, id, "X11 forwarding",
+ CONFIRM_WARN);
+ }
}
if (cctx->want_agent_fwd && options.forward_agent) {
debug("Requesting authentication agent forwarding.");
- channel_request_start(id, "auth-agent-req@openssh.com", 0);
- packet_send();
+ 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));
}
- client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
- cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env);
+ client_session2_setup(ssh, id, cctx->want_tty, cctx->want_subsys,
+ cctx->term, &cctx->tio, c->rfd, cctx->cmd, cctx->env);
debug3("%s: sending success reply", __func__);
/* prepare reply */
- buffer_init(&reply);
- buffer_put_int(&reply, MUX_S_SESSION_OPENED);
- buffer_put_int(&reply, cctx->rid);
- buffer_put_int(&reply, c->self);
+ if ((r = sshbuf_put_u32(reply, MUX_S_SESSION_OPENED)) != 0 ||
+ (r = sshbuf_put_u32(reply, cctx->rid)) != 0 ||
+ (r = sshbuf_put_u32(reply, c->self)) != 0)
+ fatal("%s: reply: %s", __func__, ssh_err(r));
done:
/* Send reply */
- buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply));
- buffer_free(&reply);
+ if ((r = sshbuf_put_stringb(cc->output, reply)) != 0)
+ fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
+ sshbuf_free(reply);
if (cc->mux_pause <= 0)
fatal("%s: mux_pause %d", __func__, cc->mux_pause);
cc->mux_pause = 0; /* start processing messages again */
c->open_confirm_ctx = NULL;
- buffer_free(&cctx->cmd);
+ sshbuf_free(cctx->cmd);
free(cctx->term);
if (cctx->env != NULL) {
for (i = 0; cctx->env[i] != NULL; i++)
@@ -1409,23 +1474,25 @@ control_client_sigrelay(int signo)
}
static int
-mux_client_read(int fd, Buffer *b, u_int need)
+mux_client_read(int fd, struct sshbuf *b, size_t need)
{
- u_int have;
+ size_t have;
ssize_t len;
u_char *p;
struct pollfd pfd;
+ int r;
pfd.fd = fd;
pfd.events = POLLIN;
- p = buffer_append_space(b, need);
+ if ((r = sshbuf_reserve(b, need, &p)) != 0)
+ fatal("%s: reserve: %s", __func__, ssh_err(r));
for (have = 0; have < need; ) {
if (muxclient_terminate) {
errno = EINTR;
return -1;
}
len = read(fd, p + have, need - have);
- if (len < 0) {
+ if (len == -1) {
switch (errno) {
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
case EWOULDBLOCK:
@@ -1443,36 +1510,38 @@ mux_client_read(int fd, Buffer *b, u_int need)
errno = EPIPE;
return -1;
}
- have += (u_int)len;
+ have += (size_t)len;
}
return 0;
}
static int
-mux_client_write_packet(int fd, Buffer *m)
+mux_client_write_packet(int fd, struct sshbuf *m)
{
- Buffer queue;
+ struct sshbuf *queue;
u_int have, need;
- int oerrno, len;
- u_char *ptr;
+ int r, oerrno, len;
+ const u_char *ptr;
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLOUT;
- buffer_init(&queue);
- buffer_put_string(&queue, buffer_ptr(m), buffer_len(m));
+ if ((queue = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_put_stringb(queue, m)) != 0)
+ fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
- need = buffer_len(&queue);
- ptr = buffer_ptr(&queue);
+ need = sshbuf_len(queue);
+ ptr = sshbuf_ptr(queue);
for (have = 0; have < need; ) {
if (muxclient_terminate) {
- buffer_free(&queue);
+ sshbuf_free(queue);
errno = EINTR;
return -1;
}
len = write(fd, ptr + have, need - have);
- if (len < 0) {
+ if (len == -1) {
switch (errno) {
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
case EWOULDBLOCK:
@@ -1484,132 +1553,160 @@ mux_client_write_packet(int fd, Buffer *m)
continue;
default:
oerrno = errno;
- buffer_free(&queue);
+ sshbuf_free(queue);
errno = oerrno;
return -1;
}
}
if (len == 0) {
- buffer_free(&queue);
+ sshbuf_free(queue);
errno = EPIPE;
return -1;
}
have += (u_int)len;
}
- buffer_free(&queue);
+ sshbuf_free(queue);
return 0;
}
static int
-mux_client_read_packet(int fd, Buffer *m)
+mux_client_read_packet(int fd, struct sshbuf *m)
{
- Buffer queue;
- u_int need, have;
+ struct sshbuf *queue;
+ size_t need, have;
const u_char *ptr;
- int oerrno;
+ int r, oerrno;
- buffer_init(&queue);
- if (mux_client_read(fd, &queue, 4) != 0) {
+ if ((queue = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if (mux_client_read(fd, queue, 4) != 0) {
if ((oerrno = errno) == EPIPE)
debug3("%s: read header failed: %s", __func__,
strerror(errno));
- buffer_free(&queue);
+ sshbuf_free(queue);
errno = oerrno;
return -1;
}
- need = get_u32(buffer_ptr(&queue));
- if (mux_client_read(fd, &queue, need) != 0) {
+ 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));
- buffer_free(&queue);
+ sshbuf_free(queue);
errno = oerrno;
return -1;
}
- ptr = buffer_get_string_ptr(&queue, &have);
- buffer_append(m, ptr, have);
- buffer_free(&queue);
+ if ((r = sshbuf_get_string_direct(queue, &ptr, &have)) != 0 ||
+ (r = sshbuf_put(m, ptr, have)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ sshbuf_free(queue);
return 0;
}
static int
mux_client_hello_exchange(int fd)
{
- Buffer m;
+ struct sshbuf *m;
u_int type, ver;
+ int r, ret = -1;
- buffer_init(&m);
- buffer_put_int(&m, MUX_MSG_HELLO);
- buffer_put_int(&m, SSHMUX_VER);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_put_u32(m, MUX_MSG_HELLO)) != 0 ||
+ (r = sshbuf_put_u32(m, SSHMUX_VER)) != 0)
+ fatal("%s: hello: %s", __func__, ssh_err(r));
/* no extensions */
- if (mux_client_write_packet(fd, &m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ if (mux_client_write_packet(fd, m) != 0) {
+ debug("%s: write packet: %s", __func__, strerror(errno));
+ goto out;
+ }
- buffer_clear(&m);
+ sshbuf_reset(m);
/* Read their HELLO */
- if (mux_client_read_packet(fd, &m) != 0) {
- buffer_free(&m);
- return -1;
+ if (mux_client_read_packet(fd, m) != 0) {
+ debug("%s: read packet failed", __func__);
+ goto out;
}
- type = buffer_get_int(&m);
- if (type != MUX_MSG_HELLO)
- fatal("%s: expected HELLO (%u) received %u",
+ if ((r = sshbuf_get_u32(m, &type)) != 0)
+ fatal("%s: decode type: %s", __func__, ssh_err(r));
+ if (type != MUX_MSG_HELLO) {
+ error("%s: expected HELLO (%u) received %u",
__func__, MUX_MSG_HELLO, type);
- ver = buffer_get_int(&m);
- if (ver != SSHMUX_VER)
- fatal("Unsupported multiplexing protocol version %d "
+ goto out;
+ }
+ if ((r = sshbuf_get_u32(m, &ver)) != 0)
+ fatal("%s: decode version: %s", __func__, ssh_err(r));
+ if (ver != SSHMUX_VER) {
+ error("Unsupported multiplexing protocol version %d "
"(expected %d)", ver, SSHMUX_VER);
+ goto out;
+ }
debug2("%s: master version %u", __func__, ver);
/* No extensions are presently defined */
- while (buffer_len(&m) > 0) {
- char *name = buffer_get_string(&m, NULL);
- char *value = buffer_get_string(&m, NULL);
+ while (sshbuf_len(m) > 0) {
+ char *name = NULL;
+ if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 ||
+ (r = sshbuf_skip_string(m)) != 0) { /* value */
+ error("%s: malformed extension: %s",
+ __func__, ssh_err(r));
+ goto out;
+ }
debug2("Unrecognised master extension \"%s\"", name);
free(name);
- free(value);
}
- buffer_free(&m);
- return 0;
+ /* success */
+ ret = 0;
+ out:
+ sshbuf_free(m);
+ return ret;
}
static u_int
mux_client_request_alive(int fd)
{
- Buffer m;
+ struct sshbuf *m;
char *e;
u_int pid, type, rid;
+ int r;
debug3("%s: entering", __func__);
- buffer_init(&m);
- buffer_put_int(&m, MUX_C_ALIVE_CHECK);
- buffer_put_int(&m, muxclient_request_id);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_put_u32(m, MUX_C_ALIVE_CHECK)) != 0 ||
+ (r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
+ fatal("%s: request: %s", __func__, ssh_err(r));
- if (mux_client_write_packet(fd, &m) != 0)
+ if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
- buffer_clear(&m);
+ sshbuf_reset(m);
/* Read their reply */
- if (mux_client_read_packet(fd, &m) != 0) {
- buffer_free(&m);
+ if (mux_client_read_packet(fd, m) != 0) {
+ sshbuf_free(m);
return 0;
}
- type = buffer_get_int(&m);
+ if ((r = sshbuf_get_u32(m, &type)) != 0)
+ fatal("%s: decode type: %s", __func__, ssh_err(r));
if (type != MUX_S_ALIVE) {
- e = buffer_get_string(&m, NULL);
+ if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
+ fatal("%s: decode error: %s", __func__, ssh_err(r));
fatal("%s: master returned error: %s", __func__, e);
}
- if ((rid = buffer_get_int(&m)) != muxclient_request_id)
+ if ((r = sshbuf_get_u32(m, &rid)) != 0)
+ fatal("%s: decode remote ID: %s", __func__, ssh_err(r));
+ if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
- pid = buffer_get_int(&m);
- buffer_free(&m);
+ if ((r = sshbuf_get_u32(m, &pid)) != 0)
+ fatal("%s: decode PID: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
debug3("%s: done pid = %u", __func__, pid);
@@ -1621,129 +1718,152 @@ mux_client_request_alive(int fd)
static void
mux_client_request_terminate(int fd)
{
- Buffer m;
+ struct sshbuf *m;
char *e;
u_int type, rid;
+ int r;
debug3("%s: entering", __func__);
- buffer_init(&m);
- buffer_put_int(&m, MUX_C_TERMINATE);
- buffer_put_int(&m, muxclient_request_id);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_put_u32(m, MUX_C_TERMINATE)) != 0 ||
+ (r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
+ fatal("%s: request: %s", __func__, ssh_err(r));
- if (mux_client_write_packet(fd, &m) != 0)
+ if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
- buffer_clear(&m);
+ sshbuf_reset(m);
/* Read their reply */
- if (mux_client_read_packet(fd, &m) != 0) {
+ if (mux_client_read_packet(fd, m) != 0) {
/* Remote end exited already */
if (errno == EPIPE) {
- buffer_free(&m);
+ sshbuf_free(m);
return;
}
fatal("%s: read from master failed: %s",
__func__, strerror(errno));
}
- type = buffer_get_int(&m);
- if ((rid = buffer_get_int(&m)) != muxclient_request_id)
+ if ((r = sshbuf_get_u32(m, &type)) != 0 ||
+ (r = sshbuf_get_u32(m, &rid)) != 0)
+ fatal("%s: decode: %s", __func__, ssh_err(r));
+ if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
switch (type) {
case MUX_S_OK:
break;
case MUX_S_PERMISSION_DENIED:
- e = buffer_get_string(&m, NULL);
+ if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
+ fatal("%s: decode error: %s", __func__, ssh_err(r));
fatal("Master refused termination request: %s", e);
case MUX_S_FAILURE:
- e = buffer_get_string(&m, NULL);
+ if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
+ fatal("%s: decode error: %s", __func__, ssh_err(r));
fatal("%s: termination request failed: %s", __func__, e);
default:
fatal("%s: unexpected response from master 0x%08x",
__func__, type);
}
- buffer_free(&m);
+ sshbuf_free(m);
muxclient_request_id++;
}
static int
mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
{
- Buffer m;
+ struct sshbuf *m;
char *e, *fwd_desc;
+ const char *lhost, *chost;
u_int type, rid;
+ int r;
fwd_desc = format_forward(ftype, fwd);
debug("Requesting %s %s",
cancel_flag ? "cancellation of" : "forwarding of", fwd_desc);
free(fwd_desc);
- buffer_init(&m);
- buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD);
- buffer_put_int(&m, muxclient_request_id);
- buffer_put_int(&m, ftype);
- if (fwd->listen_path != NULL) {
- buffer_put_cstring(&m, fwd->listen_path);
- } else {
- buffer_put_cstring(&m,
- fwd->listen_host == NULL ? "" :
- (*fwd->listen_host == '\0' ? "*" : fwd->listen_host));
- }
- buffer_put_int(&m, fwd->listen_port);
- if (fwd->connect_path != NULL) {
- buffer_put_cstring(&m, fwd->connect_path);
- } else {
- buffer_put_cstring(&m,
- fwd->connect_host == NULL ? "" : fwd->connect_host);
- }
- buffer_put_int(&m, fwd->connect_port);
+ type = cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD;
+ if (fwd->listen_path != NULL)
+ lhost = fwd->listen_path;
+ else if (fwd->listen_host == NULL)
+ lhost = "";
+ else if (*fwd->listen_host == '\0')
+ lhost = "*";
+ else
+ lhost = fwd->listen_host;
- if (mux_client_write_packet(fd, &m) != 0)
+ if (fwd->connect_path != NULL)
+ chost = fwd->connect_path;
+ else if (fwd->connect_host == NULL)
+ chost = "";
+ else
+ chost = fwd->connect_host;
+
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_put_u32(m, type)) != 0 ||
+ (r = sshbuf_put_u32(m, muxclient_request_id)) != 0 ||
+ (r = sshbuf_put_u32(m, ftype)) != 0 ||
+ (r = sshbuf_put_cstring(m, lhost)) != 0 ||
+ (r = sshbuf_put_u32(m, fwd->listen_port)) != 0 ||
+ (r = sshbuf_put_cstring(m, chost)) != 0 ||
+ (r = sshbuf_put_u32(m, fwd->connect_port)) != 0)
+ fatal("%s: request: %s", __func__, ssh_err(r));
+
+ if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
- buffer_clear(&m);
+ sshbuf_reset(m);
/* Read their reply */
- if (mux_client_read_packet(fd, &m) != 0) {
- buffer_free(&m);
+ if (mux_client_read_packet(fd, m) != 0) {
+ sshbuf_free(m);
return -1;
}
- type = buffer_get_int(&m);
- if ((rid = buffer_get_int(&m)) != muxclient_request_id)
+ if ((r = sshbuf_get_u32(m, &type)) != 0 ||
+ (r = sshbuf_get_u32(m, &rid)) != 0)
+ fatal("%s: decode: %s", __func__, ssh_err(r));
+ if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
+
switch (type) {
case MUX_S_OK:
break;
case MUX_S_REMOTE_PORT:
if (cancel_flag)
fatal("%s: got MUX_S_REMOTE_PORT for cancel", __func__);
- fwd->allocated_port = buffer_get_int(&m);
- logit("Allocated port %u for remote forward to %s:%d",
+ if ((r = sshbuf_get_u32(m, &fwd->allocated_port)) != 0)
+ fatal("%s: decode port: %s", __func__, ssh_err(r));
+ verbose("Allocated port %u for remote forward to %s:%d",
fwd->allocated_port,
fwd->connect_host ? fwd->connect_host : "",
fwd->connect_port);
if (muxclient_command == SSHMUX_COMMAND_FORWARD)
- fprintf(stdout, "%u\n", fwd->allocated_port);
+ fprintf(stdout, "%i\n", fwd->allocated_port);
break;
case MUX_S_PERMISSION_DENIED:
- e = buffer_get_string(&m, NULL);
- buffer_free(&m);
+ if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
+ fatal("%s: decode error: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
error("Master refused forwarding request: %s", e);
return -1;
case MUX_S_FAILURE:
- e = buffer_get_string(&m, NULL);
- buffer_free(&m);
+ if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
+ fatal("%s: decode error: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
error("%s: forwarding request failed: %s", __func__, e);
return -1;
default:
fatal("%s: unexpected response from master 0x%08x",
__func__, type);
}
- buffer_free(&m);
+ sshbuf_free(m);
muxclient_request_id++;
return 0;
@@ -1777,11 +1897,12 @@ mux_client_forwards(int fd, int cancel_flag)
static int
mux_client_request_session(int fd)
{
- Buffer m;
- char *e, *term;
- u_int i, rid, sid, esid, exitval, type, exitval_seen;
+ struct sshbuf *m;
+ char *e;
+ const char *term;
+ u_int echar, rid, sid, esid, exitval, type, exitval_seen;
extern char **environ;
- int devnull, rawmode;
+ int r, i, devnull, rawmode;
debug3("%s: entering", __func__);
@@ -1790,7 +1911,7 @@ mux_client_request_session(int fd)
return -1;
}
- signal(SIGPIPE, SIG_IGN);
+ ssh_signal(SIGPIPE, SIG_IGN);
if (stdin_null_flag) {
if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
@@ -1801,31 +1922,41 @@ mux_client_request_session(int fd)
close(devnull);
}
- term = getenv("TERM");
-
- buffer_init(&m);
- buffer_put_int(&m, MUX_C_NEW_SESSION);
- buffer_put_int(&m, muxclient_request_id);
- buffer_put_cstring(&m, ""); /* reserved */
- buffer_put_int(&m, tty_flag);
- buffer_put_int(&m, options.forward_x11);
- buffer_put_int(&m, options.forward_agent);
- buffer_put_int(&m, subsystem_flag);
- buffer_put_int(&m, options.escape_char == SSH_ESCAPECHAR_NONE ?
- 0xffffffff : (u_int)options.escape_char);
- buffer_put_cstring(&m, term == NULL ? "" : term);
- buffer_put_string(&m, buffer_ptr(&command), buffer_len(&command));
-
+ if ((term = getenv("TERM")) == NULL)
+ term = "";
+ echar = 0xffffffff;
+ if (options.escape_char != SSH_ESCAPECHAR_NONE)
+ echar = (u_int)options.escape_char;
+
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_put_u32(m, MUX_C_NEW_SESSION)) != 0 ||
+ (r = sshbuf_put_u32(m, muxclient_request_id)) != 0 ||
+ (r = sshbuf_put_string(m, NULL, 0)) != 0 || /* reserved */
+ (r = sshbuf_put_u32(m, tty_flag)) != 0 ||
+ (r = sshbuf_put_u32(m, options.forward_x11)) != 0 ||
+ (r = sshbuf_put_u32(m, options.forward_agent)) != 0 ||
+ (r = sshbuf_put_u32(m, subsystem_flag)) != 0 ||
+ (r = sshbuf_put_u32(m, echar)) != 0 ||
+ (r = sshbuf_put_cstring(m, term)) != 0 ||
+ (r = sshbuf_put_stringb(m, command)) != 0)
+ fatal("%s: request: %s", __func__, ssh_err(r));
+
+ /* Pass environment */
if (options.num_send_env > 0 && environ != NULL) {
- /* Pass environment */
for (i = 0; environ[i] != NULL; i++) {
- if (env_permitted(environ[i])) {
- buffer_put_cstring(&m, environ[i]);
- }
+ if (!env_permitted(environ[i]))
+ continue;
+ if ((r = sshbuf_put_cstring(m, environ[i])) != 0)
+ fatal("%s: request: %s", __func__, ssh_err(r));
}
}
+ for (i = 0; i < options.num_setenv; i++) {
+ if ((r = sshbuf_put_cstring(m, options.setenv[i])) != 0)
+ fatal("%s: request: %s", __func__, ssh_err(r));
+ }
- if (mux_client_write_packet(fd, &m) != 0)
+ if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
/* Send the stdio file descriptors */
@@ -1837,45 +1968,55 @@ mux_client_request_session(int fd)
debug3("%s: session request sent", __func__);
/* Read their reply */
- buffer_clear(&m);
- if (mux_client_read_packet(fd, &m) != 0) {
+ sshbuf_reset(m);
+ if (mux_client_read_packet(fd, m) != 0) {
error("%s: read from master failed: %s",
__func__, strerror(errno));
- buffer_free(&m);
+ sshbuf_free(m);
return -1;
}
- type = buffer_get_int(&m);
- if ((rid = buffer_get_int(&m)) != muxclient_request_id)
+ if ((r = sshbuf_get_u32(m, &type)) != 0 ||
+ (r = sshbuf_get_u32(m, &rid)) != 0)
+ fatal("%s: decode: %s", __func__, ssh_err(r));
+ if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
+
switch (type) {
case MUX_S_SESSION_OPENED:
- sid = buffer_get_int(&m);
+ if ((r = sshbuf_get_u32(m, &sid)) != 0)
+ fatal("%s: decode ID: %s", __func__, ssh_err(r));
debug("%s: master session id: %u", __func__, sid);
break;
case MUX_S_PERMISSION_DENIED:
- e = buffer_get_string(&m, NULL);
- buffer_free(&m);
+ if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
+ fatal("%s: decode error: %s", __func__, ssh_err(r));
error("Master refused session request: %s", e);
+ sshbuf_free(m);
return -1;
case MUX_S_FAILURE:
- e = buffer_get_string(&m, NULL);
- buffer_free(&m);
+ if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
+ fatal("%s: decode error: %s", __func__, ssh_err(r));
error("%s: session request failed: %s", __func__, e);
+ sshbuf_free(m);
return -1;
default:
- buffer_free(&m);
+ sshbuf_free(m);
error("%s: unexpected response from master 0x%08x",
__func__, type);
return -1;
}
muxclient_request_id++;
- signal(SIGHUP, control_client_sighandler);
- signal(SIGINT, control_client_sighandler);
- signal(SIGTERM, control_client_sighandler);
- signal(SIGWINCH, control_client_sigrelay);
+ if (pledge("stdio proc tty", NULL) == -1)
+ fatal("%s pledge(): %s", __func__, strerror(errno));
+ platform_pledge_mux();
+
+ ssh_signal(SIGHUP, control_client_sighandler);
+ ssh_signal(SIGINT, control_client_sighandler);
+ ssh_signal(SIGTERM, control_client_sighandler);
+ ssh_signal(SIGWINCH, control_client_sigrelay);
rawmode = tty_flag;
if (tty_flag)
@@ -1889,13 +2030,17 @@ mux_client_request_session(int fd)
* terminate early too (possibly losing data).
*/
for (exitval = 255, exitval_seen = 0;;) {
- buffer_clear(&m);
- if (mux_client_read_packet(fd, &m) != 0)
+ sshbuf_reset(m);
+ if (mux_client_read_packet(fd, m) != 0)
break;
- type = buffer_get_int(&m);
+ if ((r = sshbuf_get_u32(m, &type)) != 0)
+ fatal("%s: decode type: %s", __func__, ssh_err(r));
switch (type) {
case MUX_S_TTY_ALLOC_FAIL:
- if ((esid = buffer_get_int(&m)) != sid)
+ if ((r = sshbuf_get_u32(m, &esid)) != 0)
+ fatal("%s: decode ID: %s",
+ __func__, ssh_err(r));
+ if (esid != sid)
fatal("%s: tty alloc fail on unknown session: "
"my id %u theirs %u",
__func__, sid, esid);
@@ -1904,17 +2049,24 @@ mux_client_request_session(int fd)
rawmode = 0;
continue;
case MUX_S_EXIT_MESSAGE:
- if ((esid = buffer_get_int(&m)) != sid)
+ if ((r = sshbuf_get_u32(m, &esid)) != 0)
+ fatal("%s: decode ID: %s",
+ __func__, ssh_err(r));
+ if (esid != sid)
fatal("%s: exit on unknown session: "
"my id %u theirs %u",
__func__, sid, esid);
if (exitval_seen)
fatal("%s: exitval sent twice", __func__);
- exitval = buffer_get_int(&m);
+ if ((r = sshbuf_get_u32(m, &exitval)) != 0)
+ fatal("%s: decode exit value: %s",
+ __func__, ssh_err(r));
exitval_seen = 1;
continue;
default:
- e = buffer_get_string(&m, NULL);
+ 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);
}
}
@@ -1924,7 +2076,7 @@ mux_client_request_session(int fd)
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
if (muxclient_terminate) {
- debug2("Exiting on signal %d", muxclient_terminate);
+ debug2("Exiting on signal: %s", strsignal(muxclient_terminate));
exitval = 255;
} else if (!exitval_seen) {
debug2("Control master terminated unexpectedly");
@@ -1939,12 +2091,53 @@ mux_client_request_session(int fd)
}
static int
+mux_client_proxy(int fd)
+{
+ struct sshbuf *m;
+ char *e;
+ u_int type, rid;
+ int r;
+
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_put_u32(m, MUX_C_PROXY)) != 0 ||
+ (r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
+ fatal("%s: request: %s", __func__, ssh_err(r));
+ if (mux_client_write_packet(fd, m) != 0)
+ fatal("%s: write packet: %s", __func__, strerror(errno));
+
+ sshbuf_reset(m);
+
+ /* Read their reply */
+ if (mux_client_read_packet(fd, m) != 0) {
+ sshbuf_free(m);
+ return 0;
+ }
+ if ((r = sshbuf_get_u32(m, &type)) != 0 ||
+ (r = sshbuf_get_u32(m, &rid)) != 0)
+ fatal("%s: decode: %s", __func__, ssh_err(r));
+ if (rid != muxclient_request_id)
+ fatal("%s: out of sequence reply: my id %u theirs %u",
+ __func__, muxclient_request_id, rid);
+ if (type != MUX_S_PROXY) {
+ if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
+ fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal("%s: master returned error: %s", __func__, e);
+ }
+ sshbuf_free(m);
+
+ debug3("%s: done", __func__);
+ muxclient_request_id++;
+ return 0;
+}
+
+static int
mux_client_request_stdio_fwd(int fd)
{
- Buffer m;
+ struct sshbuf *m;
char *e;
u_int type, rid, sid;
- int devnull;
+ int r, devnull;
debug3("%s: entering", __func__);
@@ -1953,7 +2146,7 @@ mux_client_request_stdio_fwd(int fd)
return -1;
}
- signal(SIGPIPE, SIG_IGN);
+ ssh_signal(SIGPIPE, SIG_IGN);
if (stdin_null_flag) {
if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
@@ -1964,14 +2157,16 @@ mux_client_request_stdio_fwd(int fd)
close(devnull);
}
- buffer_init(&m);
- buffer_put_int(&m, MUX_C_NEW_STDIO_FWD);
- buffer_put_int(&m, muxclient_request_id);
- buffer_put_cstring(&m, ""); /* reserved */
- buffer_put_cstring(&m, stdio_forward_host);
- buffer_put_int(&m, stdio_forward_port);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_put_u32(m, MUX_C_NEW_STDIO_FWD)) != 0 ||
+ (r = sshbuf_put_u32(m, muxclient_request_id)) != 0 ||
+ (r = sshbuf_put_string(m, NULL, 0)) != 0 || /* reserved */
+ (r = sshbuf_put_cstring(m, options.stdio_forward_host)) != 0 ||
+ (r = sshbuf_put_u32(m, options.stdio_forward_port)) != 0)
+ fatal("%s: request: %s", __func__, ssh_err(r));
- if (mux_client_write_packet(fd, &m) != 0)
+ if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
/* Send the stdio file descriptors */
@@ -1979,53 +2174,62 @@ mux_client_request_stdio_fwd(int fd)
mm_send_fd(fd, STDOUT_FILENO) == -1)
fatal("%s: send fds failed", __func__);
+ if (pledge("stdio proc tty", NULL) == -1)
+ fatal("%s pledge(): %s", __func__, strerror(errno));
+ platform_pledge_mux();
+
debug3("%s: stdio forward request sent", __func__);
/* Read their reply */
- buffer_clear(&m);
+ sshbuf_reset(m);
- if (mux_client_read_packet(fd, &m) != 0) {
+ if (mux_client_read_packet(fd, m) != 0) {
error("%s: read from master failed: %s",
__func__, strerror(errno));
- buffer_free(&m);
+ sshbuf_free(m);
return -1;
}
- type = buffer_get_int(&m);
- if ((rid = buffer_get_int(&m)) != muxclient_request_id)
+ if ((r = sshbuf_get_u32(m, &type)) != 0 ||
+ (r = sshbuf_get_u32(m, &rid)) != 0)
+ fatal("%s: decode: %s", __func__, ssh_err(r));
+ if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
switch (type) {
case MUX_S_SESSION_OPENED:
- sid = buffer_get_int(&m);
+ if ((r = sshbuf_get_u32(m, &sid)) != 0)
+ fatal("%s: decode ID: %s", __func__, ssh_err(r));
debug("%s: master session id: %u", __func__, sid);
break;
case MUX_S_PERMISSION_DENIED:
- e = buffer_get_string(&m, NULL);
- buffer_free(&m);
+ if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
+ fatal("%s: decode error: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
fatal("Master refused stdio forwarding request: %s", e);
case MUX_S_FAILURE:
- e = buffer_get_string(&m, NULL);
- buffer_free(&m);
+ if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
+ fatal("%s: decode error: %s", __func__, ssh_err(r));
+ sshbuf_free(m);
fatal("Stdio forwarding request failed: %s", e);
default:
- buffer_free(&m);
+ sshbuf_free(m);
error("%s: unexpected response from master 0x%08x",
__func__, type);
return -1;
}
muxclient_request_id++;
- signal(SIGHUP, control_client_sighandler);
- signal(SIGINT, control_client_sighandler);
- signal(SIGTERM, control_client_sighandler);
- signal(SIGWINCH, control_client_sigrelay);
+ ssh_signal(SIGHUP, control_client_sighandler);
+ ssh_signal(SIGINT, control_client_sighandler);
+ ssh_signal(SIGTERM, control_client_sighandler);
+ ssh_signal(SIGWINCH, control_client_sigrelay);
/*
* Stick around until the controlee closes the client_fd.
*/
- buffer_clear(&m);
- if (mux_client_read_packet(fd, &m) != 0) {
+ sshbuf_reset(m);
+ if (mux_client_read_packet(fd, m) != 0) {
if (errno == EPIPE ||
(errno == EINTR && muxclient_terminate != 0))
return 0;
@@ -2038,58 +2242,65 @@ mux_client_request_stdio_fwd(int fd)
static void
mux_client_request_stop_listening(int fd)
{
- Buffer m;
+ struct sshbuf *m;
char *e;
u_int type, rid;
+ int r;
debug3("%s: entering", __func__);
- buffer_init(&m);
- buffer_put_int(&m, MUX_C_STOP_LISTENING);
- buffer_put_int(&m, muxclient_request_id);
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((r = sshbuf_put_u32(m, MUX_C_STOP_LISTENING)) != 0 ||
+ (r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
+ fatal("%s: request: %s", __func__, ssh_err(r));
- if (mux_client_write_packet(fd, &m) != 0)
+ if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
- buffer_clear(&m);
+ sshbuf_reset(m);
/* Read their reply */
- if (mux_client_read_packet(fd, &m) != 0)
+ if (mux_client_read_packet(fd, m) != 0)
fatal("%s: read from master failed: %s",
__func__, strerror(errno));
- type = buffer_get_int(&m);
- if ((rid = buffer_get_int(&m)) != muxclient_request_id)
+ if ((r = sshbuf_get_u32(m, &type)) != 0 ||
+ (r = sshbuf_get_u32(m, &rid)) != 0)
+ fatal("%s: decode: %s", __func__, ssh_err(r));
+ if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
+
switch (type) {
case MUX_S_OK:
break;
case MUX_S_PERMISSION_DENIED:
- e = buffer_get_string(&m, NULL);
+ if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
+ fatal("%s: decode error: %s", __func__, ssh_err(r));
fatal("Master refused stop listening request: %s", e);
case MUX_S_FAILURE:
- e = buffer_get_string(&m, NULL);
+ if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
+ fatal("%s: decode error: %s", __func__, ssh_err(r));
fatal("%s: stop listening request failed: %s", __func__, e);
default:
fatal("%s: unexpected response from master 0x%08x",
__func__, type);
}
- buffer_free(&m);
+ sshbuf_free(m);
muxclient_request_id++;
}
/* Multiplex client main loop. */
-void
+int
muxclient(const char *path)
{
struct sockaddr_un addr;
- socklen_t sun_len;
int sock;
u_int pid;
if (muxclient_command == 0) {
- if (stdio_forward_host != NULL)
+ if (options.stdio_forward_host != NULL)
muxclient_command = SSHMUX_COMMAND_STDIO_FWD;
else
muxclient_command = SSHMUX_COMMAND_OPEN;
@@ -2103,22 +2314,21 @@ muxclient(const char *path)
case SSHCTL_MASTER_NO:
break;
default:
- return;
+ return -1;
}
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
- sun_len = offsetof(struct sockaddr_un, sun_path) +
- strlen(path) + 1;
if (strlcpy(addr.sun_path, path,
sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
- fatal("ControlPath too long");
+ fatal("ControlPath too long ('%s' >= %u bytes)", path,
+ (unsigned int)sizeof(addr.sun_path));
- if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
+ if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
fatal("%s socket(): %s", __func__, strerror(errno));
- if (connect(sock, (struct sockaddr *)&addr, sun_len) == -1) {
+ if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
switch (muxclient_command) {
case SSHMUX_COMMAND_OPEN:
case SSHMUX_COMMAND_STDIO_FWD:
@@ -2138,25 +2348,26 @@ muxclient(const char *path)
strerror(errno));
}
close(sock);
- return;
+ return -1;
}
set_nonblock(sock);
if (mux_client_hello_exchange(sock) != 0) {
error("%s: master hello exchange failed", __func__);
close(sock);
- return;
+ return -1;
}
switch (muxclient_command) {
case SSHMUX_COMMAND_ALIVE_CHECK:
if ((pid = mux_client_request_alive(sock)) == 0)
fatal("%s: master alive check failed", __func__);
- fprintf(stderr, "Master running (pid=%d)\r\n", pid);
+ fprintf(stderr, "Master running (pid=%u)\r\n", pid);
exit(0);
case SSHMUX_COMMAND_TERMINATE:
mux_client_request_terminate(sock);
- fprintf(stderr, "Exit request sent.\r\n");
+ if (options.log_level != SYSLOG_LEVEL_QUIET)
+ fprintf(stderr, "Exit request sent.\r\n");
exit(0);
case SSHMUX_COMMAND_FORWARD:
if (mux_client_forwards(sock, 0) != 0)
@@ -2165,22 +2376,26 @@ muxclient(const char *path)
case SSHMUX_COMMAND_OPEN:
if (mux_client_forwards(sock, 0) != 0) {
error("%s: master forward request failed", __func__);
- return;
+ return -1;
}
mux_client_request_session(sock);
- return;
+ return -1;
case SSHMUX_COMMAND_STDIO_FWD:
mux_client_request_stdio_fwd(sock);
exit(0);
case SSHMUX_COMMAND_STOP:
mux_client_request_stop_listening(sock);
- fprintf(stderr, "Stop listening request sent.\r\n");
+ if (options.log_level != SYSLOG_LEVEL_QUIET)
+ fprintf(stderr, "Stop listening request sent.\r\n");
exit(0);
case SSHMUX_COMMAND_CANCEL_FWD:
if (mux_client_forwards(sock, 1) != 0)
error("%s: master cancel forward request failed",
__func__);
exit(0);
+ case SSHMUX_COMMAND_PROXY:
+ mux_client_proxy(sock);
+ return (sock);
default:
fatal("unrecognised muxclient_command %d", muxclient_command);
}
diff --git a/myproposal.h b/myproposal.h
index 61d79ca2..5312e605 100644
--- a/myproposal.h
+++ b/myproposal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: myproposal.h,v 1.41 2014/07/11 13:54:34 tedu Exp $ */
+/* $OpenBSD: myproposal.h,v 1.67 2020/01/24 00:28:57 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -24,139 +24,46 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <openssl/opensslv.h>
-
-/* conditional algorithm support */
-
-#ifdef OPENSSL_HAS_ECC
-#ifdef OPENSSL_HAS_NISTP521
-# define KEX_ECDH_METHODS \
+#define KEX_SERVER_KEX \
+ "curve25519-sha256," \
+ "curve25519-sha256@libssh.org," \
"ecdh-sha2-nistp256," \
"ecdh-sha2-nistp384," \
- "ecdh-sha2-nistp521,"
-# define HOSTKEY_ECDSA_CERT_METHODS \
- "ecdsa-sha2-nistp256-cert-v01@openssh.com," \
- "ecdsa-sha2-nistp384-cert-v01@openssh.com," \
- "ecdsa-sha2-nistp521-cert-v01@openssh.com,"
-# define HOSTKEY_ECDSA_METHODS \
- "ecdsa-sha2-nistp256," \
- "ecdsa-sha2-nistp384," \
- "ecdsa-sha2-nistp521,"
-#else
-# define KEX_ECDH_METHODS \
- "ecdh-sha2-nistp256," \
- "ecdh-sha2-nistp384,"
-# define HOSTKEY_ECDSA_CERT_METHODS \
- "ecdsa-sha2-nistp256-cert-v01@openssh.com," \
- "ecdsa-sha2-nistp384-cert-v01@openssh.com,"
-# define HOSTKEY_ECDSA_METHODS \
- "ecdsa-sha2-nistp256," \
- "ecdsa-sha2-nistp384,"
-#endif
-#else
-# define KEX_ECDH_METHODS
-# define HOSTKEY_ECDSA_CERT_METHODS
-# define HOSTKEY_ECDSA_METHODS
-#endif
-
-#ifdef OPENSSL_HAVE_EVPGCM
-# define AESGCM_CIPHER_MODES \
- "aes128-gcm@openssh.com,aes256-gcm@openssh.com,"
-#else
-# define AESGCM_CIPHER_MODES
-#endif
-
-#ifdef HAVE_EVP_SHA256
-# define KEX_SHA256_METHODS \
- "diffie-hellman-group-exchange-sha256,"
-#define SHA2_HMAC_MODES \
- "hmac-sha2-256," \
- "hmac-sha2-512,"
-#else
-# define KEX_SHA256_METHODS
-# define SHA2_HMAC_MODES
-#endif
-
-#ifdef HAVE_EVP_RIPEMD
-#define RIPEMD_MAC_MODES \
- "hmac-ripemd160-etm@openssh.com," \
- "hmac-ripemd160," \
- "hmac-ripemd160@openssh.com",
-#else
-#define RIPEMD_MAC_MODES
-#endif
-
-#ifdef WITH_OPENSSL
-# ifdef HAVE_EVP_SHA256
-# define KEX_CURVE25519_METHODS "curve25519-sha256@libssh.org,"
-# else
-# define KEX_CURVE25519_METHODS ""
-# endif
-#define KEX_SERVER_KEX \
- KEX_CURVE25519_METHODS \
- KEX_ECDH_METHODS \
- KEX_SHA256_METHODS \
- "diffie-hellman-group14-sha1"
+ "ecdh-sha2-nistp521," \
+ "diffie-hellman-group-exchange-sha256," \
+ "diffie-hellman-group16-sha512," \
+ "diffie-hellman-group18-sha512," \
+ "diffie-hellman-group14-sha256"
-#define KEX_CLIENT_KEX KEX_SERVER_KEX "," \
- "diffie-hellman-group-exchange-sha1," \
- "diffie-hellman-group1-sha1"
+#define KEX_CLIENT_KEX KEX_SERVER_KEX
#define KEX_DEFAULT_PK_ALG \
- HOSTKEY_ECDSA_CERT_METHODS \
+ "ecdsa-sha2-nistp256-cert-v01@openssh.com," \
+ "ecdsa-sha2-nistp384-cert-v01@openssh.com," \
+ "ecdsa-sha2-nistp521-cert-v01@openssh.com," \
+ "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com," \
"ssh-ed25519-cert-v01@openssh.com," \
+ "sk-ssh-ed25519-cert-v01@openssh.com," \
+ "rsa-sha2-512-cert-v01@openssh.com," \
+ "rsa-sha2-256-cert-v01@openssh.com," \
"ssh-rsa-cert-v01@openssh.com," \
- "ssh-dss-cert-v01@openssh.com," \
- "ssh-rsa-cert-v00@openssh.com," \
- "ssh-dss-cert-v00@openssh.com," \
- HOSTKEY_ECDSA_METHODS \
+ "ecdsa-sha2-nistp256," \
+ "ecdsa-sha2-nistp384," \
+ "ecdsa-sha2-nistp521," \
+ "sk-ecdsa-sha2-nistp256@openssh.com," \
"ssh-ed25519," \
- "ssh-rsa," \
- "ssh-dss"
-
-/* the actual algorithms */
+ "sk-ssh-ed25519@openssh.com," \
+ "rsa-sha2-512," \
+ "rsa-sha2-256," \
+ "ssh-rsa"
-#define KEX_SERVER_ENCRYPT \
+#define KEX_SERVER_ENCRYPT \
+ "chacha20-poly1305@openssh.com," \
"aes128-ctr,aes192-ctr,aes256-ctr," \
- AESGCM_CIPHER_MODES \
- "chacha20-poly1305@openssh.com"
+ "aes128-gcm@openssh.com,aes256-gcm@openssh.com"
-#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT "," \
- "arcfour256,arcfour128," \
- "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \
- "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"
+#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT
-#define KEX_SERVER_MAC \
- "umac-64-etm@openssh.com," \
- "umac-128-etm@openssh.com," \
- "hmac-sha2-256-etm@openssh.com," \
- "hmac-sha2-512-etm@openssh.com," \
- "hmac-sha1-etm@openssh.com," \
- "umac-64@openssh.com," \
- "umac-128@openssh.com," \
- "hmac-sha2-256," \
- "hmac-sha2-512," \
- "hmac-sha1"
-
-#define KEX_CLIENT_MAC KEX_SERVER_MAC "," \
- "hmac-md5-etm@openssh.com," \
- "hmac-sha1-96-etm@openssh.com," \
- "hmac-md5-96-etm@openssh.com," \
- "hmac-md5," \
- RIPEMD_MAC_MODES \
- "hmac-sha1-96," \
- "hmac-md5-96"
-
-#else
-
-#define KEX_SERVER_KEX \
- "curve25519-sha256@libssh.org"
-#define KEX_DEFAULT_PK_ALG \
- "ssh-ed25519-cert-v01@openssh.com," \
- "ssh-ed25519"
-#define KEX_SERVER_ENCRYPT \
- "aes128-ctr,aes192-ctr,aes256-ctr," \
- "chacha20-poly1305@openssh.com"
#define KEX_SERVER_MAC \
"umac-64-etm@openssh.com," \
"umac-128-etm@openssh.com," \
@@ -169,13 +76,20 @@
"hmac-sha2-512," \
"hmac-sha1"
-#define KEX_CLIENT_KEX KEX_SERVER_KEX
-#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT
#define KEX_CLIENT_MAC KEX_SERVER_MAC
-#endif /* WITH_OPENSSL */
+/* Not a KEX value, but here so all the algorithm defaults are together */
+#define SSH_ALLOWED_CA_SIGALGS \
+ "ecdsa-sha2-nistp256," \
+ "ecdsa-sha2-nistp384," \
+ "ecdsa-sha2-nistp521," \
+ "sk-ecdsa-sha2-nistp256@openssh.com," \
+ "ssh-ed25519," \
+ "sk-ssh-ed25519@openssh.com," \
+ "rsa-sha2-512," \
+ "rsa-sha2-256"
-#define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib"
+#define KEX_DEFAULT_COMP "none,zlib@openssh.com"
#define KEX_DEFAULT_LANG ""
#define KEX_CLIENT \
@@ -201,4 +115,3 @@
KEX_DEFAULT_COMP, \
KEX_DEFAULT_LANG, \
KEX_DEFAULT_LANG
-
diff --git a/nchan.c b/nchan.c
index 20f6a2f4..1e96eb64 100644
--- a/nchan.c
+++ b/nchan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nchan.c,v 1.63 2010/01/26 01:28:35 djm Exp $ */
+/* $OpenBSD: nchan.c,v 1.70 2019/06/28 13:35:04 deraadt Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
@@ -33,9 +33,9 @@
#include <stdarg.h>
#include "openbsd-compat/sys-queue.h"
-#include "ssh1.h"
#include "ssh2.h"
-#include "buffer.h"
+#include "sshbuf.h"
+#include "ssherr.h"
#include "packet.h"
#include "channels.h"
#include "compat.h"
@@ -74,18 +74,16 @@
/*
* ACTIONS: should never update the channel states
*/
-static void chan_send_ieof1(Channel *);
-static void chan_send_oclose1(Channel *);
-static void chan_send_close2(Channel *);
-static void chan_send_eof2(Channel *);
-static void chan_send_eow2(Channel *);
+static void chan_send_eof2(struct ssh *, Channel *);
+static void chan_send_eow2(struct ssh *, Channel *);
/* helper */
-static void chan_shutdown_write(Channel *);
-static void chan_shutdown_read(Channel *);
+static void chan_shutdown_write(struct ssh *, Channel *);
+static void chan_shutdown_read(struct ssh *, Channel *);
+static void chan_shutdown_extended_read(struct ssh *, Channel *);
-static char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
-static char *istates[] = { "open", "drain", "wait_oclose", "closed" };
+static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
+static const char *istates[] = { "open", "drain", "wait_oclose", "closed" };
static void
chan_set_istate(Channel *c, u_int next)
@@ -96,6 +94,7 @@ chan_set_istate(Channel *c, u_int next)
istates[next]);
c->istate = next;
}
+
static void
chan_set_ostate(Channel *c, u_int next)
{
@@ -106,41 +105,13 @@ chan_set_ostate(Channel *c, u_int next)
c->ostate = next;
}
-/*
- * SSH1 specific implementation of event functions
- */
-
-static void
-chan_rcvd_oclose1(Channel *c)
-{
- debug2("channel %d: rcvd oclose", c->self);
- switch (c->istate) {
- case CHAN_INPUT_WAIT_OCLOSE:
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- break;
- case CHAN_INPUT_OPEN:
- chan_shutdown_read(c);
- chan_send_ieof1(c);
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- break;
- case CHAN_INPUT_WAIT_DRAIN:
- /* both local read_failed and remote write_failed */
- chan_send_ieof1(c);
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- break;
- default:
- error("channel %d: protocol error: rcvd_oclose for istate %d",
- c->self, c->istate);
- return;
- }
-}
void
-chan_read_failed(Channel *c)
+chan_read_failed(struct ssh *ssh, Channel *c)
{
debug2("channel %d: read failed", c->self);
switch (c->istate) {
case CHAN_INPUT_OPEN:
- chan_shutdown_read(c);
+ chan_shutdown_read(ssh, c);
chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN);
break;
default:
@@ -149,25 +120,21 @@ chan_read_failed(Channel *c)
break;
}
}
+
void
-chan_ibuf_empty(Channel *c)
+chan_ibuf_empty(struct ssh *ssh, Channel *c)
{
debug2("channel %d: ibuf empty", c->self);
- if (buffer_len(&c->input)) {
+ if (sshbuf_len(c->input)) {
error("channel %d: chan_ibuf_empty for non empty buffer",
c->self);
return;
}
switch (c->istate) {
case CHAN_INPUT_WAIT_DRAIN:
- if (compat20) {
- if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))
- chan_send_eof2(c);
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- } else {
- chan_send_ieof1(c);
- chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE);
- }
+ if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))
+ chan_send_eof2(ssh, c);
+ chan_set_istate(c, CHAN_INPUT_CLOSED);
break;
default:
error("channel %d: chan_ibuf_empty for istate %d",
@@ -175,58 +142,19 @@ chan_ibuf_empty(Channel *c)
break;
}
}
-static void
-chan_rcvd_ieof1(Channel *c)
-{
- debug2("channel %d: rcvd ieof", c->self);
- switch (c->ostate) {
- case CHAN_OUTPUT_OPEN:
- chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
- break;
- case CHAN_OUTPUT_WAIT_IEOF:
- chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
- break;
- default:
- error("channel %d: protocol error: rcvd_ieof for ostate %d",
- c->self, c->ostate);
- break;
- }
-}
-static void
-chan_write_failed1(Channel *c)
-{
- debug2("channel %d: write failed", c->self);
- switch (c->ostate) {
- case CHAN_OUTPUT_OPEN:
- chan_shutdown_write(c);
- chan_send_oclose1(c);
- chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF);
- break;
- case CHAN_OUTPUT_WAIT_DRAIN:
- chan_shutdown_write(c);
- chan_send_oclose1(c);
- chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
- break;
- default:
- error("channel %d: chan_write_failed for ostate %d",
- c->self, c->ostate);
- break;
- }
-}
+
void
-chan_obuf_empty(Channel *c)
+chan_obuf_empty(struct ssh *ssh, Channel *c)
{
debug2("channel %d: obuf empty", c->self);
- if (buffer_len(&c->output)) {
+ if (sshbuf_len(c->output)) {
error("channel %d: chan_obuf_empty for non empty buffer",
c->self);
return;
}
switch (c->ostate) {
case CHAN_OUTPUT_WAIT_DRAIN:
- chan_shutdown_write(c);
- if (!compat20)
- chan_send_oclose1(c);
+ chan_shutdown_write(ssh, c);
chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
break;
default:
@@ -235,47 +163,107 @@ chan_obuf_empty(Channel *c)
break;
}
}
-static void
-chan_send_ieof1(Channel *c)
+
+void
+chan_rcvd_eow(struct ssh *ssh, Channel *c)
{
- debug2("channel %d: send ieof", c->self);
+ debug2("channel %d: rcvd eow", c->self);
switch (c->istate) {
case CHAN_INPUT_OPEN:
+ chan_shutdown_read(ssh, c);
+ chan_set_istate(c, CHAN_INPUT_CLOSED);
+ break;
+ }
+}
+
+static void
+chan_send_eof2(struct ssh *ssh, Channel *c)
+{
+ int r;
+
+ debug2("channel %d: send eof", c->self);
+ switch (c->istate) {
case CHAN_INPUT_WAIT_DRAIN:
- packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
- packet_put_int(c->remote_id);
- packet_send();
+ if (!c->have_remote_id)
+ fatal("%s: channel %d: no remote_id",
+ __func__, 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));
+ c->flags |= CHAN_EOF_SENT;
break;
default:
- error("channel %d: cannot send ieof for istate %d",
+ error("channel %d: cannot send eof for istate %d",
c->self, c->istate);
break;
}
}
+
static void
-chan_send_oclose1(Channel *c)
+chan_send_close2(struct ssh *ssh, Channel *c)
{
- debug2("channel %d: send oclose", c->self);
- switch (c->ostate) {
- case CHAN_OUTPUT_OPEN:
- case CHAN_OUTPUT_WAIT_DRAIN:
- buffer_clear(&c->output);
- packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
- packet_put_int(c->remote_id);
- packet_send();
- break;
- default:
- error("channel %d: cannot send oclose for ostate %d",
- c->self, c->ostate);
- break;
+ int r;
+
+ debug2("channel %d: send close", c->self);
+ if (c->ostate != CHAN_OUTPUT_CLOSED ||
+ c->istate != CHAN_INPUT_CLOSED) {
+ error("channel %d: cannot send close for istate/ostate %d/%d",
+ c->self, c->istate, c->ostate);
+ } else if (c->flags & CHAN_CLOSE_SENT) {
+ error("channel %d: already sent close", c->self);
+ } else {
+ if (!c->have_remote_id)
+ fatal("%s: channel %d: no remote_id",
+ __func__, 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));
+ c->flags |= CHAN_CLOSE_SENT;
}
}
-/*
- * the same for SSH2
- */
static void
-chan_rcvd_close2(Channel *c)
+chan_send_eow2(struct ssh *ssh, Channel *c)
+{
+ int r;
+
+ debug2("channel %d: send eow", c->self);
+ if (c->ostate == CHAN_OUTPUT_CLOSED) {
+ error("channel %d: must not sent eow on closed output",
+ c->self);
+ return;
+ }
+ if (!(datafellows & SSH_NEW_OPENSSH))
+ return;
+ if (!c->have_remote_id)
+ fatal("%s: channel %d: no remote_id", __func__, 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));
+}
+
+/* shared */
+
+void
+chan_rcvd_ieof(struct ssh *ssh, Channel *c)
+{
+ debug2("channel %d: rcvd eof", c->self);
+ c->flags |= CHAN_EOF_RCVD;
+ if (c->ostate == CHAN_OUTPUT_OPEN)
+ chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
+ if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
+ sshbuf_len(c->output) == 0 &&
+ !CHANNEL_EFD_OUTPUT_ACTIVE(c))
+ chan_obuf_empty(ssh, c);
+}
+
+void
+chan_rcvd_oclose(struct ssh *ssh, Channel *c)
{
debug2("channel %d: rcvd close", c->self);
if (!(c->flags & CHAN_LOCAL)) {
@@ -301,46 +289,29 @@ chan_rcvd_close2(Channel *c)
}
switch (c->istate) {
case CHAN_INPUT_OPEN:
- chan_shutdown_read(c);
+ chan_shutdown_read(ssh, c);
+ chan_shutdown_extended_read(ssh, c);
chan_set_istate(c, CHAN_INPUT_CLOSED);
break;
case CHAN_INPUT_WAIT_DRAIN:
if (!(c->flags & CHAN_LOCAL))
- chan_send_eof2(c);
+ chan_send_eof2(ssh, c);
+ chan_shutdown_extended_read(ssh, c);
chan_set_istate(c, CHAN_INPUT_CLOSED);
break;
}
}
void
-chan_rcvd_eow(Channel *c)
-{
- debug2("channel %d: rcvd eow", c->self);
- switch (c->istate) {
- case CHAN_INPUT_OPEN:
- chan_shutdown_read(c);
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- break;
- }
-}
-static void
-chan_rcvd_eof2(Channel *c)
-{
- debug2("channel %d: rcvd eof", c->self);
- c->flags |= CHAN_EOF_RCVD;
- if (c->ostate == CHAN_OUTPUT_OPEN)
- chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
-}
-static void
-chan_write_failed2(Channel *c)
+chan_write_failed(struct ssh *ssh, Channel *c)
{
debug2("channel %d: write failed", c->self);
switch (c->ostate) {
case CHAN_OUTPUT_OPEN:
case CHAN_OUTPUT_WAIT_DRAIN:
- chan_shutdown_write(c);
+ chan_shutdown_write(ssh, c);
if (strcmp(c->ctype, "session") == 0)
- chan_send_eow2(c);
+ chan_send_eow2(ssh, c);
chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
break;
default:
@@ -349,97 +320,15 @@ chan_write_failed2(Channel *c)
break;
}
}
-static void
-chan_send_eof2(Channel *c)
-{
- debug2("channel %d: send eof", c->self);
- switch (c->istate) {
- case CHAN_INPUT_WAIT_DRAIN:
- packet_start(SSH2_MSG_CHANNEL_EOF);
- packet_put_int(c->remote_id);
- packet_send();
- c->flags |= CHAN_EOF_SENT;
- break;
- default:
- error("channel %d: cannot send eof for istate %d",
- c->self, c->istate);
- break;
- }
-}
-static void
-chan_send_close2(Channel *c)
-{
- debug2("channel %d: send close", c->self);
- if (c->ostate != CHAN_OUTPUT_CLOSED ||
- c->istate != CHAN_INPUT_CLOSED) {
- error("channel %d: cannot send close for istate/ostate %d/%d",
- c->self, c->istate, c->ostate);
- } else if (c->flags & CHAN_CLOSE_SENT) {
- error("channel %d: already sent close", c->self);
- } else {
- packet_start(SSH2_MSG_CHANNEL_CLOSE);
- packet_put_int(c->remote_id);
- packet_send();
- c->flags |= CHAN_CLOSE_SENT;
- }
-}
-static void
-chan_send_eow2(Channel *c)
-{
- debug2("channel %d: send eow", c->self);
- if (c->ostate == CHAN_OUTPUT_CLOSED) {
- error("channel %d: must not sent eow on closed output",
- c->self);
- return;
- }
- if (!(datafellows & SSH_NEW_OPENSSH))
- return;
- packet_start(SSH2_MSG_CHANNEL_REQUEST);
- packet_put_int(c->remote_id);
- packet_put_cstring("eow@openssh.com");
- packet_put_char(0);
- packet_send();
-}
-
-/* shared */
-
-void
-chan_rcvd_ieof(Channel *c)
-{
- if (compat20)
- chan_rcvd_eof2(c);
- else
- chan_rcvd_ieof1(c);
- if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
- buffer_len(&c->output) == 0 &&
- !CHANNEL_EFD_OUTPUT_ACTIVE(c))
- chan_obuf_empty(c);
-}
-void
-chan_rcvd_oclose(Channel *c)
-{
- if (compat20)
- chan_rcvd_close2(c);
- else
- chan_rcvd_oclose1(c);
-}
-void
-chan_write_failed(Channel *c)
-{
- if (compat20)
- chan_write_failed2(c);
- else
- chan_write_failed1(c);
-}
void
-chan_mark_dead(Channel *c)
+chan_mark_dead(struct ssh *ssh, Channel *c)
{
c->type = SSH_CHANNEL_ZOMBIE;
}
int
-chan_is_dead(Channel *c, int do_send)
+chan_is_dead(struct ssh *ssh, Channel *c, int do_send)
{
if (c->type == SSH_CHANNEL_ZOMBIE) {
debug2("channel %d: zombie", c->self);
@@ -447,16 +336,12 @@ chan_is_dead(Channel *c, int do_send)
}
if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
return 0;
- if (!compat20) {
- debug2("channel %d: is dead", c->self);
- return 1;
- }
if ((datafellows & SSH_BUG_EXTEOF) &&
c->extended_usage == CHAN_EXTENDED_WRITE &&
c->efd != -1 &&
- buffer_len(&c->extended) > 0) {
- debug2("channel %d: active efd: %d len %d",
- c->self, c->efd, buffer_len(&c->extended));
+ sshbuf_len(c->extended) > 0) {
+ debug2("channel %d: active efd: %d len %zu",
+ c->self, c->efd, sshbuf_len(c->extended));
return 0;
}
if (c->flags & CHAN_LOCAL) {
@@ -465,7 +350,7 @@ chan_is_dead(Channel *c, int do_send)
}
if (!(c->flags & CHAN_CLOSE_SENT)) {
if (do_send) {
- chan_send_close2(c);
+ chan_send_close2(ssh, c);
} else {
/* channel would be dead if we sent a close */
if (c->flags & CHAN_CLOSE_RCVD) {
@@ -485,47 +370,77 @@ chan_is_dead(Channel *c, int do_send)
/* helper */
static void
-chan_shutdown_write(Channel *c)
+chan_shutdown_write(struct ssh *ssh, Channel *c)
{
- buffer_clear(&c->output);
- if (compat20 && c->type == SSH_CHANNEL_LARVAL)
+ sshbuf_reset(c->output);
+ if (c->type == SSH_CHANNEL_LARVAL)
return;
/* shutdown failure is allowed if write failed already */
- debug2("channel %d: close_write", c->self);
+ 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,
+ channel_format_extended_usage(c));
if (c->sock != -1) {
- if (shutdown(c->sock, SHUT_WR) < 0)
- debug2("channel %d: chan_shutdown_write: "
- "shutdown() failed for fd %d: %.100s",
- c->self, c->sock, strerror(errno));
+ 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));
+ }
} else {
- if (channel_close_fd(&c->wfd) < 0)
- logit("channel %d: chan_shutdown_write: "
- "close() failed for fd %d: %.100s",
- c->self, c->wfd, strerror(errno));
+ 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));
+ }
}
}
+
static void
-chan_shutdown_read(Channel *c)
+chan_shutdown_read(struct ssh *ssh, Channel *c)
{
- if (compat20 && c->type == SSH_CHANNEL_LARVAL)
+ if (c->type == SSH_CHANNEL_LARVAL)
return;
- debug2("channel %d: close_read", c->self);
+ 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,
+ channel_format_extended_usage(c));
if (c->sock != -1) {
/*
* shutdown(sock, SHUT_READ) may return ENOTCONN if the
* write side has been closed already. (bug on Linux)
* HP-UX may return ENOTCONN also.
*/
- if (shutdown(c->sock, SHUT_RD) < 0
- && errno != ENOTCONN)
- error("channel %d: chan_shutdown_read: "
- "shutdown() failed for fd %d [i%d o%d]: %.100s",
- c->self, c->sock, c->istate, c->ostate,
- strerror(errno));
+ 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));
+ }
} else {
- if (channel_close_fd(&c->rfd) < 0)
- logit("channel %d: chan_shutdown_read: "
- "close() failed for fd %d: %.100s",
- c->self, c->rfd, strerror(errno));
+ 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));
+ }
+ }
+}
+
+static void
+chan_shutdown_extended_read(struct ssh *ssh, Channel *c)
+{
+ if (c->type == SSH_CHANNEL_LARVAL || c->efd == -1)
+ return;
+ 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,
+ 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));
}
}
diff --git a/opacket.c b/opacket.c
deleted file mode 100644
index b9160d59..00000000
--- a/opacket.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/* Written by Markus Friedl. Placed in the public domain. */
-
-#include "includes.h"
-
-#include "ssherr.h"
-#include "packet.h"
-#include "log.h"
-
-struct ssh *active_state, *backup_state;
-
-/* Map old to new API */
-
-void
-ssh_packet_start(struct ssh *ssh, u_char type)
-{
- int r;
-
- if ((r = sshpkt_start(ssh, type)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-void
-ssh_packet_put_char(struct ssh *ssh, int value)
-{
- u_char ch = value;
- int r;
-
- if ((r = sshpkt_put_u8(ssh, ch)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-void
-ssh_packet_put_int(struct ssh *ssh, u_int value)
-{
- int r;
-
- if ((r = sshpkt_put_u32(ssh, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-void
-ssh_packet_put_int64(struct ssh *ssh, u_int64_t value)
-{
- int r;
-
- if ((r = sshpkt_put_u64(ssh, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-void
-ssh_packet_put_string(struct ssh *ssh, const void *buf, u_int len)
-{
- int r;
-
- if ((r = sshpkt_put_string(ssh, buf, len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-void
-ssh_packet_put_cstring(struct ssh *ssh, const char *str)
-{
- int r;
-
- if ((r = sshpkt_put_cstring(ssh, str)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-void
-ssh_packet_put_raw(struct ssh *ssh, const void *buf, u_int len)
-{
- int r;
-
- if ((r = sshpkt_put(ssh, buf, len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-#ifdef WITH_SSH1
-void
-ssh_packet_put_bignum(struct ssh *ssh, BIGNUM * value)
-{
- int r;
-
- if ((r = sshpkt_put_bignum1(ssh, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-#endif
-
-#ifdef WITH_OPENSSL
-void
-ssh_packet_put_bignum2(struct ssh *ssh, BIGNUM * value)
-{
- int r;
-
- if ((r = sshpkt_put_bignum2(ssh, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-# ifdef OPENSSL_HAS_ECC
-void
-ssh_packet_put_ecpoint(struct ssh *ssh, const EC_GROUP *curve,
- const EC_POINT *point)
-{
- int r;
-
- if ((r = sshpkt_put_ec(ssh, point, curve)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-# endif
-#endif /* WITH_OPENSSL */
-
-void
-ssh_packet_send(struct ssh *ssh)
-{
- int r;
-
- if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-u_int
-ssh_packet_get_char(struct ssh *ssh)
-{
- u_char ch;
- int r;
-
- if ((r = sshpkt_get_u8(ssh, &ch)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- return ch;
-}
-
-u_int
-ssh_packet_get_int(struct ssh *ssh)
-{
- u_int val;
- int r;
-
- if ((r = sshpkt_get_u32(ssh, &val)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- return val;
-}
-
-u_int64_t
-ssh_packet_get_int64(struct ssh *ssh)
-{
- u_int64_t val;
- int r;
-
- if ((r = sshpkt_get_u64(ssh, &val)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- return val;
-}
-
-#ifdef WITH_SSH1
-void
-ssh_packet_get_bignum(struct ssh *ssh, BIGNUM * value)
-{
- int r;
-
- if ((r = sshpkt_get_bignum1(ssh, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-#endif
-
-#ifdef WITH_OPENSSL
-void
-ssh_packet_get_bignum2(struct ssh *ssh, BIGNUM * value)
-{
- int r;
-
- if ((r = sshpkt_get_bignum2(ssh, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-# ifdef OPENSSL_HAS_ECC
-void
-ssh_packet_get_ecpoint(struct ssh *ssh, const EC_GROUP *curve, EC_POINT *point)
-{
- int r;
-
- if ((r = sshpkt_get_ec(ssh, point, curve)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-# endif
-#endif /* WITH_OPENSSL */
-
-void *
-ssh_packet_get_string(struct ssh *ssh, u_int *length_ptr)
-{
- int r;
- size_t len;
- u_char *val;
-
- if ((r = sshpkt_get_string(ssh, &val, &len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- if (length_ptr != NULL)
- *length_ptr = (u_int)len;
- return val;
-}
-
-const void *
-ssh_packet_get_string_ptr(struct ssh *ssh, u_int *length_ptr)
-{
- int r;
- size_t len;
- const u_char *val;
-
- if ((r = sshpkt_get_string_direct(ssh, &val, &len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- if (length_ptr != NULL)
- *length_ptr = (u_int)len;
- return val;
-}
-
-char *
-ssh_packet_get_cstring(struct ssh *ssh, u_int *length_ptr)
-{
- int r;
- size_t len;
- char *val;
-
- if ((r = sshpkt_get_cstring(ssh, &val, &len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- if (length_ptr != NULL)
- *length_ptr = (u_int)len;
- return val;
-}
-
-/* Old API, that had to be reimplemented */
-
-void
-packet_set_connection(int fd_in, int fd_out)
-{
- active_state = ssh_packet_set_connection(active_state, fd_in, fd_out);
- if (active_state == NULL)
- fatal("%s: ssh_packet_set_connection failed", __func__);
-}
-
-void
-packet_backup_state(void)
-{
- ssh_packet_backup_state(active_state, backup_state);
-}
-
-void
-packet_restore_state(void)
-{
- ssh_packet_restore_state(active_state, backup_state);
-}
-
-u_int
-packet_get_char(void)
-{
- return (ssh_packet_get_char(active_state));
-}
-
-u_int
-packet_get_int(void)
-{
- return (ssh_packet_get_int(active_state));
-}
-
-int
-packet_read_seqnr(u_int32_t *seqnr)
-{
- u_char type;
- int r;
-
- if ((r = ssh_packet_read_seqnr(active_state, &type, seqnr)) != 0)
- sshpkt_fatal(active_state, __func__, r);
- return type;
-}
-
-int
-packet_read_poll_seqnr(u_int32_t *seqnr)
-{
- u_char type;
- int r;
-
- if ((r = ssh_packet_read_poll_seqnr(active_state, &type, seqnr)))
- sshpkt_fatal(active_state, __func__, r);
- return type;
-}
-
-void
-packet_close(void)
-{
- ssh_packet_close(active_state);
- active_state = NULL;
-}
-
-void
-packet_process_incoming(const char *buf, u_int len)
-{
- int r;
-
- if ((r = ssh_packet_process_incoming(active_state, buf, len)) != 0)
- sshpkt_fatal(active_state, __func__, r);
-}
-
-void
-packet_write_wait(void)
-{
- int r;
-
- if ((r = ssh_packet_write_wait(active_state)) != 0)
- sshpkt_fatal(active_state, __func__, r);
-}
-
-void
-packet_write_poll(void)
-{
- int r;
-
- if ((r = ssh_packet_write_poll(active_state)) != 0)
- sshpkt_fatal(active_state, __func__, r);
-}
-
-void
-packet_read_expect(int expected_type)
-{
- int r;
-
- if ((r = ssh_packet_read_expect(active_state, expected_type)) != 0)
- sshpkt_fatal(active_state, __func__, r);
-}
-
-void
-packet_disconnect(const char *fmt, ...)
-{
- char buf[1024];
- va_list args;
-
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- ssh_packet_disconnect(active_state, "%s", buf);
-}
-
-void
-packet_send_debug(const char *fmt, ...)
-{
- char buf[1024];
- va_list args;
-
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- ssh_packet_send_debug(active_state, "%s", buf);
-}
diff --git a/opacket.h b/opacket.h
deleted file mode 100644
index a0a60e55..00000000
--- a/opacket.h
+++ /dev/null
@@ -1,168 +0,0 @@
-#ifndef _OPACKET_H
-/* Written by Markus Friedl. Placed in the public domain. */
-
-/* Map old to new API */
-void ssh_packet_start(struct ssh *, u_char);
-void ssh_packet_put_char(struct ssh *, int ch);
-void ssh_packet_put_int(struct ssh *, u_int value);
-void ssh_packet_put_int64(struct ssh *, u_int64_t value);
-void ssh_packet_put_bignum(struct ssh *, BIGNUM * value);
-void ssh_packet_put_bignum2(struct ssh *, BIGNUM * value);
-void ssh_packet_put_ecpoint(struct ssh *, const EC_GROUP *, const EC_POINT *);
-void ssh_packet_put_string(struct ssh *, const void *buf, u_int len);
-void ssh_packet_put_cstring(struct ssh *, const char *str);
-void ssh_packet_put_raw(struct ssh *, const void *buf, u_int len);
-void ssh_packet_send(struct ssh *);
-
-u_int ssh_packet_get_char(struct ssh *);
-u_int ssh_packet_get_int(struct ssh *);
-u_int64_t ssh_packet_get_int64(struct ssh *);
-void ssh_packet_get_bignum(struct ssh *, BIGNUM * value);
-void ssh_packet_get_bignum2(struct ssh *, BIGNUM * value);
-void ssh_packet_get_ecpoint(struct ssh *, const EC_GROUP *, EC_POINT *);
-void *ssh_packet_get_string(struct ssh *, u_int *length_ptr);
-char *ssh_packet_get_cstring(struct ssh *, u_int *length_ptr);
-
-/* don't allow remaining bytes after the end of the message */
-#define ssh_packet_check_eom(ssh) \
-do { \
- int _len = ssh_packet_remaining(ssh); \
- if (_len > 0) { \
- logit("Packet integrity error (%d bytes remaining) at %s:%d", \
- _len ,__FILE__, __LINE__); \
- ssh_packet_disconnect(ssh, \
- "Packet integrity error."); \
- } \
-} while (0)
-
-/* old API */
-void packet_close(void);
-u_int packet_get_char(void);
-u_int packet_get_int(void);
-void packet_backup_state(void);
-void packet_restore_state(void);
-void packet_set_connection(int, int);
-int packet_read_seqnr(u_int32_t *);
-int packet_read_poll_seqnr(u_int32_t *);
-void packet_process_incoming(const char *buf, u_int len);
-void packet_write_wait(void);
-void packet_write_poll(void);
-void packet_read_expect(int expected_type);
-#define packet_set_timeout(timeout, count) \
- ssh_packet_set_timeout(active_state, (timeout), (count))
-#define packet_connection_is_on_socket() \
- ssh_packet_connection_is_on_socket(active_state)
-#define packet_set_nonblocking() \
- ssh_packet_set_nonblocking(active_state)
-#define packet_get_connection_in() \
- ssh_packet_get_connection_in(active_state)
-#define packet_get_connection_out() \
- ssh_packet_get_connection_out(active_state)
-#define packet_set_protocol_flags(protocol_flags) \
- ssh_packet_set_protocol_flags(active_state, (protocol_flags))
-#define packet_get_protocol_flags() \
- ssh_packet_get_protocol_flags(active_state)
-#define packet_start_compression(level) \
- ssh_packet_start_compression(active_state, (level))
-#define packet_set_encryption_key(key, keylen, number) \
- ssh_packet_set_encryption_key(active_state, (key), (keylen), (number))
-#define packet_start(type) \
- ssh_packet_start(active_state, (type))
-#define packet_put_char(value) \
- ssh_packet_put_char(active_state, (value))
-#define packet_put_int(value) \
- ssh_packet_put_int(active_state, (value))
-#define packet_put_int64(value) \
- ssh_packet_put_int64(active_state, (value))
-#define packet_put_string( buf, len) \
- ssh_packet_put_string(active_state, (buf), (len))
-#define packet_put_cstring(str) \
- ssh_packet_put_cstring(active_state, (str))
-#define packet_put_raw(buf, len) \
- ssh_packet_put_raw(active_state, (buf), (len))
-#define packet_put_bignum(value) \
- ssh_packet_put_bignum(active_state, (value))
-#define packet_put_bignum2(value) \
- ssh_packet_put_bignum2(active_state, (value))
-#define packet_send() \
- ssh_packet_send(active_state)
-#define packet_read() \
- ssh_packet_read(active_state)
-#define packet_get_int64() \
- ssh_packet_get_int64(active_state)
-#define packet_get_bignum(value) \
- ssh_packet_get_bignum(active_state, (value))
-#define packet_get_bignum2(value) \
- ssh_packet_get_bignum2(active_state, (value))
-#define packet_remaining() \
- ssh_packet_remaining(active_state)
-#define packet_get_string(length_ptr) \
- ssh_packet_get_string(active_state, (length_ptr))
-#define packet_get_string_ptr(length_ptr) \
- ssh_packet_get_string_ptr(active_state, (length_ptr))
-#define packet_get_cstring(length_ptr) \
- ssh_packet_get_cstring(active_state, (length_ptr))
-void packet_send_debug(const char *, ...)
- __attribute__((format(printf, 1, 2)));
-void packet_disconnect(const char *, ...)
- __attribute__((format(printf, 1, 2)))
- __attribute__((noreturn));
-#define packet_have_data_to_write() \
- ssh_packet_have_data_to_write(active_state)
-#define packet_not_very_much_data_to_write() \
- ssh_packet_not_very_much_data_to_write(active_state)
-#define packet_set_interactive(interactive, qos_interactive, qos_bulk) \
- ssh_packet_set_interactive(active_state, (interactive), (qos_interactive), (qos_bulk))
-#define packet_is_interactive() \
- ssh_packet_is_interactive(active_state)
-#define packet_set_maxsize(s) \
- ssh_packet_set_maxsize(active_state, (s))
-#define packet_inc_alive_timeouts() \
- ssh_packet_inc_alive_timeouts(active_state)
-#define packet_set_alive_timeouts(ka) \
- ssh_packet_set_alive_timeouts(active_state, (ka))
-#define packet_get_maxsize() \
- ssh_packet_get_maxsize(active_state)
-#define packet_add_padding(pad) \
- sshpkt_add_padding(active_state, (pad))
-#define packet_send_ignore(nbytes) \
- ssh_packet_send_ignore(active_state, (nbytes))
-#define packet_need_rekeying() \
- ssh_packet_need_rekeying(active_state)
-#define packet_set_server() \
- ssh_packet_set_server(active_state)
-#define packet_set_authenticated() \
- ssh_packet_set_authenticated(active_state)
-#define packet_get_input() \
- ssh_packet_get_input(active_state)
-#define packet_get_output() \
- ssh_packet_get_output(active_state)
-#define packet_set_compress_hooks(ctx, allocfunc, freefunc) \
- ssh_packet_set_compress_hooks(active_state, ctx, \
- allocfunc, freefunc);
-#define packet_check_eom() \
- ssh_packet_check_eom(active_state)
-#define set_newkeys(mode) \
- ssh_set_newkeys(active_state, (mode))
-#define packet_get_state(m) \
- ssh_packet_get_state(active_state, m)
-#define packet_set_state(m) \
- ssh_packet_set_state(active_state, m)
-#if 0
-#define get_remote_ipaddr() \
- ssh_remote_ipaddr(active_state)
-#endif
-#define packet_get_raw(lenp) \
- sshpkt_ptr(active_state, lenp)
-#define packet_get_ecpoint(c,p) \
- ssh_packet_get_ecpoint(active_state, c, p)
-#define packet_put_ecpoint(c,p) \
- ssh_packet_put_ecpoint(active_state, c, p)
-#define packet_get_rekey_timeout() \
- ssh_packet_get_rekey_timeout(active_state)
-#define packet_set_rekey_limits(x,y) \
- ssh_packet_set_rekey_limits(active_state, x, y)
-#define packet_get_bytes(x,y) \
- ssh_packet_get_bytes(active_state, x, y)
-
-#endif /* _OPACKET_H */
diff --git a/openbsd-compat/.cvsignore b/openbsd-compat/.cvsignore
deleted file mode 100644
index f3c7a7c5..00000000
--- a/openbsd-compat/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in
index 3c5e3b7f..3eb188f0 100644
--- a/openbsd-compat/Makefile.in
+++ b/openbsd-compat/Makefile.in
@@ -1,5 +1,3 @@
-# $Id: Makefile.in,v 1.56 2014/09/30 23:43:08 djm Exp $
-
sysconfdir=@sysconfdir@
piddir=@piddir@
srcdir=@srcdir@
@@ -9,21 +7,99 @@ VPATH=@srcdir@
CC=@CC@
LD=@LD@
CFLAGS=@CFLAGS@
+CFLAGS_NOPIE=@CFLAGS_NOPIE@
CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@
+PICFLAG=@PICFLAG@
LIBS=@LIBS@
AR=@AR@
RANLIB=@RANLIB@
INSTALL=@INSTALL@
LDFLAGS=-L. @LDFLAGS@
+LDFLAGS_NOPIE=-L. -Lopenbsd-compat/ @LDFLAGS_NOPIE@
-OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o reallocarray.o realpath.o rresvport.o setenv.o setproctitle.o sha1.o sha2.o rmd160.o md5.o sigact.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o
+OPENBSD=base64.o \
+ basename.o \
+ bcrypt_pbkdf.o \
+ bcrypt_pbkdf.o \
+ bindresvport.o \
+ blowfish.o \
+ daemon.o \
+ dirname.o \
+ explicit_bzero.o \
+ fmt_scaled.o \
+ freezero.o \
+ fnmatch.o \
+ getcwd.o \
+ getgrouplist.o \
+ getopt_long.o \
+ getrrsetbyname.o \
+ glob.o \
+ inet_aton.o \
+ inet_ntoa.o \
+ inet_ntop.o \
+ md5.o \
+ memmem.o \
+ mktemp.o \
+ pwcache.o \
+ readpassphrase.o \
+ reallocarray.o \
+ recallocarray.o \
+ rresvport.o \
+ setenv.o \
+ setproctitle.o \
+ sha1.o \
+ sha2.o \
+ sigact.o \
+ strcasestr.o \
+ strlcat.o \
+ strlcpy.o \
+ strmode.o \
+ strndup.o \
+ strnlen.o \
+ strptime.o \
+ strsep.o \
+ strtoll.o \
+ strtonum.o \
+ strtoull.o \
+ strtoul.o \
+ timingsafe_bcmp.o \
+ vis.o
-COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o kludge-fd_set.o
+COMPAT= arc4random.o \
+ bsd-asprintf.o \
+ bsd-closefrom.o \
+ bsd-cygwin_util.o \
+ bsd-err.o \
+ bsd-flock.o \
+ bsd-getline.o \
+ bsd-getpagesize.o \
+ bsd-getpeereid.o \
+ bsd-malloc.o \
+ bsd-misc.o \
+ bsd-nextstep.o \
+ bsd-openpty.o \
+ bsd-poll.o \
+ bsd-setres_id.o \
+ bsd-signal.o \
+ bsd-snprintf.o \
+ bsd-statvfs.o \
+ bsd-waitpid.o \
+ fake-rfc2553.o \
+ getrrsetbyname-ldns.o \
+ kludge-fd_set.o \
+ openssl-compat.o \
+ libressl-api-compat.o \
+ xcrypt.o
-PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o
+PORTS= port-aix.o \
+ port-irix.o \
+ port-linux.o \
+ port-solaris.o \
+ port-net.o \
+ port-uw.o
.c.o:
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+ $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $<
all: libopenbsd-compat.a
@@ -36,7 +112,7 @@ libopenbsd-compat.a: $(COMPAT) $(OPENBSD) $(PORTS)
$(RANLIB) $@
clean:
- rm -f *.o *.a core
+ rm -f *.o *.a core
distclean: clean
rm -f Makefile *~
diff --git a/openbsd-compat/arc4random.c b/openbsd-compat/arc4random.c
index 046f57e6..578f69f4 100644
--- a/openbsd-compat/arc4random.c
+++ b/openbsd-compat/arc4random.c
@@ -33,6 +33,10 @@
#include <string.h>
#include <unistd.h>
+#ifdef HAVE_SYS_RANDOM_H
+# include <sys/random.h>
+#endif
+
#ifndef HAVE_ARC4RANDOM
#ifdef WITH_OPENSSL
@@ -78,8 +82,9 @@ _rs_init(u_char *buf, size_t n)
}
#ifndef WITH_OPENSSL
-#define SSH_RANDOM_DEV "/dev/urandom"
-/* XXX use getrandom() if supported on Linux */
+# ifndef SSH_RANDOM_DEV
+# define SSH_RANDOM_DEV "/dev/urandom"
+# endif /* SSH_RANDOM_DEV */
static void
getrnd(u_char *s, size_t len)
{
@@ -87,6 +92,11 @@ getrnd(u_char *s, size_t len)
ssize_t r;
size_t o = 0;
+#ifdef HAVE_GETRANDOM
+ if ((r = getrandom(s, len, 0)) > 0 && (size_t)r == 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));
while (o < len) {
@@ -101,7 +111,7 @@ getrnd(u_char *s, size_t len)
}
close(fd);
}
-#endif
+#endif /* WITH_OPENSSL */
static void
_rs_stir(void)
@@ -110,8 +120,8 @@ _rs_stir(void)
#ifdef WITH_OPENSSL
if (RAND_bytes(rnd, sizeof(rnd)) <= 0)
- fatal("Couldn't obtain random bytes (error %ld)",
- ERR_get_error());
+ fatal("Couldn't obtain random bytes (error 0x%lx)",
+ (unsigned long)ERR_get_error());
#else
getrnd(rnd, sizeof(rnd));
#endif
diff --git a/openbsd-compat/base64.h b/openbsd-compat/base64.h
index 732c6b3f..bd772931 100644
--- a/openbsd-compat/base64.h
+++ b/openbsd-compat/base64.h
@@ -1,5 +1,3 @@
-/* $Id: base64.h,v 1.6 2003/08/29 16:59:52 mouring Exp $ */
-
/*
* Copyright (c) 1996 by Internet Software Consortium.
*
@@ -49,7 +47,7 @@
#ifndef HAVE___B64_NTOP
# ifndef HAVE_B64_NTOP
-int b64_ntop(u_char const *src, size_t srclength, char *target,
+int b64_ntop(u_char const *src, size_t srclength, char *target,
size_t targsize);
# endif /* !HAVE_B64_NTOP */
# define __b64_ntop(a,b,c,d) b64_ntop(a,b,c,d)
diff --git a/openbsd-compat/bcrypt_pbkdf.c b/openbsd-compat/bcrypt_pbkdf.c
index 16912575..78523456 100644
--- a/openbsd-compat/bcrypt_pbkdf.c
+++ b/openbsd-compat/bcrypt_pbkdf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcrypt_pbkdf.c,v 1.9 2014/07/13 21:21:25 tedu Exp $ */
+/* $OpenBSD: bcrypt_pbkdf.c,v 1.13 2015/01/12 03:20:04 tedu Exp $ */
/*
* Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
*
@@ -37,6 +37,8 @@
#endif
#define SHA512_DIGEST_LENGTH crypto_hash_sha512_BYTES
+#define MINIMUM(a,b) (((a) < (b)) ? (a) : (b))
+
/*
* pkcs #5 pbkdf2 implementation using the "bcrypt" hash
*
@@ -44,7 +46,7 @@
* function with the following modifications:
* 1. The input password and salt are preprocessed with SHA512.
* 2. The output length is expanded to 256 bits.
- * 3. Subsequently the magic string to be encrypted is lengthened and modifed
+ * 3. Subsequently the magic string to be encrypted is lengthened and modified
* to "OxychromaticBlowfishSwatDynamite"
* 4. The hash function is defined to perform 64 rounds of initial state
* expansion. (More rounds are performed by iterating the hash.)
@@ -61,8 +63,8 @@
* wise caller could do; we just do it for you.
*/
-#define BCRYPT_BLOCKS 8
-#define BCRYPT_HASHSIZE (BCRYPT_BLOCKS * 4)
+#define BCRYPT_WORDS 8
+#define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4)
static void
bcrypt_hash(u_int8_t *sha2pass, u_int8_t *sha2salt, u_int8_t *out)
@@ -70,7 +72,7 @@ bcrypt_hash(u_int8_t *sha2pass, u_int8_t *sha2salt, u_int8_t *out)
blf_ctx state;
u_int8_t ciphertext[BCRYPT_HASHSIZE] =
"OxychromaticBlowfishSwatDynamite";
- uint32_t cdata[BCRYPT_BLOCKS];
+ uint32_t cdata[BCRYPT_WORDS];
int i;
uint16_t j;
size_t shalen = SHA512_DIGEST_LENGTH;
@@ -85,14 +87,14 @@ bcrypt_hash(u_int8_t *sha2pass, u_int8_t *sha2salt, u_int8_t *out)
/* encryption */
j = 0;
- for (i = 0; i < BCRYPT_BLOCKS; i++)
+ for (i = 0; i < BCRYPT_WORDS; i++)
cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
&j);
for (i = 0; i < 64; i++)
blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t));
/* copy out */
- for (i = 0; i < BCRYPT_BLOCKS; i++) {
+ for (i = 0; i < BCRYPT_WORDS; i++) {
out[4 * i + 3] = (cdata[i] >> 24) & 0xff;
out[4 * i + 2] = (cdata[i] >> 16) & 0xff;
out[4 * i + 1] = (cdata[i] >> 8) & 0xff;
@@ -156,9 +158,9 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const u_int8_t *salt, size_t salt
}
/*
- * pbkdf2 deviation: ouput the key material non-linearly.
+ * pbkdf2 deviation: output the key material non-linearly.
*/
- amt = MIN(amt, keylen);
+ amt = MINIMUM(amt, keylen);
for (i = 0; i < amt; i++) {
size_t dest = i * stride + (count - 1);
if (dest >= origkeylen)
diff --git a/openbsd-compat/bindresvport.c b/openbsd-compat/bindresvport.c
index c89f2140..eeb269d5 100644
--- a/openbsd-compat/bindresvport.c
+++ b/openbsd-compat/bindresvport.c
@@ -64,6 +64,7 @@ bindresvport_sa(int sd, struct sockaddr *sa)
if (sa == NULL) {
memset(&myaddr, 0, sizeof(myaddr));
sa = (struct sockaddr *)&myaddr;
+ salen = sizeof(myaddr);
if (getsockname(sd, sa, &salen) == -1)
return -1; /* errno is correctly set */
diff --git a/openbsd-compat/blowfish.c b/openbsd-compat/blowfish.c
index 6c419549..e10f7e7d 100644
--- a/openbsd-compat/blowfish.c
+++ b/openbsd-compat/blowfish.c
@@ -50,7 +50,9 @@
#endif
#include <sys/types.h>
+#ifdef HAVE_BLF_H
#include <blf.h>
+#endif
#undef inline
#ifdef __GNUC__
diff --git a/openbsd-compat/bsd-asprintf.c b/openbsd-compat/bsd-asprintf.c
index 3368195d..10927727 100644
--- a/openbsd-compat/bsd-asprintf.c
+++ b/openbsd-compat/bsd-asprintf.c
@@ -19,24 +19,21 @@
#include "includes.h"
+/*
+ * Don't let systems with broken printf(3) avoid our replacements
+ * via asprintf(3)/vasprintf(3) calling libc internally.
+ */
+#if defined(BROKEN_SNPRINTF)
+# undef HAVE_VASPRINTF
+# undef HAVE_ASPRINTF
+#endif
+
#ifndef HAVE_VASPRINTF
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
-#ifndef VA_COPY
-# ifdef HAVE_VA_COPY
-# define VA_COPY(dest, src) va_copy(dest, src)
-# else
-# ifdef HAVE___VA_COPY
-# define VA_COPY(dest, src) __va_copy(dest, src)
-# else
-# define VA_COPY(dest, src) (dest) = (src)
-# endif
-# endif
-#endif
-
#define INIT_SZ 128
int
@@ -90,7 +87,7 @@ int asprintf(char **str, const char *fmt, ...)
{
va_list ap;
int ret;
-
+
*str = NULL;
va_start(ap, fmt);
ret = vasprintf(str, fmt, ap);
diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c
index 9380b33a..8fadca2d 100644
--- a/openbsd-compat/bsd-closefrom.c
+++ b/openbsd-compat/bsd-closefrom.c
@@ -46,6 +46,9 @@
# include <ndir.h>
# endif
#endif
+#if defined(HAVE_LIBPROC_H)
+# include <libproc.h>
+#endif
#ifndef OPEN_MAX
# define OPEN_MAX 256
@@ -55,21 +58,73 @@
__unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $";
#endif /* lint */
+#ifndef HAVE_FCNTL_CLOSEM
/*
* Close all file descriptors greater than or equal to lowfd.
*/
+static void
+closefrom_fallback(int lowfd)
+{
+ long fd, maxfd;
+
+ /*
+ * Fall back on sysconf() or getdtablesize(). We avoid checking
+ * resource limits since it is possible to open a file descriptor
+ * and then drop the rlimit such that it is below the open fd.
+ */
+#ifdef HAVE_SYSCONF
+ maxfd = sysconf(_SC_OPEN_MAX);
+#else
+ maxfd = getdtablesize();
+#endif /* HAVE_SYSCONF */
+ if (maxfd < 0)
+ maxfd = OPEN_MAX;
+
+ for (fd = lowfd; fd < maxfd; fd++)
+ (void) close((int) fd);
+}
+#endif /* HAVE_FCNTL_CLOSEM */
+
#ifdef HAVE_FCNTL_CLOSEM
void
closefrom(int lowfd)
{
(void) fcntl(lowfd, F_CLOSEM, 0);
}
-#else
+#elif defined(HAVE_LIBPROC_H) && defined(HAVE_PROC_PIDINFO)
void
closefrom(int lowfd)
{
- long fd, maxfd;
-#if defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
+ int i, r, sz;
+ pid_t pid = getpid();
+ struct proc_fdinfo *fdinfo_buf = NULL;
+
+ sz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
+ if (sz == 0)
+ return; /* no fds, really? */
+ else if (sz == -1)
+ goto fallback;
+ if ((fdinfo_buf = malloc(sz)) == NULL)
+ goto fallback;
+ r = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdinfo_buf, sz);
+ if (r < 0 || r > sz)
+ goto fallback;
+ for (i = 0; i < r / (int)PROC_PIDLISTFD_SIZE; i++) {
+ if (fdinfo_buf[i].proc_fd >= lowfd)
+ close(fdinfo_buf[i].proc_fd);
+ }
+ free(fdinfo_buf);
+ return;
+ fallback:
+ free(fdinfo_buf);
+ closefrom_fallback(lowfd);
+ return;
+}
+#elif defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
+void
+closefrom(int lowfd)
+{
+ long fd;
char fdpath[PATH_MAX], *endp;
struct dirent *dent;
DIR *dirp;
@@ -77,7 +132,7 @@ closefrom(int lowfd)
/* Check for a /proc/$$/fd directory. */
len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
- if (len > 0 && (size_t)len <= sizeof(fdpath) && (dirp = opendir(fdpath))) {
+ if (len > 0 && (size_t)len < sizeof(fdpath) && (dirp = opendir(fdpath))) {
while ((dent = readdir(dirp)) != NULL) {
fd = strtol(dent->d_name, &endp, 10);
if (dent->d_name != endp && *endp == '\0' &&
@@ -85,25 +140,16 @@ closefrom(int lowfd)
(void) close((int) fd);
}
(void) closedir(dirp);
- } else
-#endif
- {
- /*
- * Fall back on sysconf() or getdtablesize(). We avoid checking
- * resource limits since it is possible to open a file descriptor
- * and then drop the rlimit such that it is below the open fd.
- */
-#ifdef HAVE_SYSCONF
- maxfd = sysconf(_SC_OPEN_MAX);
-#else
- maxfd = getdtablesize();
-#endif /* HAVE_SYSCONF */
- if (maxfd < 0)
- maxfd = OPEN_MAX;
-
- for (fd = lowfd; fd < maxfd; fd++)
- (void) close((int) fd);
+ return;
}
+ /* /proc/$$/fd strategy failed, fall back to brute force closure */
+ closefrom_fallback(lowfd);
+}
+#else
+void
+closefrom(int lowfd)
+{
+ closefrom_fallback(lowfd);
}
#endif /* !HAVE_FCNTL_CLOSEM */
#endif /* HAVE_CLOSEFROM */
diff --git a/openbsd-compat/bsd-cray.c b/openbsd-compat/bsd-cray.c
deleted file mode 100644
index f1bbd7de..00000000
--- a/openbsd-compat/bsd-cray.c
+++ /dev/null
@@ -1,817 +0,0 @@
-/*
- * $Id: bsd-cray.c,v 1.17 2007/08/15 09:17:43 dtucker Exp $
- *
- * bsd-cray.c
- *
- * Copyright (c) 2002, Cray Inc. (Wendy Palm <wendyp@cray.com>)
- * Significant portions provided by
- * Wayne Schroeder, SDSC <schroeder@sdsc.edu>
- * William Jones, UTexas <jones@tacc.utexas.edu>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Created: Apr 22 16.34:00 2002 wp
- *
- * This file contains functions required for proper execution
- * on UNICOS systems.
- *
- */
-#ifdef _UNICOS
-
-#include <udb.h>
-#include <tmpdir.h>
-#include <unistd.h>
-#include <sys/category.h>
-#include <utmp.h>
-#include <sys/jtab.h>
-#include <signal.h>
-#include <sys/priv.h>
-#include <sys/secparm.h>
-#include <sys/tfm.h>
-#include <sys/usrv.h>
-#include <sys/sysv.h>
-#include <sys/sectab.h>
-#include <sys/secstat.h>
-#include <sys/stat.h>
-#include <sys/session.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <ia.h>
-#include <urm.h>
-#include "ssh.h"
-
-#include "includes.h"
-#include "sys/types.h"
-
-#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
-# define _SS_MAXSIZE 128 /* Implementation specific max size */
-# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr))
-
-# define ss_family ss_sa.sa_family
-#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
-
-#ifndef IN6_IS_ADDR_LOOPBACK
-# define IN6_IS_ADDR_LOOPBACK(a) \
- (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \
- ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1))
-#endif /* !IN6_IS_ADDR_LOOPBACK */
-
-#ifndef AF_INET6
-/* Define it to something that should never appear */
-#define AF_INET6 AF_MAX
-#endif
-
-#include "log.h"
-#include "servconf.h"
-#include "bsd-cray.h"
-
-#define MAXACID 80
-
-extern ServerOptions options;
-
-char cray_tmpdir[TPATHSIZ + 1]; /* job TMPDIR path */
-
-struct sysv sysv; /* system security structure */
-struct usrv usrv; /* user security structure */
-
-/*
- * Functions.
- */
-void cray_retain_utmp(struct utmp *, int);
-void cray_delete_tmpdir(char *, int, uid_t);
-void cray_init_job(struct passwd *);
-void cray_set_tmpdir(struct utmp *);
-void cray_login_failure(char *, int);
-int cray_setup(uid_t, char *, const char *);
-int cray_access_denied(char *);
-
-void
-cray_login_failure(char *username, int errcode)
-{
- struct udb *ueptr; /* UDB pointer for username */
- ia_failure_t fsent; /* ia_failure structure */
- ia_failure_ret_t fret; /* ia_failure return stuff */
- struct jtab jtab; /* job table structure */
- int jid = 0; /* job id */
-
- if ((jid = getjtab(&jtab)) < 0)
- debug("cray_login_failure(): getjtab error");
-
- getsysudb();
- if ((ueptr = getudbnam(username)) == UDB_NULL)
- debug("cray_login_failure(): getudbname() returned NULL");
- endudb();
-
- memset(&fsent, '\0', sizeof(fsent));
- fsent.revision = 0;
- fsent.uname = username;
- fsent.host = (char *)get_canonical_hostname(options.use_dns);
- fsent.ttyn = "sshd";
- fsent.caller = IA_SSHD;
- fsent.flags = IA_INTERACTIVE;
- fsent.ueptr = ueptr;
- fsent.jid = jid;
- fsent.errcode = errcode;
- fsent.pwdp = NULL;
- fsent.exitcode = 0; /* dont exit in ia_failure() */
-
- fret.revision = 0;
- fret.normal = 0;
-
- /*
- * Call ia_failure because of an login failure.
- */
- ia_failure(&fsent, &fret);
-}
-
-/*
- * Cray access denied
- */
-int
-cray_access_denied(char *username)
-{
- struct udb *ueptr; /* UDB pointer for username */
- int errcode; /* IA errorcode */
-
- errcode = 0;
- getsysudb();
- if ((ueptr = getudbnam(username)) == UDB_NULL)
- debug("cray_login_failure(): getudbname() returned NULL");
- endudb();
-
- if (ueptr != NULL && ueptr->ue_disabled)
- errcode = IA_DISABLED;
- if (errcode)
- cray_login_failure(username, errcode);
-
- return (errcode);
-}
-
-/*
- * record_failed_login: generic "login failed" interface function
- */
-void
-record_failed_login(const char *user, const char *hostname, const char *ttyname)
-{
- cray_login_failure((char *)user, IA_UDBERR);
-}
-
-int
-cray_setup (uid_t uid, char *username, const char *command)
-{
- extern struct udb *getudb();
- extern char *setlimits();
-
- int err; /* error return */
- time_t system_time; /* current system clock */
- time_t expiration_time; /* password expiration time */
- int maxattempts; /* maximum no. of failed login attempts */
- int SecureSys; /* unicos security flag */
- int minslevel = 0; /* system minimum security level */
- int i, j;
- int valid_acct = -1; /* flag for reading valid acct */
- char acct_name[MAXACID] = { "" }; /* used to read acct name */
- struct jtab jtab; /* Job table struct */
- struct udb ue; /* udb entry for logging-in user */
- struct udb *up; /* pointer to UDB entry */
- struct secstat secinfo; /* file security attributes */
- struct servprov init_info; /* used for sesscntl() call */
- int jid; /* job ID */
- int pid; /* process ID */
- char *sr; /* status return from setlimits() */
- char *ttyn = NULL; /* ttyname or command name*/
- char hostname[MAXHOSTNAMELEN];
- /* passwd stuff for ia_user */
- passwd_t pwdacm, pwddialup, pwdudb, pwdwal, pwddce;
- ia_user_ret_t uret; /* stuff returned from ia_user */
- ia_user_t usent; /* ia_user main structure */
- int ia_rcode; /* ia_user return code */
- ia_failure_t fsent; /* ia_failure structure */
- ia_failure_ret_t fret; /* ia_failure return stuff */
- ia_success_t ssent; /* ia_success structure */
- ia_success_ret_t sret; /* ia_success return stuff */
- int ia_mlsrcode; /* ia_mlsuser return code */
- int secstatrc; /* [f]secstat return code */
-
- if (SecureSys = (int)sysconf(_SC_CRAY_SECURE_SYS)) {
- getsysv(&sysv, sizeof(struct sysv));
- minslevel = sysv.sy_minlvl;
- if (getusrv(&usrv) < 0)
- fatal("getusrv() failed, errno = %d", errno);
- }
- hostname[0] = '\0';
- strlcpy(hostname,
- (char *)get_canonical_hostname(options.use_dns),
- MAXHOSTNAMELEN);
- /*
- * Fetch user's UDB entry.
- */
- getsysudb();
- if ((up = getudbnam(username)) == UDB_NULL)
- fatal("cannot fetch user's UDB entry");
-
- /*
- * Prevent any possible fudging so perform a data
- * safety check and compare the supplied uid against
- * the udb's uid.
- */
- if (up->ue_uid != uid)
- fatal("IA uid missmatch");
- endudb();
-
- if ((jid = getjtab(&jtab)) < 0) {
- debug("getjtab");
- return(-1);
- }
- pid = getpid();
- ttyn = ttyname(0);
- if (SecureSys) {
- if (ttyn != NULL)
- secstatrc = secstat(ttyn, &secinfo);
- else
- secstatrc = fsecstat(1, &secinfo);
-
- if (secstatrc == 0)
- debug("[f]secstat() successful");
- else
- fatal("[f]secstat() error, rc = %d", secstatrc);
- }
- if ((ttyn == NULL) && ((char *)command != NULL))
- ttyn = (char *)command;
- /*
- * Initialize all structures to call ia_user
- */
- usent.revision = 0;
- usent.uname = username;
- usent.host = hostname;
- usent.ttyn = ttyn;
- usent.caller = IA_SSHD;
- usent.pswdlist = &pwdacm;
- usent.ueptr = &ue;
- usent.flags = IA_INTERACTIVE | IA_FFLAG;
- pwdacm.atype = IA_SECURID;
- pwdacm.pwdp = NULL;
- pwdacm.next = &pwdudb;
-
- pwdudb.atype = IA_UDB;
- pwdudb.pwdp = NULL;
- pwdudb.next = &pwddce;
-
- pwddce.atype = IA_DCE;
- pwddce.pwdp = NULL;
- pwddce.next = &pwddialup;
-
- pwddialup.atype = IA_DIALUP;
- pwddialup.pwdp = NULL;
- /* pwddialup.next = &pwdwal; */
- pwddialup.next = NULL;
-
- pwdwal.atype = IA_WAL;
- pwdwal.pwdp = NULL;
- pwdwal.next = NULL;
-
- uret.revision = 0;
- uret.pswd = NULL;
- uret.normal = 0;
-
- ia_rcode = ia_user(&usent, &uret);
- switch (ia_rcode) {
- /*
- * These are acceptable return codes from ia_user()
- */
- case IA_UDBWEEK: /* Password Expires in 1 week */
- expiration_time = ue.ue_pwage.time + ue.ue_pwage.maxage;
- printf ("WARNING - your current password will expire %s\n",
- ctime((const time_t *)&expiration_time));
- break;
- case IA_UDBEXPIRED:
- if (ttyname(0) != NULL) {
- /* Force a password change */
- printf("Your password has expired; Choose a new one.\n");
- execl("/bin/passwd", "passwd", username, 0);
- exit(9);
- }
- break;
- case IA_NORMAL: /* Normal Return Code */
- break;
- case IA_BACKDOOR:
- /* XXX: can we memset it to zero here so save some of this */
- strlcpy(ue.ue_name, "root", sizeof(ue.ue_name));
- strlcpy(ue.ue_dir, "/", sizeof(ue.ue_dir));
- strlcpy(ue.ue_shell, "/bin/sh", sizeof(ue.ue_shell));
-
- ue.ue_passwd[0] = '\0';
- ue.ue_age[0] = '\0';
- ue.ue_comment[0] = '\0';
- ue.ue_loghost[0] = '\0';
- ue.ue_logline[0] = '\0';
-
- ue.ue_uid = -1;
- ue.ue_nice[UDBRC_INTER] = 0;
-
- for (i = 0; i < MAXVIDS; i++)
- ue.ue_gids[i] = 0;
-
- ue.ue_logfails = 0;
- ue.ue_minlvl = ue.ue_maxlvl = ue.ue_deflvl = minslevel;
- ue.ue_defcomps = 0;
- ue.ue_comparts = 0;
- ue.ue_permits = 0;
- ue.ue_trap = 0;
- ue.ue_disabled = 0;
- ue.ue_logtime = 0;
- break;
- case IA_CONSOLE: /* Superuser not from Console */
- case IA_TRUSTED: /* Trusted user */
- if (options.permit_root_login > PERMIT_NO)
- break; /* Accept root login */
- default:
- /*
- * These are failed return codes from ia_user()
- */
- switch (ia_rcode)
- {
- case IA_BADAUTH:
- printf("Bad authorization, access denied.\n");
- break;
- case IA_DISABLED:
- printf("Your login has been disabled. Contact the system ");
- printf("administrator for assistance.\n");
- break;
- case IA_GETSYSV:
- printf("getsysv() failed - errno = %d\n", errno);
- break;
- case IA_MAXLOGS:
- printf("Maximum number of failed login attempts exceeded.\n");
- printf("Access denied.\n");
- break;
- case IA_UDBPWDNULL:
- if (SecureSys)
- printf("NULL Password not allowed on MLS systems.\n");
- break;
- default:
- break;
- }
-
- /*
- * Authentication failed.
- */
- printf("sshd: Login incorrect, (0%o)\n",
- ia_rcode-IA_ERRORCODE);
-
- /*
- * Initialize structure for ia_failure
- * which will exit.
- */
- fsent.revision = 0;
- fsent.uname = username;
- fsent.host = hostname;
- fsent.ttyn = ttyn;
- fsent.caller = IA_SSHD;
- fsent.flags = IA_INTERACTIVE;
- fsent.ueptr = &ue;
- fsent.jid = jid;
- fsent.errcode = ia_rcode;
- fsent.pwdp = uret.pswd;
- fsent.exitcode = 1;
-
- fret.revision = 0;
- fret.normal = 0;
-
- /*
- * Call ia_failure because of an IA failure.
- * There is no return because ia_failure exits.
- */
- ia_failure(&fsent, &fret);
-
- exit(1);
- }
-
- ia_mlsrcode = IA_NORMAL;
- if (SecureSys) {
- debug("calling ia_mlsuser()");
- ia_mlsrcode = ia_mlsuser(&ue, &secinfo, &usrv, NULL, 0);
- }
- if (ia_mlsrcode != IA_NORMAL) {
- printf("sshd: Login incorrect, (0%o)\n",
- ia_mlsrcode-IA_ERRORCODE);
- /*
- * Initialize structure for ia_failure
- * which will exit.
- */
- fsent.revision = 0;
- fsent.uname = username;
- fsent.host = hostname;
- fsent.ttyn = ttyn;
- fsent.caller = IA_SSHD;
- fsent.flags = IA_INTERACTIVE;
- fsent.ueptr = &ue;
- fsent.jid = jid;
- fsent.errcode = ia_mlsrcode;
- fsent.pwdp = uret.pswd;
- fsent.exitcode = 1;
- fret.revision = 0;
- fret.normal = 0;
-
- /*
- * Call ia_failure because of an IA failure.
- * There is no return because ia_failure exits.
- */
- ia_failure(&fsent,&fret);
- exit(1);
- }
-
- /* Provide login status information */
- if (options.print_lastlog && ue.ue_logtime != 0) {
- printf("Last successful login was : %.*s ", 19,
- (char *)ctime(&ue.ue_logtime));
-
- if (*ue.ue_loghost != '\0') {
- printf("from %.*s\n", sizeof(ue.ue_loghost),
- ue.ue_loghost);
- } else {
- printf("on %.*s\n", sizeof(ue.ue_logline),
- ue.ue_logline);
- }
-
- if (SecureSys && (ue.ue_logfails != 0)) {
- printf(" followed by %d failed attempts\n",
- ue.ue_logfails);
- }
- }
-
- /*
- * Call ia_success to process successful I/A.
- */
- ssent.revision = 0;
- ssent.uname = username;
- ssent.host = hostname;
- ssent.ttyn = ttyn;
- ssent.caller = IA_SSHD;
- ssent.flags = IA_INTERACTIVE;
- ssent.ueptr = &ue;
- ssent.jid = jid;
- ssent.errcode = ia_rcode;
- ssent.us = NULL;
- ssent.time = 1; /* Set ue_logtime */
-
- sret.revision = 0;
- sret.normal = 0;
-
- ia_success(&ssent, &sret);
-
- /*
- * Query for account, iff > 1 valid acid & askacid permbit
- */
- if (((ue.ue_permbits & PERMBITS_ACCTID) ||
- (ue.ue_acids[0] >= 0) && (ue.ue_acids[1] >= 0)) &&
- ue.ue_permbits & PERMBITS_ASKACID) {
- if (ttyname(0) != NULL) {
- debug("cray_setup: ttyname true case, %.100s", ttyname);
- while (valid_acct == -1) {
- printf("Account (? for available accounts)"
- " [%s]: ", acid2nam(ue.ue_acids[0]));
- fgets(acct_name, MAXACID, stdin);
- switch (acct_name[0]) {
- case EOF:
- exit(0);
- break;
- case '\0':
- valid_acct = ue.ue_acids[0];
- strlcpy(acct_name, acid2nam(valid_acct), MAXACID);
- break;
- case '?':
- /* Print the list 3 wide */
- for (i = 0, j = 0; i < MAXVIDS; i++) {
- if (ue.ue_acids[i] == -1) {
- printf("\n");
- break;
- }
- if (++j == 4) {
- j = 1;
- printf("\n");
- }
- printf(" %s",
- acid2nam(ue.ue_acids[i]));
- }
- if (ue.ue_permbits & PERMBITS_ACCTID) {
- printf("\"acctid\" permbit also allows"
- " you to select any valid "
- "account name.\n");
- }
- printf("\n");
- break;
- default:
- valid_acct = nam2acid(acct_name);
- if (valid_acct == -1)
- printf(
- "Account id not found for"
- " account name \"%s\"\n\n",
- acct_name);
- break;
- }
- /*
- * If an account was given, search the user's
- * acids array to verify they can use this account.
- */
- if ((valid_acct != -1) &&
- !(ue.ue_permbits & PERMBITS_ACCTID)) {
- for (i = 0; i < MAXVIDS; i++) {
- if (ue.ue_acids[i] == -1)
- break;
- if (valid_acct == ue.ue_acids[i])
- break;
- }
- if (i == MAXVIDS ||
- ue.ue_acids[i] == -1) {
- fprintf(stderr, "Cannot set"
- " account name to "
- "\"%s\", permission "
- "denied\n\n", acct_name);
- valid_acct = -1;
- }
- }
- }
- } else {
- /*
- * The client isn't connected to a terminal and can't
- * respond to an acid prompt. Use default acid.
- */
- debug("cray_setup: ttyname false case, %.100s",
- ttyname);
- valid_acct = ue.ue_acids[0];
- }
- } else {
- /*
- * The user doesn't have the askacid permbit set or
- * only has one valid account to use.
- */
- valid_acct = ue.ue_acids[0];
- }
- if (acctid(0, valid_acct) < 0) {
- printf ("Bad account id: %d\n", valid_acct);
- exit(1);
- }
-
- /*
- * Now set shares, quotas, limits, including CPU time for the
- * (interactive) job and process, and set up permissions
- * (for chown etc), etc.
- */
- if (setshares(ue.ue_uid, valid_acct, printf, 0, 0)) {
- printf("Unable to give %d shares to <%s>(%d/%d)\n",
- ue.ue_shares, ue.ue_name, ue.ue_uid, valid_acct);
- exit(1);
- }
-
- sr = setlimits(username, C_PROC, pid, UDBRC_INTER);
- if (sr != NULL) {
- debug("%.200s", sr);
- exit(1);
- }
- sr = setlimits(username, C_JOB, jid, UDBRC_INTER);
- if (sr != NULL) {
- debug("%.200s", sr);
- exit(1);
- }
- /*
- * Place the service provider information into
- * the session table (Unicos) or job table (Unicos/mk).
- * There exist double defines for the job/session table in
- * unicos/mk (jtab.h) so no need for a compile time switch.
- */
- memset(&init_info, '\0', sizeof(init_info));
- init_info.s_sessinit.si_id = URM_SPT_LOGIN;
- init_info.s_sessinit.si_pid = getpid();
- init_info.s_sessinit.si_sid = jid;
- sesscntl(0, S_SETSERVPO, (int)&init_info);
-
- /*
- * Set user and controlling tty security attributes.
- */
- if (SecureSys) {
- if (setusrv(&usrv) == -1) {
- debug("setusrv() failed, errno = %d",errno);
- exit(1);
- }
- }
-
- return (0);
-}
-
-/*
- * The rc.* and /etc/sdaemon methods of starting a program on unicos/unicosmk
- * can have pal privileges that sshd can inherit which
- * could allow a user to su to root with out a password.
- * This subroutine clears all privileges.
- */
-void
-drop_cray_privs()
-{
-#if defined(_SC_CRAY_PRIV_SU)
- priv_proc_t *privstate;
- int result;
- extern int priv_set_proc();
- extern priv_proc_t *priv_init_proc();
-
- /*
- * If ether of theses two flags are not set
- * then don't allow this version of ssh to run.
- */
- if (!sysconf(_SC_CRAY_PRIV_SU))
- fatal("Not PRIV_SU system.");
- if (!sysconf(_SC_CRAY_POSIX_PRIV))
- fatal("Not POSIX_PRIV.");
-
- debug("Setting MLS labels.");;
-
- if (sysconf(_SC_CRAY_SECURE_MAC)) {
- usrv.sv_minlvl = SYSLOW;
- usrv.sv_actlvl = SYSHIGH;
- usrv.sv_maxlvl = SYSHIGH;
- } else {
- usrv.sv_minlvl = sysv.sy_minlvl;
- usrv.sv_actlvl = sysv.sy_minlvl;
- usrv.sv_maxlvl = sysv.sy_maxlvl;
- }
- usrv.sv_actcmp = 0;
- usrv.sv_valcmp = sysv.sy_valcmp;
-
- usrv.sv_intcat = TFM_SYSTEM;
- usrv.sv_valcat |= (TFM_SYSTEM | TFM_SYSFILE);
-
- if (setusrv(&usrv) < 0) {
- fatal("%s(%d): setusrv(): %s", __FILE__, __LINE__,
- strerror(errno));
- }
-
- if ((privstate = priv_init_proc()) != NULL) {
- result = priv_set_proc(privstate);
- if (result != 0 ) {
- fatal("%s(%d): priv_set_proc(): %s",
- __FILE__, __LINE__, strerror(errno));
- }
- priv_free_proc(privstate);
- }
- debug ("Privileges should be cleared...");
-#else
- /* XXX: do this differently */
-# error Cray systems must be run with _SC_CRAY_PRIV_SU on!
-#endif
-}
-
-
-/*
- * Retain utmp/wtmp information - used by cray accounting.
- */
-void
-cray_retain_utmp(struct utmp *ut, int pid)
-{
- int fd;
- struct utmp utmp;
-
- if ((fd = open(UTMP_FILE, O_RDONLY)) != -1) {
- /* XXX use atomicio */
- while (read(fd, (char *)&utmp, sizeof(utmp)) == sizeof(utmp)) {
- if (pid == utmp.ut_pid) {
- ut->ut_jid = utmp.ut_jid;
- strncpy(ut->ut_tpath, utmp.ut_tpath, sizeof(utmp.ut_tpath));
- strncpy(ut->ut_host, utmp.ut_host, sizeof(utmp.ut_host));
- strncpy(ut->ut_name, utmp.ut_name, sizeof(utmp.ut_name));
- break;
- }
- }
- close(fd);
- } else
- fatal("Unable to open utmp file");
-}
-
-/*
- * tmpdir support.
- */
-
-/*
- * find and delete jobs tmpdir.
- */
-void
-cray_delete_tmpdir(char *login, int jid, uid_t uid)
-{
- static char jtmp[TPATHSIZ];
- struct stat statbuf;
- int child, c, wstat;
-
- for (c = 'a'; c <= 'z'; c++) {
- snprintf(jtmp, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c);
- if (stat(jtmp, &statbuf) == 0 && statbuf.st_uid == uid)
- break;
- }
-
- if (c > 'z')
- return;
-
- if ((child = fork()) == 0) {
- execl(CLEANTMPCMD, CLEANTMPCMD, login, jtmp, (char *)NULL);
- fatal("cray_delete_tmpdir: execl of CLEANTMPCMD failed");
- }
-
- while (waitpid(child, &wstat, 0) == -1 && errno == EINTR)
- ;
-}
-
-/*
- * Remove tmpdir on job termination.
- */
-void
-cray_job_termination_handler(int sig)
-{
- int jid;
- char *login = NULL;
- struct jtab jtab;
-
- if ((jid = waitjob(&jtab)) == -1 ||
- (login = uid2nam(jtab.j_uid)) == NULL)
- return;
-
- cray_delete_tmpdir(login, jid, jtab.j_uid);
-}
-
-/*
- * Set job id and create tmpdir directory.
- */
-void
-cray_init_job(struct passwd *pw)
-{
- int jid;
- int c;
-
- jid = setjob(pw->pw_uid, WJSIGNAL);
- if (jid < 0)
- fatal("System call setjob failure");
-
- for (c = 'a'; c <= 'z'; c++) {
- snprintf(cray_tmpdir, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c);
- if (mkdir(cray_tmpdir, JTMPMODE) != 0)
- continue;
- if (chown(cray_tmpdir, pw->pw_uid, pw->pw_gid) != 0) {
- rmdir(cray_tmpdir);
- continue;
- }
- break;
- }
-
- if (c > 'z')
- cray_tmpdir[0] = '\0';
-}
-
-void
-cray_set_tmpdir(struct utmp *ut)
-{
- int jid;
- struct jtab jbuf;
-
- if ((jid = getjtab(&jbuf)) < 0)
- return;
-
- /*
- * Set jid and tmpdir in utmp record.
- */
- ut->ut_jid = jid;
- strncpy(ut->ut_tpath, cray_tmpdir, TPATHSIZ);
-}
-#endif /* UNICOS */
-
-#ifdef _UNICOSMP
-#include <pwd.h>
-/*
- * Set job id and create tmpdir directory.
- */
-void
-cray_init_job(struct passwd *pw)
-{
- initrm_silent(pw->pw_uid);
- return;
-}
-#endif /* _UNICOSMP */
diff --git a/openbsd-compat/bsd-cray.h b/openbsd-compat/bsd-cray.h
deleted file mode 100644
index 774eceb5..00000000
--- a/openbsd-compat/bsd-cray.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* $Id: bsd-cray.h,v 1.12 2005/02/02 06:10:11 dtucker Exp $ */
-
-/*
- * Copyright (c) 2002, Cray Inc. (Wendy Palm <wendyp@cray.com>)
- * Significant portions provided by
- * Wayne Schroeder, SDSC <schroeder@sdsc.edu>
- * William Jones, UTexas <jones@tacc.utexas.edu>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Created: Apr 22 16.34:00 2002 wp
- *
- * This file contains functions required for proper execution
- * on UNICOS systems.
- *
- */
-
-#ifndef _BSD_CRAY_H
-#define _BSD_CRAY_H
-
-#ifdef _UNICOS
-
-void cray_init_job(struct passwd *);
-void cray_job_termination_handler(int);
-void cray_login_failure(char *, int );
-int cray_access_denied(char *);
-extern char cray_tmpdir[];
-
-#define CUSTOM_FAILED_LOGIN 1
-
-#ifndef IA_SSHD
-# define IA_SSHD IA_LOGIN
-#endif
-#ifndef MAXHOSTNAMELEN
-# define MAXHOSTNAMELEN 64
-#endif
-#ifndef _CRAYT3E
-# define TIOCGPGRP (tIOC|20)
-#endif
-
-#endif /* UNICOS */
-
-#endif /* _BSD_CRAY_H */
diff --git a/openbsd-compat/bsd-cygwin_util.c b/openbsd-compat/bsd-cygwin_util.c
index a2d82126..54628e26 100644
--- a/openbsd-compat/bsd-cygwin_util.c
+++ b/openbsd-compat/bsd-cygwin_util.c
@@ -36,15 +36,19 @@
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
#include "xmalloc.h"
-int
+int
binary_open(const char *filename, int flags, ...)
{
va_list ap;
mode_t mode;
-
+
va_start(ap, flags);
mode = va_arg(ap, mode_t);
va_end(ap);
@@ -68,7 +72,7 @@ cygwin_ssh_privsep_user()
if (cygwin_internal (CW_CYGNAME_FROM_WINNAME, "sshd", cyg_privsep_user,
sizeof cyg_privsep_user) != 0)
#endif
- strcpy (cyg_privsep_user, "sshd");
+ strlcpy(cyg_privsep_user, "sshd", sizeof(cyg_privsep_user));
}
return cyg_privsep_user;
}
@@ -116,4 +120,150 @@ free_windows_environment(char **p)
free(p);
}
+/*
+ * Returns true if the given string matches the pattern (which may contain ?
+ * and * as wildcards), and zero if it does not match.
+ *
+ * The Cygwin version of this function must be case-insensitive and take
+ * Unicode characters into account.
+ */
+
+static int
+__match_pattern (const wchar_t *s, const wchar_t *pattern)
+{
+ for (;;) {
+ /* If at end of pattern, accept if also at end of string. */
+ if (!*pattern)
+ return !*s;
+
+ if (*pattern == '*') {
+ /* Skip the asterisk. */
+ pattern++;
+
+ /* If at end of pattern, accept immediately. */
+ if (!*pattern)
+ return 1;
+
+ /* If next character in pattern is known, optimize. */
+ if (*pattern != '?' && *pattern != '*') {
+ /*
+ * Look instances of the next character in
+ * pattern, and try to match starting from
+ * those.
+ */
+ for (; *s; s++)
+ if (*s == *pattern &&
+ __match_pattern(s + 1, pattern + 1))
+ return 1;
+ /* Failed. */
+ return 0;
+ }
+ /*
+ * Move ahead one character at a time and try to
+ * match at each position.
+ */
+ for (; *s; s++)
+ if (__match_pattern(s, pattern))
+ return 1;
+ /* Failed. */
+ return 0;
+ }
+ /*
+ * There must be at least one more character in the string.
+ * If we are at the end, fail.
+ */
+ if (!*s)
+ return 0;
+
+ /* Check if the next character of the string is acceptable. */
+ if (*pattern != '?' && towlower(*pattern) != towlower(*s))
+ return 0;
+
+ /* Move to the next character, both in string and in pattern. */
+ s++;
+ pattern++;
+ }
+ /* NOTREACHED */
+}
+
+static int
+_match_pattern(const char *s, const char *pattern)
+{
+ wchar_t *ws;
+ wchar_t *wpattern;
+ size_t len;
+ int ret;
+
+ if ((len = mbstowcs(NULL, s, 0)) < 0)
+ return 0;
+ ws = (wchar_t *) xcalloc(len + 1, sizeof (wchar_t));
+ mbstowcs(ws, s, len + 1);
+ if ((len = mbstowcs(NULL, pattern, 0)) < 0)
+ return 0;
+ wpattern = (wchar_t *) xcalloc(len + 1, sizeof (wchar_t));
+ mbstowcs(wpattern, pattern, len + 1);
+ ret = __match_pattern (ws, wpattern);
+ free(ws);
+ free(wpattern);
+ return ret;
+}
+
+/*
+ * Tries to match the string against the
+ * comma-separated sequence of subpatterns (each possibly preceded by ! to
+ * indicate negation). Returns -1 if negation matches, 1 if there is
+ * a positive match, 0 if there is no match at all.
+ */
+int
+cygwin_ug_match_pattern_list(const char *string, const char *pattern)
+{
+ char sub[1024];
+ int negated;
+ int got_positive;
+ u_int i, subi, len = strlen(pattern);
+
+ got_positive = 0;
+ for (i = 0; i < len;) {
+ /* Check if the subpattern is negated. */
+ if (pattern[i] == '!') {
+ negated = 1;
+ i++;
+ } else
+ negated = 0;
+
+ /*
+ * Extract the subpattern up to a comma or end. Convert the
+ * subpattern to lowercase.
+ */
+ for (subi = 0;
+ i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
+ subi++, i++)
+ sub[subi] = pattern[i];
+ /* If subpattern too long, return failure (no match). */
+ if (subi >= sizeof(sub) - 1)
+ return 0;
+
+ /* If the subpattern was terminated by a comma, then skip it. */
+ if (i < len && pattern[i] == ',')
+ i++;
+
+ /* Null-terminate the subpattern. */
+ sub[subi] = '\0';
+
+ /* Try to match the subpattern against the string. */
+ if (_match_pattern(string, sub)) {
+ if (negated)
+ return -1; /* Negative */
+ else
+ got_positive = 1; /* Positive */
+ }
+ }
+
+ /*
+ * Return success if got a positive match. If there was a negative
+ * match, we have already returned -1 and never get here.
+ */
+ return got_positive;
+}
+
#endif /* HAVE_CYGWIN */
diff --git a/openbsd-compat/bsd-cygwin_util.h b/openbsd-compat/bsd-cygwin_util.h
index 79cb2a19..55c5a5b8 100644
--- a/openbsd-compat/bsd-cygwin_util.h
+++ b/openbsd-compat/bsd-cygwin_util.h
@@ -1,5 +1,3 @@
-/* $Id: bsd-cygwin_util.h,v 1.18 2014/05/27 04:34:43 djm Exp $ */
-
/*
* Copyright (c) 2000, 2001, 2011, 2013 Corinna Vinschen <vinschen@redhat.com>
*
@@ -43,7 +41,7 @@ typedef void *HANDLE;
#define UNLEN 256
/* Cygwin functions for which declarations are only available when including
- windows headers, so we have to define them here explicitely. */
+ windows headers, so we have to define them here explicitly. */
extern HANDLE cygwin_logon_user (const struct passwd *, const char *);
extern void cygwin_set_impersonation_token (const HANDLE);
@@ -57,6 +55,7 @@ int binary_open(const char *, int , ...);
int check_ntsec(const char *);
char **fetch_windows_environment(void);
void free_windows_environment(char **);
+int cygwin_ug_match_pattern_list(const char *, const char *);
#ifndef NO_BINARY_OPEN
#define open binary_open
diff --git a/openbsd-compat/bsd-err.c b/openbsd-compat/bsd-err.c
new file mode 100644
index 00000000..e4ed22b8
--- /dev/null
+++ b/openbsd-compat/bsd-err.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015 Tim Rice <tim@multitalents.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.
+ * 3. 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.
+ */
+
+#include "includes.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef HAVE_ERR
+void
+err(int r, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ fprintf(stderr, "%s: ", strerror(errno));
+ vfprintf(stderr, fmt, args);
+ fputc('\n', stderr);
+ va_end(args);
+ exit(r);
+}
+#endif
+
+#ifndef HAVE_ERRX
+void
+errx(int r, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ fputc('\n', stderr);
+ va_end(args);
+ exit(r);
+}
+#endif
+
+#ifndef HAVE_WARN
+void
+warn(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ fprintf(stderr, "%s: ", strerror(errno));
+ vfprintf(stderr, fmt, args);
+ fputc('\n', stderr);
+ va_end(args);
+}
+#endif
diff --git a/openbsd-compat/bsd-flock.c b/openbsd-compat/bsd-flock.c
new file mode 100644
index 00000000..9b15d1ea
--- /dev/null
+++ b/openbsd-compat/bsd-flock.c
@@ -0,0 +1,81 @@
+/* $NetBSD: flock.c,v 1.6 2008/04/28 20:24:12 martin Exp $ */
+
+/*-
+ * 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.
+ */
+
+/*
+ * Emulate flock() with fcntl(), where available.
+ * Otherwise, don't do locking; just pretend success.
+ */
+
+#include "includes.h"
+
+#ifndef HAVE_FLOCK
+#include <errno.h>
+#include <fcntl.h>
+
+int
+flock(int fd, int op)
+{
+ int rc = 0;
+
+#if defined(F_SETLK) && defined(F_SETLKW)
+ struct flock fl = {0};
+
+ switch (op & (LOCK_EX|LOCK_SH|LOCK_UN)) {
+ case LOCK_EX:
+ fl.l_type = F_WRLCK;
+ break;
+
+ case LOCK_SH:
+ fl.l_type = F_RDLCK;
+ break;
+
+ case LOCK_UN:
+ fl.l_type = F_UNLCK;
+ break;
+
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ fl.l_whence = SEEK_SET;
+ rc = fcntl(fd, op & LOCK_NB ? F_SETLK : F_SETLKW, &fl);
+
+ if (rc && (errno == EAGAIN))
+ errno = EWOULDBLOCK;
+#else
+ rc = -1;
+ errno = ENOSYS;
+#endif
+
+ return rc;
+}
+#endif
diff --git a/openbsd-compat/bsd-getline.c b/openbsd-compat/bsd-getline.c
new file mode 100644
index 00000000..d676f4ce
--- /dev/null
+++ b/openbsd-compat/bsd-getline.c
@@ -0,0 +1,113 @@
+/* $NetBSD: getline.c,v 1.1.1.6 2015/01/02 20:34:27 christos Exp $ */
+
+/* NetBSD: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+
+/* NETBSD ORIGINAL: external/bsd/file/dist/src/getline.c */
+
+#include "includes.h"
+
+#if 0
+#include "file.h"
+#endif
+
+#if !HAVE_GETLINE
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+static ssize_t
+getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
+{
+ char *ptr, *eptr;
+
+
+ if (*buf == NULL || *bufsiz == 0) {
+ if ((*buf = malloc(BUFSIZ)) == NULL)
+ return -1;
+ *bufsiz = BUFSIZ;
+ }
+
+ for (ptr = *buf, eptr = *buf + *bufsiz;;) {
+ int c = fgetc(fp);
+ if (c == -1) {
+ if (feof(fp)) {
+ ssize_t diff = (ssize_t)(ptr - *buf);
+ if (diff != 0) {
+ *ptr = '\0';
+ return diff;
+ }
+ }
+ return -1;
+ }
+ *ptr++ = c;
+ if (c == delimiter) {
+ *ptr = '\0';
+ return ptr - *buf;
+ }
+ if (ptr + 2 >= eptr) {
+ char *nbuf;
+ size_t nbufsiz = *bufsiz * 2;
+ ssize_t d = ptr - *buf;
+ if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
+ return -1;
+ *buf = nbuf;
+ *bufsiz = nbufsiz;
+ eptr = nbuf + nbufsiz;
+ ptr = nbuf + d;
+ }
+ }
+}
+
+ssize_t
+getline(char **buf, size_t *bufsiz, FILE *fp)
+{
+ return getdelim(buf, bufsiz, '\n', fp);
+}
+
+#endif
+
+#ifdef TEST
+int
+main(int argc, char *argv[])
+{
+ char *p = NULL;
+ ssize_t len;
+ size_t n = 0;
+
+ while ((len = getline(&p, &n, stdin)) != -1)
+ (void)printf("%" SIZE_T_FORMAT "d %s", len, p);
+ free(p);
+ return 0;
+}
+#endif
diff --git a/openbsd-compat/bsd-getpagesize.c b/openbsd-compat/bsd-getpagesize.c
new file mode 100644
index 00000000..416a8d4c
--- /dev/null
+++ b/openbsd-compat/bsd-getpagesize.c
@@ -0,0 +1,25 @@
+/* Placed in the public domain */
+
+#include "includes.h"
+
+#ifndef HAVE_GETPAGESIZE
+
+#include <unistd.h>
+#include <limits.h>
+
+int
+getpagesize(void)
+{
+#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
+ long r = sysconf(_SC_PAGESIZE);
+ if (r > 0 && r < INT_MAX)
+ return (int)r;
+#endif
+ /*
+ * This is at the lower end of common values and appropriate for
+ * our current use of getpagesize() in recallocarray().
+ */
+ return 4096;
+}
+
+#endif /* HAVE_GETPAGESIZE */
diff --git a/openbsd-compat/bsd-malloc.c b/openbsd-compat/bsd-malloc.c
new file mode 100644
index 00000000..482facdc
--- /dev/null
+++ b/openbsd-compat/bsd-malloc.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 Darren Tucker (dtucker at zip com au).
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+#undef malloc
+#undef calloc
+#undef realloc
+
+#include <sys/types.h>
+#include <stdlib.h>
+
+#if defined(HAVE_MALLOC) && HAVE_MALLOC == 0
+void *
+rpl_malloc(size_t size)
+{
+ if (size == 0)
+ size = 1;
+ return malloc(size);
+}
+#endif
+
+#if defined(HAVE_CALLOC) && HAVE_CALLOC == 0
+void *
+rpl_calloc(size_t nmemb, size_t size)
+{
+ if (nmemb == 0)
+ nmemb = 1;
+ if (size == 0)
+ size = 1;
+ return calloc(nmemb, size);
+}
+#endif
+
+#if defined (HAVE_REALLOC) && HAVE_REALLOC == 0
+void *
+rpl_realloc(void *ptr, size_t size)
+{
+ if (size == 0)
+ size = 1;
+ if (ptr == 0)
+ return malloc(size);
+ return realloc(ptr, size);
+}
+#endif
diff --git a/openbsd-compat/bsd-misc.c b/openbsd-compat/bsd-misc.c
index f7be415e..059b6d3b 100644
--- a/openbsd-compat/bsd-misc.c
+++ b/openbsd-compat/bsd-misc.c
@@ -25,9 +25,11 @@
# include <sys/time.h>
#endif
+#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
+#include <stdio.h>
#include <time.h>
#include <unistd.h>
@@ -70,8 +72,8 @@ int setlogin(const char *name)
#endif /* !HAVE_SETLOGIN */
#ifndef HAVE_INNETGR
-int innetgr(const char *netgroup, const char *host,
- const char *user, const char *domain)
+int innetgr(const char *netgroup, const char *host,
+ const char *user, const char *domain)
{
return (0);
}
@@ -96,7 +98,7 @@ const char *strerror(int e)
{
extern int sys_nerr;
extern char *sys_errlist[];
-
+
if ((e >= 0) && (e < sys_nerr))
return (sys_errlist[e]);
@@ -111,10 +113,112 @@ int utimes(char *filename, struct timeval *tvp)
ub.actime = tvp[0].tv_sec;
ub.modtime = tvp[1].tv_sec;
-
+
return (utime(filename, &ub));
}
-#endif
+#endif
+
+#ifndef HAVE_UTIMENSAT
+/*
+ * A limited implementation of utimensat() that only implements the
+ * functionality used by OpenSSH, currently only AT_FDCWD and
+ * AT_SYMLINK_NOFOLLOW.
+ */
+int
+utimensat(int fd, const char *path, const struct timespec times[2],
+ int flag)
+{
+ struct timeval tv[2];
+# ifdef HAVE_FUTIMES
+ int ret, oflags = O_WRONLY;
+# endif
+
+ tv[0].tv_sec = times[0].tv_sec;
+ tv[0].tv_usec = times[0].tv_nsec / 1000;
+ tv[1].tv_sec = times[1].tv_sec;
+ tv[1].tv_usec = times[1].tv_nsec / 1000;
+
+ if (fd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+# ifndef HAVE_FUTIMES
+ return utimes(path, tv);
+# else
+# ifdef O_NOFOLLOW
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ oflags |= O_NOFOLLOW;
+# endif /* O_NOFOLLOW */
+ if ((fd = open(path, oflags)) == -1)
+ return -1;
+ ret = futimes(fd, tv);
+ close(fd);
+ return ret;
+# endif
+}
+#endif
+
+#ifndef HAVE_FCHOWNAT
+/*
+ * A limited implementation of fchownat() that only implements the
+ * functionality used by OpenSSH, currently only AT_FDCWD and
+ * AT_SYMLINK_NOFOLLOW.
+ */
+int
+fchownat(int fd, const char *path, uid_t owner, gid_t group, int flag)
+{
+ int ret, oflags = O_WRONLY;
+
+ if (fd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+# ifndef HAVE_FCHOWN
+ return chown(path, owner, group);
+# else
+# ifdef O_NOFOLLOW
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ oflags |= O_NOFOLLOW;
+# endif /* O_NOFOLLOW */
+ if ((fd = open(path, oflags)) == -1)
+ return -1;
+ ret = fchown(fd, owner, group);
+ close(fd);
+ return ret;
+# endif
+}
+#endif
+
+#ifndef HAVE_FCHMODAT
+/*
+ * A limited implementation of fchmodat() that only implements the
+ * functionality used by OpenSSH, currently only AT_FDCWD and
+ * AT_SYMLINK_NOFOLLOW.
+ */
+int
+fchmodat(int fd, const char *path, mode_t mode, int flag)
+{
+ int ret, oflags = O_WRONLY;
+
+ if (fd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+# ifndef HAVE_FCHMOD
+ return chmod(path, mode);
+# else
+# ifdef O_NOFOLLOW
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ oflags |= O_NOFOLLOW;
+# endif /* O_NOFOLLOW */
+ if ((fd = open(path, oflags)) == -1)
+ return -1;
+ ret = fchmod(fd, mode);
+ close(fd);
+ return ret;
+# endif
+}
+#endif
#ifndef HAVE_TRUNCATE
int truncate(const char *path, off_t length)
@@ -149,9 +253,9 @@ int nanosleep(const struct timespec *req, struct timespec *rem)
saverrno = errno;
(void) gettimeofday (&tstop, NULL);
errno = saverrno;
- tremain.tv_sec = time2wait.tv_sec -
+ tremain.tv_sec = time2wait.tv_sec -
(tstop.tv_sec - tstart.tv_sec);
- tremain.tv_usec = time2wait.tv_usec -
+ tremain.tv_usec = time2wait.tv_usec -
(tstop.tv_usec - tstart.tv_usec);
tremain.tv_sec += tremain.tv_usec / 1000000L;
tremain.tv_usec %= 1000000L;
@@ -211,33 +315,6 @@ tcsendbreak(int fd, int duration)
}
#endif /* HAVE_TCSENDBREAK */
-mysig_t
-mysignal(int sig, mysig_t act)
-{
-#ifdef HAVE_SIGACTION
- struct sigaction sa, osa;
-
- if (sigaction(sig, NULL, &osa) == -1)
- return (mysig_t) -1;
- if (osa.sa_handler != act) {
- memset(&sa, 0, sizeof(sa));
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
-#ifdef SA_INTERRUPT
- if (sig == SIGALRM)
- sa.sa_flags |= SA_INTERRUPT;
-#endif
- sa.sa_handler = act;
- if (sigaction(sig, &sa, NULL) == -1)
- return (mysig_t) -1;
- }
- return (osa.sa_handler);
-#else
- #undef signal
- return (signal(sig, act));
-#endif
-}
-
#ifndef HAVE_STRDUP
char *
strdup(const char *str)
@@ -265,7 +342,7 @@ isblank(int c)
pid_t
getpgid(pid_t pid)
{
-#if defined(HAVE_GETPGRP) && !defined(GETPGRP_VOID)
+#if defined(HAVE_GETPGRP) && !defined(GETPGRP_VOID) && GETPGRP_VOID == 0
return getpgrp(pid);
#elif defined(HAVE_GETPGRP)
if (pid == 0)
@@ -276,3 +353,88 @@ getpgid(pid_t pid)
return -1;
}
#endif
+
+#ifndef HAVE_PLEDGE
+int
+pledge(const char *promises, const char *paths[])
+{
+ return 0;
+}
+#endif
+
+#ifndef HAVE_MBTOWC
+/* a mbtowc that only supports ASCII */
+int
+mbtowc(wchar_t *pwc, const char *s, size_t n)
+{
+ if (s == NULL || *s == '\0')
+ return 0; /* ASCII is not state-dependent */
+ if (*s < 0 || *s > 0x7f || n < 1) {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+ if (pwc != NULL)
+ *pwc = *s;
+ return 1;
+}
+#endif
+
+#ifndef HAVE_LLABS
+long long
+llabs(long long j)
+{
+ return (j < 0 ? -j : j);
+}
+#endif
+
+#ifndef HAVE_BZERO
+void
+bzero(void *b, size_t n)
+{
+ (void)memset(b, 0, n);
+}
+#endif
+
+#ifndef HAVE_RAISE
+int
+raise(int sig)
+{
+ kill(getpid(), sig);
+}
+#endif
+
+#ifndef HAVE_GETSID
+pid_t
+getsid(pid_t pid)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+#ifdef FFLUSH_NULL_BUG
+#undef fflush
+int _ssh_compat_fflush(FILE *f)
+{
+ int r1, r2;
+
+ if (f == NULL) {
+ r1 = fflush(stdout);
+ r2 = fflush(stderr);
+ if (r1 == -1 || r2 == -1)
+ return -1;
+ return 0;
+ }
+ return fflush(f);
+}
+#endif
+
+#ifndef HAVE_LOCALTIME_R
+struct tm *
+localtime_r(const time_t *timep, struct tm *result)
+{
+ struct tm *tm = localtime(timep);
+ *result = *tm;
+ return result;
+}
+#endif
diff --git a/openbsd-compat/bsd-misc.h b/openbsd-compat/bsd-misc.h
index 65c18ec2..3a7dd6f4 100644
--- a/openbsd-compat/bsd-misc.h
+++ b/openbsd-compat/bsd-misc.h
@@ -1,5 +1,3 @@
-/* $Id: bsd-misc.h,v 1.25 2013/08/04 11:48:41 dtucker Exp $ */
-
/*
* Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org>
*
@@ -49,7 +47,7 @@ int setegid(uid_t);
#if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR)
const char *strerror(int);
-#endif
+#endif
#if !defined(HAVE_SETLINEBUF)
#define setlinebuf(a) (setvbuf((a), NULL, _IOLBF, 0))
@@ -66,20 +64,43 @@ struct timeval {
int utimes(char *, struct timeval *);
#endif /* HAVE_UTIMES */
+#ifndef AT_FDCWD
+# define AT_FDCWD (-2)
+#endif
+
+#ifndef HAVE_FCHMODAT
+int fchmodat(int, const char *, mode_t, int);
+#endif
+
+#ifndef HAVE_FCHOWNAT
+int fchownat(int, const char *, uid_t, gid_t, int);
+#endif
+
#ifndef HAVE_TRUNCATE
int truncate (const char *, off_t);
#endif /* HAVE_TRUNCATE */
-#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP)
#ifndef HAVE_STRUCT_TIMESPEC
struct timespec {
time_t tv_sec;
long tv_nsec;
};
-#endif
+#endif /* !HAVE_STRUCT_TIMESPEC */
+
+#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP)
+# include <time.h>
int nanosleep(const struct timespec *, struct timespec *);
#endif
+#ifndef HAVE_UTIMENSAT
+# include <time.h>
+/* start with the high bits and work down to minimise risk of overlap */
+# ifndef AT_SYMLINK_NOFOLLOW
+# define AT_SYMLINK_NOFOLLOW 0x80000000
+# endif
+int utimensat(int, const char *, const struct timespec[2], int);
+#endif /* !HAVE_UTIMENSAT */
+
#ifndef HAVE_USLEEP
int usleep(unsigned int useconds);
#endif
@@ -96,12 +117,6 @@ int tcsendbreak(int, int);
int unsetenv(const char *);
#endif
-/* wrapper for signal interface */
-typedef void (*mysig_t)(int);
-mysig_t mysignal(int sig, mysig_t act);
-
-#define signal(a,b) mysignal(a,b)
-
#ifndef HAVE_ISBLANK
int isblank(int);
#endif
@@ -111,7 +126,7 @@ pid_t getpgid(pid_t);
#endif
#ifndef HAVE_ENDGRENT
-# define endgrent() {}
+# define endgrent() do { } while(0)
#endif
#ifndef HAVE_KRB5_GET_ERROR_MESSAGE
@@ -119,7 +134,58 @@ pid_t getpgid(pid_t);
#endif
#ifndef HAVE_KRB5_FREE_ERROR_MESSAGE
-# define krb5_free_error_message(a,b) while(0)
+# define krb5_free_error_message(a,b) do { } while(0)
+#endif
+
+#ifndef HAVE_PLEDGE
+int pledge(const char *promises, const char *paths[]);
+#endif
+
+/* bsd-err.h */
+#ifndef HAVE_ERR
+void err(int, const char *, ...) __attribute__((format(printf, 2, 3)));
+#endif
+#ifndef HAVE_ERRX
+void errx(int, const char *, ...) __attribute__((format(printf, 2, 3)));
+#endif
+#ifndef HAVE_WARN
+void warn(const char *, ...) __attribute__((format(printf, 1, 2)));
+#endif
+
+#ifndef HAVE_LLABS
+long long llabs(long long);
+#endif
+
+#if defined(HAVE_DECL_BZERO) && HAVE_DECL_BZERO == 0
+void bzero(void *, size_t);
+#endif
+
+#ifndef HAVE_RAISE
+int raise(int);
+#endif
+
+#ifndef HAVE_GETSID
+pid_t getsid(pid_t);
+#endif
+
+#ifndef HAVE_FLOCK
+# define LOCK_SH 0x01
+# define LOCK_EX 0x02
+# define LOCK_NB 0x04
+# define LOCK_UN 0x08
+int flock(int, int);
+#endif
+
+#ifdef FFLUSH_NULL_BUG
+# define fflush(x) (_ssh_compat_fflush(x))
+#endif
+
+#ifndef HAVE_LOCALTIME_R
+struct tm *localtime_r(const time_t *, struct tm *);
+#endif
+
+#ifndef HAVE_REALPATH
+#define realpath(x, y) (sftp_realpath((x), (y)))
#endif
#endif /* _BSD_MISC_H */
diff --git a/openbsd-compat/bsd-nextstep.c b/openbsd-compat/bsd-nextstep.c
index 8195af88..d52443f6 100644
--- a/openbsd-compat/bsd-nextstep.c
+++ b/openbsd-compat/bsd-nextstep.c
@@ -29,7 +29,7 @@
#include <sys/wait.h>
#include "bsd-nextstep.h"
-pid_t
+pid_t
posix_wait(int *status)
{
union wait statusp;
diff --git a/openbsd-compat/bsd-nextstep.h b/openbsd-compat/bsd-nextstep.h
index ca5b4b54..4a45b15a 100644
--- a/openbsd-compat/bsd-nextstep.h
+++ b/openbsd-compat/bsd-nextstep.h
@@ -1,5 +1,3 @@
-/* $Id: bsd-nextstep.h,v 1.9 2003/08/29 16:59:52 mouring Exp $ */
-
/*
* Copyright (c) 2000,2001 Ben Lindstrom. All rights reserved.
*
@@ -38,7 +36,7 @@
/* NeXT's readdir() is BSD (struct direct) not POSIX (struct dirent) */
#define dirent direct
-/* Swap out NeXT's BSD wait() for a more POSIX complient one */
+/* Swap out NeXT's BSD wait() for a more POSIX compliant one */
pid_t posix_wait(int *);
#define wait(a) posix_wait(a)
diff --git a/openbsd-compat/bsd-openpty.c b/openbsd-compat/bsd-openpty.c
index 1e0c3333..0b3fc3b2 100644
--- a/openbsd-compat/bsd-openpty.c
+++ b/openbsd-compat/bsd-openpty.c
@@ -65,6 +65,8 @@
#include <string.h>
#include <unistd.h>
+#include "misc.h"
+
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
@@ -97,16 +99,16 @@ openpty(int *amaster, int *aslave, char *name, struct termios *termp,
*/
int ptm;
char *pts;
- mysig_t old_signal;
+ sshsig_t old_signal;
if ((ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1)
return (-1);
/* XXX: need to close ptm on error? */
- old_signal = signal(SIGCHLD, SIG_DFL);
+ old_signal = ssh_signal(SIGCHLD, SIG_DFL);
if (grantpt(ptm) < 0)
return (-1);
- signal(SIGCHLD, old_signal);
+ ssh_signal(SIGCHLD, old_signal);
if (unlockpt(ptm) < 0)
return (-1);
@@ -122,8 +124,17 @@ openpty(int *amaster, int *aslave, char *name, struct termios *termp,
}
#if !defined(ANDROID)
+# if defined(I_FIND) && defined(__SVR4)
+ /*
+ * If the streams modules have already been pushed then there
+ * is no more work to do here.
+ */
+ if (ioctl(*aslave, I_FIND, "ptem") != 0)
+ return 0;
+# endif
+
/*
- * Try to push the appropriate streams modules, as described
+ * Try to push the appropriate streams modules, as described
* in Solaris pts(7).
*/
ioctl(*aslave, I_PUSH, "ptem");
@@ -149,31 +160,6 @@ openpty(int *amaster, int *aslave, char *name, struct termios *termp,
}
return (0);
-#elif defined(_UNICOS)
- char ptbuf[64], ttbuf[64];
- int i;
- int highpty;
-
- highpty = 128;
-#ifdef _SC_CRAY_NPTY
- if ((highpty = sysconf(_SC_CRAY_NPTY)) == -1)
- highpty = 128;
-#endif /* _SC_CRAY_NPTY */
-
- for (i = 0; i < highpty; i++) {
- snprintf(ptbuf, sizeof(ptbuf), "/dev/pty/%03d", i);
- snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%03d", i);
- if ((*amaster = open(ptbuf, O_RDWR|O_NOCTTY)) == -1)
- continue;
- /* Open the slave side. */
- if ((*aslave = open(ttbuf, O_RDWR|O_NOCTTY)) == -1) {
- close(*amaster);
- return (-1);
- }
- return (0);
- }
- return (-1);
-
#else
/* BSD-style pty code. */
char ptbuf[64], ttbuf[64];
@@ -186,7 +172,7 @@ openpty(int *amaster, int *aslave, char *name, struct termios *termp,
struct termios tio;
for (i = 0; i < num_ptys; i++) {
- snprintf(ptbuf, sizeof(ptbuf), "/dev/pty%c%c",
+ snprintf(ptbuf, sizeof(ptbuf), "/dev/pty%c%c",
ptymajors[i / num_minors], ptyminors[i % num_minors]);
snprintf(ttbuf, sizeof(ttbuf), "/dev/tty%c%c",
ptymajors[i / num_minors], ptyminors[i % num_minors]);
diff --git a/openbsd-compat/bsd-poll.c b/openbsd-compat/bsd-poll.c
index 73a85248..c8e6222c 100644
--- a/openbsd-compat/bsd-poll.c
+++ b/openbsd-compat/bsd-poll.c
@@ -1,5 +1,3 @@
-/* $Id: bsd-poll.c,v 1.6 2014/02/05 23:44:13 dtucker Exp $ */
-
/*
* Copyright (c) 2004, 2005, 2007 Darren Tucker (dtucker at zip com au).
*
diff --git a/openbsd-compat/bsd-poll.h b/openbsd-compat/bsd-poll.h
index dcbb9ca4..17945f5b 100644
--- a/openbsd-compat/bsd-poll.h
+++ b/openbsd-compat/bsd-poll.h
@@ -42,11 +42,11 @@ typedef unsigned int nfds_t;
#define POLLIN 0x0001
#define POLLOUT 0x0004
#define POLLERR 0x0008
+#define POLLHUP 0x0010
+#define POLLNVAL 0x0020
#if 0
/* the following are currently not implemented */
#define POLLPRI 0x0002
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
#define POLLRDNORM 0x0040
#define POLLNORM POLLRDNORM
#define POLLWRNORM POLLOUT
diff --git a/openbsd-compat/bsd-setres_id.c b/openbsd-compat/bsd-setres_id.c
index 018bde8c..04752d5a 100644
--- a/openbsd-compat/bsd-setres_id.c
+++ b/openbsd-compat/bsd-setres_id.c
@@ -1,5 +1,3 @@
-/* $Id: bsd-setres_id.c,v 1.2 2013/12/07 21:23:09 djm Exp $ */
-
/*
* Copyright (c) 2012 Darren Tucker (dtucker at zip com au).
*
@@ -39,20 +37,20 @@ setresgid(gid_t rgid, gid_t egid, gid_t sgid)
#if defined(HAVE_SETREGID) && !defined(BROKEN_SETREGID)
if (setregid(rgid, egid) < 0) {
saved_errno = errno;
- error("setregid %u: %.100s", rgid, strerror(errno));
+ error("setregid %lu: %.100s", (u_long)rgid, strerror(errno));
errno = saved_errno;
ret = -1;
}
#else
if (setegid(egid) < 0) {
saved_errno = errno;
- error("setegid %u: %.100s", (u_int)egid, strerror(errno));
+ error("setegid %lu: %.100s", (u_long)egid, strerror(errno));
errno = saved_errno;
ret = -1;
}
if (setgid(rgid) < 0) {
saved_errno = errno;
- error("setgid %u: %.100s", rgid, strerror(errno));
+ error("setgid %lu: %.100s", (u_long)rgid, strerror(errno));
errno = saved_errno;
ret = -1;
}
@@ -74,7 +72,7 @@ setresuid(uid_t ruid, uid_t euid, uid_t suid)
#if defined(HAVE_SETREUID) && !defined(BROKEN_SETREUID)
if (setreuid(ruid, euid) < 0) {
saved_errno = errno;
- error("setreuid %u: %.100s", ruid, strerror(errno));
+ error("setreuid %lu: %.100s", (u_long)ruid, strerror(errno));
errno = saved_errno;
ret = -1;
}
@@ -83,14 +81,14 @@ setresuid(uid_t ruid, uid_t euid, uid_t suid)
# ifndef SETEUID_BREAKS_SETUID
if (seteuid(euid) < 0) {
saved_errno = errno;
- error("seteuid %u: %.100s", euid, strerror(errno));
+ error("seteuid %lu: %.100s", (u_long)euid, strerror(errno));
errno = saved_errno;
ret = -1;
}
# endif
if (setuid(ruid) < 0) {
saved_errno = errno;
- error("setuid %u: %.100s", ruid, strerror(errno));
+ error("setuid %lu: %.100s", (u_long)ruid, strerror(errno));
errno = saved_errno;
ret = -1;
}
diff --git a/openbsd-compat/bsd-setres_id.h b/openbsd-compat/bsd-setres_id.h
index 6c269e0b..0350a596 100644
--- a/openbsd-compat/bsd-setres_id.h
+++ b/openbsd-compat/bsd-setres_id.h
@@ -1,5 +1,3 @@
-/* $Id: bsd-setres_id.h,v 1.1 2012/11/05 06:04:37 dtucker Exp $ */
-
/*
* Copyright (c) 2012 Darren Tucker (dtucker at zip com au).
*
diff --git a/openbsd-compat/bsd-signal.c b/openbsd-compat/bsd-signal.c
new file mode 100644
index 00000000..38d5e972
--- /dev/null
+++ b/openbsd-compat/bsd-signal.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "openbsd-compat/bsd-signal.h"
+
+#if !defined(HAVE_STRSIGNAL)
+char *strsignal(int sig)
+{
+ static char buf[16];
+
+ (void)snprintf(buf, sizeof(buf), "%d", sig);
+ return buf;
+}
+#endif
+
diff --git a/openbsd-compat/bsd-signal.h b/openbsd-compat/bsd-signal.h
new file mode 100644
index 00000000..8d8c4441
--- /dev/null
+++ b/openbsd-compat/bsd-signal.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BSD_SIGNAL_H
+#define _BSD_SIGNAL_H
+
+#include "includes.h"
+
+#include <signal.h>
+
+#ifndef _NSIG
+# ifdef NSIG
+# define _NSIG NSIG
+# else
+# define _NSIG 128
+# endif
+#endif
+
+#if !defined(HAVE_STRSIGNAL)
+char *strsignal(int);
+#endif
+
+#endif /* _BSD_SIGNAL_H */
diff --git a/openbsd-compat/bsd-snprintf.c b/openbsd-compat/bsd-snprintf.c
index 23a63598..f041121f 100644
--- a/openbsd-compat/bsd-snprintf.c
+++ b/openbsd-compat/bsd-snprintf.c
@@ -30,7 +30,7 @@
* probably requires libm on most operating systems. Don't yet
* support the exponent (e,E) and sigfig (g,G). Also, fmtint()
* was pretty badly broken, it just wasn't being exercised in ways
- * which showed it, so that's been fixed. Also, formated the code
+ * which showed it, so that's been fixed. Also, formatted the code
* to mutt conventions, and removed dead code left over from the
* original. Also, there is now a builtin-test, just compile with:
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
@@ -73,7 +73,7 @@
* Fix incorrect zpadlen handling in fmtfp.
* Thanks to Ollie Oldham <ollie.oldham@metro-optix.com> for spotting it.
* few mods to make it easier to compile the tests.
- * addedd the "Ollie" test to the floating point ones.
+ * added the "Ollie" test to the floating point ones.
*
* Martin Pool (mbp@samba.org) April 2003
* Remove NO_CONFIG_H so that the test case can be built within a source
@@ -99,18 +99,6 @@
# undef HAVE_VSNPRINTF
#endif
-#ifndef VA_COPY
-# ifdef HAVE_VA_COPY
-# define VA_COPY(dest, src) va_copy(dest, src)
-# else
-# ifdef HAVE___VA_COPY
-# define VA_COPY(dest, src) __va_copy(dest, src)
-# else
-# define VA_COPY(dest, src) (dest) = (src)
-# endif
-# endif
-#endif
-
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
#include <ctype.h>
diff --git a/openbsd-compat/bsd-statvfs.c b/openbsd-compat/bsd-statvfs.c
index 2d93bfc8..b05ee2b3 100644
--- a/openbsd-compat/bsd-statvfs.c
+++ b/openbsd-compat/bsd-statvfs.c
@@ -1,5 +1,3 @@
-/* $Id: bsd-statvfs.c,v 1.2 2014/01/17 07:10:59 dtucker Exp $ */
-
/*
* Copyright (c) 2008,2014 Darren Tucker <dtucker@zip.com.au>
*
@@ -26,13 +24,21 @@
#endif
#if defined(ANDROID)
-#include <sys/vfs.h>
-#include <string.h>
+#include <sys/param.h>
#define MNAMELEN PATH_MAX
#endif
#include <errno.h>
+#ifndef MNAMELEN
+# define MNAMELEN 32
+#endif
+
+#ifdef HAVE_STRUCT_STATFS_F_FILES
+# define HAVE_STRUCT_STATFS
+#endif
+
+#ifdef HAVE_STRUCT_STATFS
static void
copy_statfs_to_statvfs(struct statvfs *to, struct statfs *from)
{
@@ -45,18 +51,19 @@ copy_statfs_to_statvfs(struct statvfs *to, struct statfs *from)
to->f_ffree = from->f_ffree;
to->f_favail = from->f_ffree; /* no exact equivalent */
to->f_fsid = 0; /* XXX fix me */
-#if GCE_PLATFORM_SDK_VERSION >= 19
+#ifdef HAVE_STRUCT_STATFS_F_FLAGS
to->f_flag = from->f_flags;
#else
- to->f_flag = from->f_spare[0];
+ to->f_flag = 0;
#endif
to->f_namemax = MNAMELEN;
}
+#endif
# ifndef HAVE_STATVFS
int statvfs(const char *path, struct statvfs *buf)
{
-# ifdef HAVE_STATFS
+# if defined(HAVE_STATFS) && defined(HAVE_STRUCT_STATFS)
struct statfs fs;
memset(&fs, 0, sizeof(fs));
@@ -74,7 +81,7 @@ int statvfs(const char *path, struct statvfs *buf)
# ifndef HAVE_FSTATVFS
int fstatvfs(int fd, struct statvfs *buf)
{
-# ifdef HAVE_FSTATFS
+# if defined(HAVE_FSTATFS) && defined(HAVE_STRUCT_STATFS)
struct statfs fs;
memset(&fs, 0, sizeof(fs));
diff --git a/openbsd-compat/bsd-statvfs.h b/openbsd-compat/bsd-statvfs.h
index dfd60997..e2a4c15f 100644
--- a/openbsd-compat/bsd-statvfs.h
+++ b/openbsd-compat/bsd-statvfs.h
@@ -1,5 +1,3 @@
-/* $Id: bsd-statvfs.h,v 1.3 2014/01/17 07:48:22 dtucker Exp $ */
-
/*
* Copyright (c) 2008,2014 Darren Tucker <dtucker@zip.com.au>
*
@@ -28,6 +26,9 @@
#ifdef HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
#ifndef HAVE_FSBLKCNT_T
typedef unsigned long fsblkcnt_t;
diff --git a/openbsd-compat/bsd-waitpid.c b/openbsd-compat/bsd-waitpid.c
index 40e6ffaa..113fb1ea 100644
--- a/openbsd-compat/bsd-waitpid.c
+++ b/openbsd-compat/bsd-waitpid.c
@@ -24,7 +24,7 @@
#include "includes.h"
-#ifndef HAVE_WAITPID
+#ifndef HAVE_WAITPID
#include <errno.h>
#include <sys/wait.h>
#include "bsd-waitpid.h"
@@ -43,11 +43,11 @@ waitpid(int pid, int *stat_loc, int options)
/* wait4() wants pid=0 for indiscriminate wait. */
pid = 0;
}
- wait_pid = wait4(pid, &statusp, options, NULL);
+ wait_pid = wait4(pid, &statusp, options, NULL);
if (stat_loc)
- *stat_loc = (int) statusp.w_status;
+ *stat_loc = (int) statusp.w_status;
- return (wait_pid);
+ return (wait_pid);
}
#endif /* !HAVE_WAITPID */
diff --git a/openbsd-compat/bsd-waitpid.h b/openbsd-compat/bsd-waitpid.h
index 2d853db6..b551268a 100644
--- a/openbsd-compat/bsd-waitpid.h
+++ b/openbsd-compat/bsd-waitpid.h
@@ -1,5 +1,3 @@
-/* $Id: bsd-waitpid.h,v 1.5 2003/08/29 16:59:52 mouring Exp $ */
-
/*
* Copyright (c) 2000 Ben Lindstrom. All rights reserved.
*
@@ -29,7 +27,7 @@
#define _BSD_WAITPID_H
#ifndef HAVE_WAITPID
-/* Clean out any potental issues */
+/* Clean out any potential issues */
#undef WIFEXITED
#undef WIFSTOPPED
#undef WIFSIGNALED
diff --git a/openbsd-compat/explicit_bzero.c b/openbsd-compat/explicit_bzero.c
index 13f87fe3..7a2fa354 100644
--- a/openbsd-compat/explicit_bzero.c
+++ b/openbsd-compat/explicit_bzero.c
@@ -6,6 +6,7 @@
*/
#include "includes.h"
+
#include <string.h>
/*
@@ -19,6 +20,8 @@
void
explicit_bzero(void *p, size_t n)
{
+ if (n == 0)
+ return;
(void)memset_s(p, n, 0, n);
}
@@ -28,12 +31,29 @@ explicit_bzero(void *p, size_t n)
* Indirect bzero through a volatile pointer to hopefully avoid
* dead-store optimisation eliminating the call.
*/
-static void* (* volatile ssh_memset)(void *, int, size_t) = memset;
+#if defined(ANDROID)
+static void (* volatile ssh_bzero)(void *, size_t) = __bionic_bzero;
+#else
+static void (* volatile ssh_bzero)(void *, size_t) = bzero;
+#endif
void
explicit_bzero(void *p, size_t n)
{
- ssh_memset(p, 0, n);
+ if (n == 0)
+ return;
+ /*
+ * clang -fsanitize=memory needs to intercept memset-like functions
+ * to correctly detect memory initialisation. Make sure one is called
+ * directly since our indirection trick above successfully confuses it.
+ */
+#if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+ memset(p, 0, n);
+# endif
+#endif
+
+ ssh_bzero(p, n);
}
#endif /* HAVE_MEMSET_S */
diff --git a/openbsd-compat/fake-rfc2553.c b/openbsd-compat/fake-rfc2553.c
index 096d9e09..d5a62975 100644
--- a/openbsd-compat/fake-rfc2553.c
+++ b/openbsd-compat/fake-rfc2553.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2000-2003 Damien Miller. All rights reserved.
* Copyright (C) 1999 WIDE Project. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -13,7 +13,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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
@@ -44,8 +44,8 @@
#include <arpa/inet.h>
#ifndef HAVE_GETNAMEINFO
-int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
- size_t hostlen, char *serv, size_t servlen, int flags)
+int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
+ size_t hostlen, char *serv, size_t servlen, int flags)
{
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
struct hostent *hp;
@@ -67,11 +67,11 @@ int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
else
return (0);
} else {
- hp = gethostbyaddr((char *)&sin->sin_addr,
+ hp = gethostbyaddr((char *)&sin->sin_addr,
sizeof(struct in_addr), AF_INET);
if (hp == NULL)
return (EAI_NODATA);
-
+
if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
return (EAI_MEMORY);
else
@@ -102,7 +102,7 @@ gai_strerror(int err)
default:
return ("unknown/invalid error.");
}
-}
+}
#endif /* !HAVE_GAI_STRERROR */
#ifndef HAVE_FREEADDRINFO
@@ -128,9 +128,9 @@ addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in));
if (ai == NULL)
return (NULL);
-
+
memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in));
-
+
ai->ai_addr = (struct sockaddr *)(ai + 1);
/* XXX -- ssh doesn't use sa_len */
ai->ai_addrlen = sizeof(struct sockaddr_in);
@@ -138,7 +138,7 @@ addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
-
+
/* XXX: the following is not generally correct, but does what we want */
if (hints->ai_socktype)
ai->ai_socktype = hints->ai_socktype;
@@ -152,7 +152,7 @@ addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
}
int
-getaddrinfo(const char *hostname, const char *servname,
+getaddrinfo(const char *hostname, const char *servname,
const struct addrinfo *hints, struct addrinfo **res)
{
struct hostent *hp;
@@ -183,29 +183,29 @@ getaddrinfo(const char *hostname, const char *servname,
if (hostname && inet_aton(hostname, &in) != 0)
addr = in.s_addr;
*res = malloc_ai(port, addr, hints);
- if (*res == NULL)
+ if (*res == NULL)
return (EAI_MEMORY);
return (0);
}
-
+
if (!hostname) {
*res = malloc_ai(port, htonl(0x7f000001), hints);
- if (*res == NULL)
+ if (*res == NULL)
return (EAI_MEMORY);
return (0);
}
-
+
if (inet_aton(hostname, &in)) {
*res = malloc_ai(port, in.s_addr, hints);
- if (*res == NULL)
+ if (*res == NULL)
return (EAI_MEMORY);
return (0);
}
-
+
/* Don't try DNS if AI_NUMERICHOST is set */
if (hints && hints->ai_flags & AI_NUMERICHOST)
return (EAI_NONAME);
-
+
hp = gethostbyname(hostname);
if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
struct addrinfo *cur, *prev;
@@ -229,7 +229,7 @@ getaddrinfo(const char *hostname, const char *servname,
}
return (0);
}
-
+
return (EAI_NODATA);
}
#endif /* !HAVE_GETADDRINFO */
diff --git a/openbsd-compat/fake-rfc2553.h b/openbsd-compat/fake-rfc2553.h
index 6426f7bf..f913617f 100644
--- a/openbsd-compat/fake-rfc2553.h
+++ b/openbsd-compat/fake-rfc2553.h
@@ -1,9 +1,7 @@
-/* $Id: fake-rfc2553.h,v 1.16 2008/07/14 11:37:37 djm Exp $ */
-
/*
* Copyright (C) 2000-2003 Damien Miller. All rights reserved.
* Copyright (C) 1999 WIDE Project. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -15,7 +13,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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
@@ -47,7 +45,7 @@
#endif
/*
- * First, socket and INET6 related definitions
+ * First, socket and INET6 related definitions
*/
#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
# define _SS_MAXSIZE 128 /* Implementation specific max size */
@@ -154,7 +152,7 @@ struct addrinfo {
# undef getaddrinfo
#endif
#define getaddrinfo(a,b,c,d) (ssh_getaddrinfo(a,b,c,d))
-int getaddrinfo(const char *, const char *,
+int getaddrinfo(const char *, const char *,
const struct addrinfo *, struct addrinfo **);
#endif /* !HAVE_GETADDRINFO */
@@ -170,7 +168,7 @@ void freeaddrinfo(struct addrinfo *);
#ifndef HAVE_GETNAMEINFO
#define getnameinfo(a,b,c,d,e,f,g) (ssh_getnameinfo(a,b,c,d,e,f,g))
-int getnameinfo(const struct sockaddr *, size_t, char *, size_t,
+int getnameinfo(const struct sockaddr *, size_t, char *, size_t,
char *, size_t, int);
#endif /* !HAVE_GETNAMEINFO */
diff --git a/openbsd-compat/fmt_scaled.c b/openbsd-compat/fmt_scaled.c
index edd682a4..2f76ef93 100644
--- a/openbsd-compat/fmt_scaled.c
+++ b/openbsd-compat/fmt_scaled.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fmt_scaled.c,v 1.9 2007/03/20 03:42:52 tedu Exp $ */
+/* $OpenBSD: fmt_scaled.c,v 1.17 2018/05/14 04:39:04 djm Exp $ */
/*
* Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved.
@@ -69,7 +69,7 @@ static long long scale_factors[] = {
#define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */
-/** Convert the given input string "scaled" into numeric in "result".
+/* Convert the given input string "scaled" into numeric in "result".
* Return 0 on success, -1 and errno set on error.
*/
int
@@ -81,7 +81,7 @@ scan_scaled(char *scaled, long long *result)
long long scale_fact = 1, whole = 0, fpart = 0;
/* Skip leading whitespace */
- while (isascii(*p) && isspace(*p))
+ while (isascii((unsigned char)*p) && isspace((unsigned char)*p))
++p;
/* Then at most one leading + or - */
@@ -108,7 +108,8 @@ scan_scaled(char *scaled, long long *result)
* (but note that E for Exa might look like e to some!).
* Advance 'p' to end, to get scale factor.
*/
- for (; isascii(*p) && (isdigit(*p) || *p=='.'); ++p) {
+ for (; isascii((unsigned char)*p) &&
+ (isdigit((unsigned char)*p) || *p=='.'); ++p) {
if (*p == '.') {
if (fract_digits > 0) { /* oops, more than one '.' */
errno = EINVAL;
@@ -124,14 +125,30 @@ scan_scaled(char *scaled, long long *result)
/* ignore extra fractional digits */
continue;
fract_digits++; /* for later scaling */
+ if (fpart > LLONG_MAX / 10) {
+ errno = ERANGE;
+ return -1;
+ }
fpart *= 10;
+ if (i > LLONG_MAX - fpart) {
+ errno = ERANGE;
+ return -1;
+ }
fpart += i;
} else { /* normal digit */
if (++ndigits >= MAX_DIGITS) {
errno = ERANGE;
return -1;
}
+ if (whole > LLONG_MAX / 10) {
+ errno = ERANGE;
+ return -1;
+ }
whole *= 10;
+ if (i > LLONG_MAX - whole) {
+ errno = ERANGE;
+ return -1;
+ }
whole += i;
}
}
@@ -150,21 +167,28 @@ scan_scaled(char *scaled, long long *result)
/* Validate scale factor, and scale whole and fraction by it. */
for (i = 0; i < SCALE_LENGTH; i++) {
- /** Are we there yet? */
+ /* Are we there yet? */
if (*p == scale_chars[i] ||
- *p == tolower(scale_chars[i])) {
+ *p == tolower((unsigned char)scale_chars[i])) {
/* If it ends with alphanumerics after the scale char, bad. */
- if (isalnum(*(p+1))) {
+ if (isalnum((unsigned char)*(p+1))) {
errno = EINVAL;
return -1;
}
scale_fact = scale_factors[i];
+ /* check for overflow and underflow after scaling */
+ if (whole > LLONG_MAX / scale_fact ||
+ whole < LLONG_MIN / scale_fact) {
+ errno = ERANGE;
+ return -1;
+ }
+
/* scale whole part */
whole *= scale_fact;
- /* truncate fpart so it does't overflow.
+ /* truncate fpart so it doesn't overflow.
* then scale fractional part.
*/
while (fpart >= LLONG_MAX / scale_fact) {
@@ -181,7 +205,9 @@ scan_scaled(char *scaled, long long *result)
return 0;
}
}
- errno = ERANGE;
+
+ /* Invalid unit or character */
+ errno = EINVAL;
return -1;
}
@@ -196,7 +222,7 @@ fmt_scaled(long long number, char *result)
unsigned int i;
unit_type unit = NONE;
- abval = (number < 0LL) ? -number : number; /* no long long_abs yet */
+ abval = llabs(number);
/* Not every negative long long has a positive representation.
* Also check for numbers that are just too darned big to format
@@ -220,12 +246,15 @@ fmt_scaled(long long number, char *result)
fract = (10 * fract + 512) / 1024;
/* if the result would be >= 10, round main number */
- if (fract == 10) {
+ if (fract >= 10) {
if (number >= 0)
number++;
else
number--;
fract = 0;
+ } else if (fract < 0) {
+ /* shouldn't happen */
+ fract = 0;
}
if (number == 0)
diff --git a/openbsd-compat/fnmatch.c b/openbsd-compat/fnmatch.c
new file mode 100644
index 00000000..b5641a09
--- /dev/null
+++ b/openbsd-compat/fnmatch.c
@@ -0,0 +1,495 @@
+/* $OpenBSD: fnmatch.c,v 1.22 2020/03/13 03:25:45 djm Exp $ */
+
+/* Copyright (c) 2011, VMware, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the VMware, Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2008, 2016 Todd C. Miller <millert@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.
+ */
+
+/* Authored by William A. Rowe Jr. <wrowe; apache.org, vmware.com>, April 2011
+ *
+ * Derived from The Open Group Base Specifications Issue 7, IEEE Std 1003.1-2008
+ * as described in;
+ * http://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html
+ *
+ * Filename pattern matches defined in section 2.13, "Pattern Matching Notation"
+ * from chapter 2. "Shell Command Language"
+ * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13
+ * where; 1. A bracket expression starting with an unquoted <circumflex> '^'
+ * character CONTINUES to specify a non-matching list; 2. an explicit <period> '.'
+ * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading
+ * <period> in a filename; 3. a <left-square-bracket> '[' which does not introduce
+ * a valid bracket expression is treated as an ordinary character; 4. a differing
+ * number of consecutive slashes within pattern and string will NOT match;
+ * 5. a trailing '\' in FNM_ESCAPE mode is treated as an ordinary '\' character.
+ *
+ * Bracket expansion defined in section 9.3.5, "RE Bracket Expression",
+ * from chapter 9, "Regular Expressions"
+ * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
+ * with no support for collating symbols, equivalence class expressions or
+ * character class expressions. A partial range expression with a leading
+ * hyphen following a valid range expression will match only the ordinary
+ * <hyphen> and the ending character (e.g. "[a-m-z]" will match characters
+ * 'a' through 'm', a <hyphen> '-', or a 'z').
+ *
+ * Supports BSD extensions FNM_LEADING_DIR to match pattern to the end of one
+ * path segment of string, and FNM_CASEFOLD to ignore alpha case.
+ *
+ * NOTE: Only POSIX/C single byte locales are correctly supported at this time.
+ * Notably, non-POSIX locales with FNM_CASEFOLD produce undefined results,
+ * particularly in ranges of mixed case (e.g. "[A-z]") or spanning alpha and
+ * nonalpha characters within a range.
+ *
+ * XXX comments below indicate porting required for multi-byte character sets
+ * and non-POSIX locale collation orders; requires mbr* APIs to track shift
+ * state of pattern and string (rewinding pattern and string repeatedly).
+ *
+ * Certain parts of the code assume 0x00-0x3F are unique with any MBCS (e.g.
+ * UTF-8, SHIFT-JIS, etc). Any implementation allowing '\' as an alternate
+ * path delimiter must be aware that 0x5C is NOT unique within SHIFT-JIS.
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/gen/fnmatch.c */
+
+#include "includes.h"
+#ifndef HAVE_FNMATCH
+
+#include <fnmatch.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "charclass.h"
+
+#define RANGE_MATCH 1
+#define RANGE_NOMATCH 0
+#define RANGE_ERROR (-1)
+
+static int
+classmatch(const char *pattern, char test, int foldcase, const char **ep)
+{
+ const char * const mismatch = pattern;
+ const char *colon;
+ struct cclass *cc;
+ int rval = RANGE_NOMATCH;
+ size_t len;
+
+ if (pattern[0] != '[' || pattern[1] != ':') {
+ *ep = mismatch;
+ return RANGE_ERROR;
+ }
+ pattern += 2;
+
+ if ((colon = strchr(pattern, ':')) == NULL || colon[1] != ']') {
+ *ep = mismatch;
+ return RANGE_ERROR;
+ }
+ *ep = colon + 2;
+ len = (size_t)(colon - pattern);
+
+ if (foldcase && strncmp(pattern, "upper:]", 7) == 0)
+ pattern = "lower:]";
+ for (cc = cclasses; cc->name != NULL; cc++) {
+ if (!strncmp(pattern, cc->name, len) && cc->name[len] == '\0') {
+ if (cc->isctype((unsigned char)test))
+ rval = RANGE_MATCH;
+ break;
+ }
+ }
+ if (cc->name == NULL) {
+ /* invalid character class, treat as normal text */
+ *ep = mismatch;
+ rval = RANGE_ERROR;
+ }
+ return rval;
+}
+
+/* Most MBCS/collation/case issues handled here. Wildcard '*' is not handled.
+ * EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over,
+ * however the "\/" sequence is advanced to '/'.
+ *
+ * Both pattern and string are **char to support pointer increment of arbitrary
+ * multibyte characters for the given locale, in a later iteration of this code
+ */
+static int fnmatch_ch(const char **pattern, const char **string, int flags)
+{
+ const char * const mismatch = *pattern;
+ const int nocase = !!(flags & FNM_CASEFOLD);
+ const int escape = !(flags & FNM_NOESCAPE);
+ const int slash = !!(flags & FNM_PATHNAME);
+ int result = FNM_NOMATCH;
+ const char *startch;
+ int negate;
+
+ if (**pattern == '[') {
+ ++*pattern;
+
+ /* Handle negation, either leading ! or ^ operators */
+ negate = (**pattern == '!') || (**pattern == '^');
+ if (negate)
+ ++*pattern;
+
+ /* ']' is an ordinary char at the start of the range pattern */
+ if (**pattern == ']')
+ goto leadingclosebrace;
+
+ while (**pattern) {
+ if (**pattern == ']') {
+ ++*pattern;
+ /* XXX: Fix for MBCS character width */
+ ++*string;
+ return (result ^ negate);
+ }
+
+ if (escape && (**pattern == '\\')) {
+ ++*pattern;
+
+ /* Patterns must terminate with ']', not EOS */
+ if (!**pattern)
+ break;
+ }
+
+ /* Patterns must terminate with ']' not '/' */
+ if (slash && (**pattern == '/'))
+ break;
+
+ /* Match character classes. */
+ switch (classmatch(*pattern, **string, nocase, pattern)) {
+ case RANGE_MATCH:
+ result = 0;
+ continue;
+ case RANGE_NOMATCH:
+ /* Valid character class but no match. */
+ continue;
+ default:
+ /* Not a valid character class. */
+ break;
+ }
+ if (!**pattern)
+ break;
+
+leadingclosebrace:
+ /* Look at only well-formed range patterns;
+ * "x-]" is not allowed unless escaped ("x-\]")
+ * XXX: Fix for locale/MBCS character width
+ */
+ if (((*pattern)[1] == '-') && ((*pattern)[2] != ']')) {
+ startch = *pattern;
+ *pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2;
+
+ /*
+ * NOT a properly balanced [expr] pattern, EOS
+ * terminated or ranges containing a slash in
+ * FNM_PATHNAME mode pattern fall out to to the
+ * rewind and test '[' literal code path.
+ */
+ if (!**pattern || (slash && (**pattern == '/')))
+ break;
+
+ /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
+ if ((**string >= *startch) && (**string <= **pattern))
+ result = 0;
+ else if (nocase &&
+ (isupper((unsigned char)**string) ||
+ isupper((unsigned char)*startch) ||
+ isupper((unsigned char)**pattern)) &&
+ (tolower((unsigned char)**string) >=
+ tolower((unsigned char)*startch)) &&
+ (tolower((unsigned char)**string) <=
+ tolower((unsigned char)**pattern)))
+ result = 0;
+
+ ++*pattern;
+ continue;
+ }
+
+ /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
+ if ((**string == **pattern))
+ result = 0;
+ else if (nocase && (isupper((unsigned char)**string) ||
+ isupper((unsigned char)**pattern)) &&
+ (tolower((unsigned char)**string) ==
+ tolower((unsigned char)**pattern)))
+ result = 0;
+
+ ++*pattern;
+ }
+ /*
+ * NOT a properly balanced [expr] pattern;
+ * Rewind and reset result to test '[' literal
+ */
+ *pattern = mismatch;
+ result = FNM_NOMATCH;
+ } else if (**pattern == '?') {
+ /* Optimize '?' match before unescaping **pattern */
+ if (!**string || (slash && (**string == '/')))
+ return FNM_NOMATCH;
+ result = 0;
+ goto fnmatch_ch_success;
+ } else if (escape && (**pattern == '\\') && (*pattern)[1]) {
+ ++*pattern;
+ }
+
+ /* XXX: handle locale/MBCS comparison, advance by the MBCS char width */
+ if (**string == **pattern)
+ result = 0;
+ else if (nocase && (isupper((unsigned char)**string) ||
+ isupper((unsigned char)**pattern)) &&
+ (tolower((unsigned char)**string) ==
+ tolower((unsigned char)**pattern)))
+ result = 0;
+
+ /* Refuse to advance over trailing slash or NULs */
+ if (**string == '\0' || **pattern == '\0' ||
+ (slash && ((**string == '/') || (**pattern == '/'))))
+ return result;
+
+fnmatch_ch_success:
+ ++*pattern;
+ ++*string;
+ return result;
+}
+
+
+int fnmatch(const char *pattern, const char *string, int flags)
+{
+ static const char dummystring[2] = {' ', 0};
+ const int escape = !(flags & FNM_NOESCAPE);
+ const int slash = !!(flags & FNM_PATHNAME);
+ const int leading_dir = !!(flags & FNM_LEADING_DIR);
+ const char *dummyptr, *matchptr, *strendseg;
+ int wild;
+ /* For '*' wild processing only; suppress 'used before initialization'
+ * warnings with dummy initialization values;
+ */
+ const char *strstartseg = NULL;
+ const char *mismatch = NULL;
+ int matchlen = 0;
+
+ if (*pattern == '*')
+ goto firstsegment;
+
+ while (*pattern && *string) {
+ /*
+ * Pre-decode "\/" which has no special significance, and
+ * match balanced slashes, starting a new segment pattern.
+ */
+ if (slash && escape && (*pattern == '\\') && (pattern[1] == '/'))
+ ++pattern;
+ if (slash && (*pattern == '/') && (*string == '/')) {
+ ++pattern;
+ ++string;
+ }
+
+firstsegment:
+ /*
+ * At the beginning of each segment, validate leading period
+ * behavior.
+ */
+ if ((flags & FNM_PERIOD) && (*string == '.')) {
+ if (*pattern == '.')
+ ++pattern;
+ else if (escape && (*pattern == '\\') && (pattern[1] == '.'))
+ pattern += 2;
+ else
+ return FNM_NOMATCH;
+ ++string;
+ }
+
+ /*
+ * Determine the end of string segment. Presumes '/'
+ * character is unique, not composite in any MBCS encoding
+ */
+ if (slash) {
+ strendseg = strchr(string, '/');
+ if (!strendseg)
+ strendseg = strchr(string, '\0');
+ } else {
+ strendseg = strchr(string, '\0');
+ }
+
+ /*
+ * Allow pattern '*' to be consumed even with no remaining
+ * string to match.
+ */
+ while (*pattern) {
+ if ((string > strendseg) ||
+ ((string == strendseg) && (*pattern != '*')))
+ break;
+
+ if (slash && ((*pattern == '/') ||
+ (escape && (*pattern == '\\') && (pattern[1] == '/'))))
+ break;
+
+ /*
+ * Reduce groups of '*' and '?' to n '?' matches
+ * followed by one '*' test for simplicity.
+ */
+ for (wild = 0; (*pattern == '*') || (*pattern == '?'); ++pattern) {
+ if (*pattern == '*') {
+ wild = 1;
+ } else if (string < strendseg) { /* && (*pattern == '?') */
+ /* XXX: Advance 1 char for MBCS locale */
+ ++string;
+ }
+ else { /* (string >= strendseg) && (*pattern == '?') */
+ return FNM_NOMATCH;
+ }
+ }
+
+ if (wild) {
+ strstartseg = string;
+ mismatch = pattern;
+
+ /*
+ * Count fixed (non '*') char matches remaining
+ * in pattern * excluding '/' (or "\/") and '*'.
+ */
+ for (matchptr = pattern, matchlen = 0; 1; ++matchlen) {
+ if ((*matchptr == '\0') ||
+ (slash && ((*matchptr == '/') ||
+ (escape && (*matchptr == '\\') &&
+ (matchptr[1] == '/'))))) {
+ /* Compare precisely this many
+ * trailing string chars, the
+ * resulting match needs no
+ * wildcard loop.
+ */
+ /* XXX: Adjust for MBCS */
+ if (string + matchlen > strendseg)
+ return FNM_NOMATCH;
+
+ string = strendseg - matchlen;
+ wild = 0;
+ break;
+ }
+
+ if (*matchptr == '*') {
+ /*
+ * Ensure at least this many
+ * trailing string chars remain
+ * for the first comparison.
+ */
+ /* XXX: Adjust for MBCS */
+ if (string + matchlen > strendseg)
+ return FNM_NOMATCH;
+
+ /*
+ * Begin first wild comparison
+ * at the current position.
+ */
+ break;
+ }
+
+ /*
+ * Skip forward in pattern by a single
+ * character match Use a dummy
+ * fnmatch_ch() test to count one
+ * "[range]" escape.
+ */
+ /* XXX: Adjust for MBCS */
+ if (escape && (*matchptr == '\\') &&
+ matchptr[1]) {
+ matchptr += 2;
+ } else if (*matchptr == '[') {
+ dummyptr = dummystring;
+ fnmatch_ch(&matchptr, &dummyptr,
+ flags);
+ } else {
+ ++matchptr;
+ }
+ }
+ }
+
+ /* Incrementally match string against the pattern. */
+ while (*pattern && (string < strendseg)) {
+ /* Success; begin a new wild pattern search. */
+ if (*pattern == '*')
+ break;
+
+ if (slash && ((*string == '/') ||
+ (*pattern == '/') || (escape &&
+ (*pattern == '\\') && (pattern[1] == '/'))))
+ break;
+
+ /*
+ * Compare ch's (the pattern is advanced over
+ * "\/" to the '/', but slashes will mismatch,
+ * and are not consumed).
+ */
+ if (!fnmatch_ch(&pattern, &string, flags))
+ continue;
+
+ /*
+ * Failed to match, loop against next char
+ * offset of string segment until not enough
+ * string chars remain to match the fixed
+ * pattern.
+ */
+ if (wild) {
+ /* XXX: Advance 1 char for MBCS locale */
+ string = ++strstartseg;
+ if (string + matchlen > strendseg)
+ return FNM_NOMATCH;
+
+ pattern = mismatch;
+ continue;
+ } else
+ return FNM_NOMATCH;
+ }
+ }
+
+ if (*string && !((slash || leading_dir) && (*string == '/')))
+ return FNM_NOMATCH;
+
+ if (*pattern && !(slash && ((*pattern == '/') ||
+ (escape && (*pattern == '\\') && (pattern[1] == '/')))))
+ return FNM_NOMATCH;
+
+ if (leading_dir && !*pattern && *string == '/')
+ return 0;
+ }
+
+ /* Where both pattern and string are at EOS, declare success. */
+ if (!*string && !*pattern)
+ return 0;
+
+ /* Pattern didn't match to the end of string. */
+ return FNM_NOMATCH;
+}
+#endif /* HAVE_FNMATCH */
diff --git a/openbsd-compat/fnmatch.h b/openbsd-compat/fnmatch.h
new file mode 100644
index 00000000..d3bc4a86
--- /dev/null
+++ b/openbsd-compat/fnmatch.h
@@ -0,0 +1,66 @@
+/* $OpenBSD: fnmatch.h,v 1.8 2005/12/13 00:35:22 millert Exp $ */
+/* $NetBSD: fnmatch.h,v 1.5 1994/10/26 00:55:53 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93
+ */
+
+/* OPENBSD ORIGINAL: include/fnmatch.h */
+
+#ifndef HAVE_FNMATCH_H
+/* Ensure we define FNM_CASEFOLD */
+#define __BSD_VISIBLE 1
+
+#ifndef _FNMATCH_H_
+#define _FNMATCH_H_
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+#define FNM_NOMATCH 1 /* Match failed. */
+#define FNM_NOSYS 2 /* Function not supported (unused). */
+
+#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
+#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
+#define FNM_PERIOD 0x04 /* Period must be matched by period. */
+#if __BSD_VISIBLE
+#define FNM_LEADING_DIR 0x08 /* Ignore /<tail> after Imatch. */
+#define FNM_CASEFOLD 0x10 /* Case insensitive search. */
+#define FNM_IGNORECASE FNM_CASEFOLD
+#define FNM_FILE_NAME FNM_PATHNAME
+#endif
+
+/* __BEGIN_DECLS */
+int fnmatch(const char *, const char *, int);
+/* __END_DECLS */
+
+#endif /* !_FNMATCH_H_ */
+#endif /* ! HAVE_FNMATCH_H */
diff --git a/roaming_serv.c b/openbsd-compat/freezero.c
index 511ca846..bad018ff 100644
--- a/roaming_serv.c
+++ b/openbsd-compat/freezero.c
@@ -1,6 +1,5 @@
-/* $OpenBSD: roaming_serv.c,v 1.1 2009/10/24 11:18:23 andreas Exp $ */
/*
- * Copyright (c) 2004-2009 AppGate Network Security AB
+ * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,15 +16,19 @@
#include "includes.h"
-#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
-#include "roaming.h"
+#ifndef HAVE_FREEZERO
-/*
- * Wait for the roaming client to reconnect. Returns 0 if a connect ocurred.
- */
-int
-wait_for_roaming_reconnect(void)
+void
+freezero(void *ptr, size_t sz)
{
- return 1;
+ if (ptr == NULL)
+ return;
+ explicit_bzero(ptr, sz);
+ free(ptr);
}
+
+#endif /* HAVE_FREEZERO */
+
diff --git a/openbsd-compat/getcwd.c b/openbsd-compat/getcwd.c
index 3edbb9cb..e4f7f5a3 100644
--- a/openbsd-compat/getcwd.c
+++ b/openbsd-compat/getcwd.c
@@ -1,4 +1,4 @@
-/* from OpenBSD: getcwd.c,v 1.14 2005/08/08 08:05:34 espie Exp */
+/* $OpenBSD: getcwd.c,v 1.14 2005/08/08 08:05:34 espie Exp */
/*
* Copyright (c) 1989, 1991, 1993
* The Regents of the University of California. All rights reserved.
diff --git a/openbsd-compat/getgrouplist.c b/openbsd-compat/getgrouplist.c
index 3afcb928..3906cd62 100644
--- a/openbsd-compat/getgrouplist.c
+++ b/openbsd-compat/getgrouplist.c
@@ -1,4 +1,4 @@
-/* from OpenBSD: getgrouplist.c,v 1.12 2005/08/08 08:05:34 espie Exp */
+/* $OpenBSD: getgrouplist.c,v 1.12 2005/08/08 08:05:34 espie Exp */
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
diff --git a/openbsd-compat/getrrsetbyname.c b/openbsd-compat/getrrsetbyname.c
index d2bea212..dc6fe053 100644
--- a/openbsd-compat/getrrsetbyname.c
+++ b/openbsd-compat/getrrsetbyname.c
@@ -56,8 +56,6 @@
#include <arpa/inet.h>
#include "getrrsetbyname.h"
-#include "nameser.h"
-#include "nameser_compat.h"
#if defined(HAVE_DECL_H_ERRNO) && !HAVE_DECL_H_ERRNO
extern int h_errno;
diff --git a/openbsd-compat/getrrsetbyname.c.orig b/openbsd-compat/getrrsetbyname.c.orig
deleted file mode 100644
index dc6fe053..00000000
--- a/openbsd-compat/getrrsetbyname.c.orig
+++ /dev/null
@@ -1,610 +0,0 @@
-/* $OpenBSD: getrrsetbyname.c,v 1.11 2007/10/11 18:36:41 jakob Exp $ */
-
-/*
- * Copyright (c) 2001 Jakob Schlyter. 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.
- */
-
-/*
- * Portions Copyright (c) 1999-2001 Internet Software Consortium.
- *
- * 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 INTERNET SOFTWARE CONSORTIUM
- * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
- * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
- * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* OPENBSD ORIGINAL: lib/libc/net/getrrsetbyname.c */
-
-#include "includes.h"
-
-#if !defined (HAVE_GETRRSETBYNAME) && !defined (HAVE_LDNS)
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "getrrsetbyname.h"
-
-#if defined(HAVE_DECL_H_ERRNO) && !HAVE_DECL_H_ERRNO
-extern int h_errno;
-#endif
-
-/* We don't need multithread support here */
-#ifdef _THREAD_PRIVATE
-# undef _THREAD_PRIVATE
-#endif
-#define _THREAD_PRIVATE(a,b,c) (c)
-
-#ifndef HAVE__RES_EXTERN
-struct __res_state _res;
-#endif
-
-/* Necessary functions and macros */
-
-/*
- * Inline versions of get/put short/long. Pointer is advanced.
- *
- * These macros demonstrate the property of C whereby it can be
- * portable or it can be elegant but rarely both.
- */
-
-#ifndef INT32SZ
-# define INT32SZ 4
-#endif
-#ifndef INT16SZ
-# define INT16SZ 2
-#endif
-
-#ifndef GETSHORT
-#define GETSHORT(s, cp) { \
- register u_char *t_cp = (u_char *)(cp); \
- (s) = ((u_int16_t)t_cp[0] << 8) \
- | ((u_int16_t)t_cp[1]) \
- ; \
- (cp) += INT16SZ; \
-}
-#endif
-
-#ifndef GETLONG
-#define GETLONG(l, cp) { \
- register u_char *t_cp = (u_char *)(cp); \
- (l) = ((u_int32_t)t_cp[0] << 24) \
- | ((u_int32_t)t_cp[1] << 16) \
- | ((u_int32_t)t_cp[2] << 8) \
- | ((u_int32_t)t_cp[3]) \
- ; \
- (cp) += INT32SZ; \
-}
-#endif
-
-/*
- * Routines to insert/extract short/long's.
- */
-
-#ifndef HAVE__GETSHORT
-static u_int16_t
-_getshort(msgp)
- register const u_char *msgp;
-{
- register u_int16_t u;
-
- GETSHORT(u, msgp);
- return (u);
-}
-#elif defined(HAVE_DECL__GETSHORT) && (HAVE_DECL__GETSHORT == 0)
-u_int16_t _getshort(register const u_char *);
-#endif
-
-#ifndef HAVE__GETLONG
-static u_int32_t
-_getlong(msgp)
- register const u_char *msgp;
-{
- register u_int32_t u;
-
- GETLONG(u, msgp);
- return (u);
-}
-#elif defined(HAVE_DECL__GETLONG) && (HAVE_DECL__GETLONG == 0)
-u_int32_t _getlong(register const u_char *);
-#endif
-
-/* ************** */
-
-#define ANSWER_BUFFER_SIZE 0xffff
-
-struct dns_query {
- char *name;
- u_int16_t type;
- u_int16_t class;
- struct dns_query *next;
-};
-
-struct dns_rr {
- char *name;
- u_int16_t type;
- u_int16_t class;
- u_int16_t ttl;
- u_int16_t size;
- void *rdata;
- struct dns_rr *next;
-};
-
-struct dns_response {
- HEADER header;
- struct dns_query *query;
- struct dns_rr *answer;
- struct dns_rr *authority;
- struct dns_rr *additional;
-};
-
-static struct dns_response *parse_dns_response(const u_char *, int);
-static struct dns_query *parse_dns_qsection(const u_char *, int,
- const u_char **, int);
-static struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **,
- int);
-
-static void free_dns_query(struct dns_query *);
-static void free_dns_rr(struct dns_rr *);
-static void free_dns_response(struct dns_response *);
-
-static int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t);
-
-int
-getrrsetbyname(const char *hostname, unsigned int rdclass,
- unsigned int rdtype, unsigned int flags,
- struct rrsetinfo **res)
-{
- struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
- int result;
- struct rrsetinfo *rrset = NULL;
- struct dns_response *response = NULL;
- struct dns_rr *rr;
- struct rdatainfo *rdata;
- int length;
- unsigned int index_ans, index_sig;
- u_char answer[ANSWER_BUFFER_SIZE];
-
- /* check for invalid class and type */
- if (rdclass > 0xffff || rdtype > 0xffff) {
- result = ERRSET_INVAL;
- goto fail;
- }
-
- /* don't allow queries of class or type ANY */
- if (rdclass == 0xff || rdtype == 0xff) {
- result = ERRSET_INVAL;
- goto fail;
- }
-
- /* don't allow flags yet, unimplemented */
- if (flags) {
- result = ERRSET_INVAL;
- goto fail;
- }
-
- /* initialize resolver */
- if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
- result = ERRSET_FAIL;
- goto fail;
- }
-
-#ifdef DEBUG
- _resp->options |= RES_DEBUG;
-#endif /* DEBUG */
-
-#ifdef RES_USE_DNSSEC
- /* turn on DNSSEC if EDNS0 is configured */
- if (_resp->options & RES_USE_EDNS0)
- _resp->options |= RES_USE_DNSSEC;
-#endif /* RES_USE_DNSEC */
-
- /* make query */
- length = res_query(hostname, (signed int) rdclass, (signed int) rdtype,
- answer, sizeof(answer));
- if (length < 0) {
- switch(h_errno) {
- case HOST_NOT_FOUND:
- result = ERRSET_NONAME;
- goto fail;
- case NO_DATA:
- result = ERRSET_NODATA;
- goto fail;
- default:
- result = ERRSET_FAIL;
- goto fail;
- }
- }
-
- /* parse result */
- response = parse_dns_response(answer, length);
- if (response == NULL) {
- result = ERRSET_FAIL;
- goto fail;
- }
-
- if (response->header.qdcount != 1) {
- result = ERRSET_FAIL;
- goto fail;
- }
-
- /* initialize rrset */
- rrset = calloc(1, sizeof(struct rrsetinfo));
- if (rrset == NULL) {
- result = ERRSET_NOMEMORY;
- goto fail;
- }
- rrset->rri_rdclass = response->query->class;
- rrset->rri_rdtype = response->query->type;
- rrset->rri_ttl = response->answer->ttl;
- rrset->rri_nrdatas = response->header.ancount;
-
-#ifdef HAVE_HEADER_AD
- /* check for authenticated data */
- if (response->header.ad == 1)
- rrset->rri_flags |= RRSET_VALIDATED;
-#endif
-
- /* copy name from answer section */
- rrset->rri_name = strdup(response->answer->name);
- if (rrset->rri_name == NULL) {
- result = ERRSET_NOMEMORY;
- goto fail;
- }
-
- /* count answers */
- rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
- rrset->rri_rdtype);
- rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
- T_RRSIG);
-
- /* allocate memory for answers */
- rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
- sizeof(struct rdatainfo));
- if (rrset->rri_rdatas == NULL) {
- result = ERRSET_NOMEMORY;
- goto fail;
- }
-
- /* allocate memory for signatures */
- if (rrset->rri_nsigs > 0) {
- rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
- if (rrset->rri_sigs == NULL) {
- result = ERRSET_NOMEMORY;
- goto fail;
- }
- }
-
- /* copy answers & signatures */
- for (rr = response->answer, index_ans = 0, index_sig = 0;
- rr; rr = rr->next) {
-
- rdata = NULL;
-
- if (rr->class == rrset->rri_rdclass &&
- rr->type == rrset->rri_rdtype)
- rdata = &rrset->rri_rdatas[index_ans++];
-
- if (rr->class == rrset->rri_rdclass &&
- rr->type == T_RRSIG)
- rdata = &rrset->rri_sigs[index_sig++];
-
- if (rdata) {
- rdata->rdi_length = rr->size;
- rdata->rdi_data = malloc(rr->size);
-
- if (rdata->rdi_data == NULL) {
- result = ERRSET_NOMEMORY;
- goto fail;
- }
- memcpy(rdata->rdi_data, rr->rdata, rr->size);
- }
- }
- free_dns_response(response);
-
- *res = rrset;
- return (ERRSET_SUCCESS);
-
-fail:
- if (rrset != NULL)
- freerrset(rrset);
- if (response != NULL)
- free_dns_response(response);
- return (result);
-}
-
-void
-freerrset(struct rrsetinfo *rrset)
-{
- u_int16_t i;
-
- if (rrset == NULL)
- return;
-
- if (rrset->rri_rdatas) {
- for (i = 0; i < rrset->rri_nrdatas; i++) {
- if (rrset->rri_rdatas[i].rdi_data == NULL)
- break;
- free(rrset->rri_rdatas[i].rdi_data);
- }
- free(rrset->rri_rdatas);
- }
-
- if (rrset->rri_sigs) {
- for (i = 0; i < rrset->rri_nsigs; i++) {
- if (rrset->rri_sigs[i].rdi_data == NULL)
- break;
- free(rrset->rri_sigs[i].rdi_data);
- }
- free(rrset->rri_sigs);
- }
-
- if (rrset->rri_name)
- free(rrset->rri_name);
- free(rrset);
-}
-
-/*
- * DNS response parsing routines
- */
-static struct dns_response *
-parse_dns_response(const u_char *answer, int size)
-{
- struct dns_response *resp;
- const u_char *cp;
-
- /* allocate memory for the response */
- resp = calloc(1, sizeof(*resp));
- if (resp == NULL)
- return (NULL);
-
- /* initialize current pointer */
- cp = answer;
-
- /* copy header */
- memcpy(&resp->header, cp, HFIXEDSZ);
- cp += HFIXEDSZ;
-
- /* fix header byte order */
- resp->header.qdcount = ntohs(resp->header.qdcount);
- resp->header.ancount = ntohs(resp->header.ancount);
- resp->header.nscount = ntohs(resp->header.nscount);
- resp->header.arcount = ntohs(resp->header.arcount);
-
- /* there must be at least one query */
- if (resp->header.qdcount < 1) {
- free_dns_response(resp);
- return (NULL);
- }
-
- /* parse query section */
- resp->query = parse_dns_qsection(answer, size, &cp,
- resp->header.qdcount);
- if (resp->header.qdcount && resp->query == NULL) {
- free_dns_response(resp);
- return (NULL);
- }
-
- /* parse answer section */
- resp->answer = parse_dns_rrsection(answer, size, &cp,
- resp->header.ancount);
- if (resp->header.ancount && resp->answer == NULL) {
- free_dns_response(resp);
- return (NULL);
- }
-
- /* parse authority section */
- resp->authority = parse_dns_rrsection(answer, size, &cp,
- resp->header.nscount);
- if (resp->header.nscount && resp->authority == NULL) {
- free_dns_response(resp);
- return (NULL);
- }
-
- /* parse additional section */
- resp->additional = parse_dns_rrsection(answer, size, &cp,
- resp->header.arcount);
- if (resp->header.arcount && resp->additional == NULL) {
- free_dns_response(resp);
- return (NULL);
- }
-
- return (resp);
-}
-
-static struct dns_query *
-parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
-{
- struct dns_query *head, *curr, *prev;
- int i, length;
- char name[MAXDNAME];
-
- for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
-
- /* allocate and initialize struct */
- curr = calloc(1, sizeof(struct dns_query));
- if (curr == NULL) {
- free_dns_query(head);
- return (NULL);
- }
- if (head == NULL)
- head = curr;
- if (prev != NULL)
- prev->next = curr;
-
- /* name */
- length = dn_expand(answer, answer + size, *cp, name,
- sizeof(name));
- if (length < 0) {
- free_dns_query(head);
- return (NULL);
- }
- curr->name = strdup(name);
- if (curr->name == NULL) {
- free_dns_query(head);
- return (NULL);
- }
- *cp += length;
-
- /* type */
- curr->type = _getshort(*cp);
- *cp += INT16SZ;
-
- /* class */
- curr->class = _getshort(*cp);
- *cp += INT16SZ;
- }
-
- return (head);
-}
-
-static struct dns_rr *
-parse_dns_rrsection(const u_char *answer, int size, const u_char **cp,
- int count)
-{
- struct dns_rr *head, *curr, *prev;
- int i, length;
- char name[MAXDNAME];
-
- for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
-
- /* allocate and initialize struct */
- curr = calloc(1, sizeof(struct dns_rr));
- if (curr == NULL) {
- free_dns_rr(head);
- return (NULL);
- }
- if (head == NULL)
- head = curr;
- if (prev != NULL)
- prev->next = curr;
-
- /* name */
- length = dn_expand(answer, answer + size, *cp, name,
- sizeof(name));
- if (length < 0) {
- free_dns_rr(head);
- return (NULL);
- }
- curr->name = strdup(name);
- if (curr->name == NULL) {
- free_dns_rr(head);
- return (NULL);
- }
- *cp += length;
-
- /* type */
- curr->type = _getshort(*cp);
- *cp += INT16SZ;
-
- /* class */
- curr->class = _getshort(*cp);
- *cp += INT16SZ;
-
- /* ttl */
- curr->ttl = _getlong(*cp);
- *cp += INT32SZ;
-
- /* rdata size */
- curr->size = _getshort(*cp);
- *cp += INT16SZ;
-
- /* rdata itself */
- curr->rdata = malloc(curr->size);
- if (curr->rdata == NULL) {
- free_dns_rr(head);
- return (NULL);
- }
- memcpy(curr->rdata, *cp, curr->size);
- *cp += curr->size;
- }
-
- return (head);
-}
-
-static void
-free_dns_query(struct dns_query *p)
-{
- if (p == NULL)
- return;
-
- if (p->name)
- free(p->name);
- free_dns_query(p->next);
- free(p);
-}
-
-static void
-free_dns_rr(struct dns_rr *p)
-{
- if (p == NULL)
- return;
-
- if (p->name)
- free(p->name);
- if (p->rdata)
- free(p->rdata);
- free_dns_rr(p->next);
- free(p);
-}
-
-static void
-free_dns_response(struct dns_response *p)
-{
- if (p == NULL)
- return;
-
- free_dns_query(p->query);
- free_dns_rr(p->answer);
- free_dns_rr(p->authority);
- free_dns_rr(p->additional);
- free(p);
-}
-
-static int
-count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
-{
- int n = 0;
-
- while(p) {
- if (p->class == class && p->type == type)
- n++;
- p = p->next;
- }
-
- return (n);
-}
-
-#endif /* !defined (HAVE_GETRRSETBYNAME) && !defined (HAVE_LDNS) */
diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c
index 742b4b95..e8915178 100644
--- a/openbsd-compat/glob.c
+++ b/openbsd-compat/glob.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: glob.c,v 1.38 2011/09/22 06:27:29 djm Exp $ */
+/* $OpenBSD: glob.c,v 1.49 2020/04/21 08:25:22 dtucker Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -59,6 +59,7 @@
*/
#include "includes.h"
+#include "glob.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -69,6 +70,9 @@
#include <limits.h>
#include <pwd.h>
#include <stdlib.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
#include <string.h>
#include <unistd.h>
@@ -79,6 +83,10 @@
#include "charclass.h"
+#ifdef TILDE
+# undef TILDE
+#endif
+
#define DOLLAR '$'
#define DOT '.'
#define EOS '\0'
@@ -130,12 +138,9 @@ typedef char Char;
#define ismeta(c) (((c)&M_QUOTE) != 0)
#define GLOB_LIMIT_MALLOC 65536
-#define GLOB_LIMIT_STAT 128
+#define GLOB_LIMIT_STAT 2048
#define GLOB_LIMIT_READDIR 16384
-/* Limit of recursion during matching attempts. */
-#define GLOB_LIMIT_RECUR 64
-
struct glob_lim {
size_t glim_malloc;
size_t glim_stat;
@@ -149,7 +154,7 @@ struct glob_path_stat {
static int compare(const void *, const void *);
static int compare_gps(const void *, const void *);
-static int g_Ctoc(const Char *, char *, u_int);
+static int g_Ctoc(const Char *, char *, size_t);
static int g_lstat(Char *, struct stat *, glob_t *);
static DIR *g_opendir(Char *, glob_t *);
static Char *g_strchr(const Char *, int);
@@ -168,7 +173,7 @@ static const Char *
static int globexp1(const Char *, glob_t *, struct glob_lim *);
static int globexp2(const Char *, const Char *, glob_t *,
struct glob_lim *);
-static int match(Char *, Char *, Char *, int);
+static int match(Char *, Char *, Char *);
#ifdef DEBUG
static void qprintf(const char *, Char *);
#endif
@@ -179,12 +184,9 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
{
const u_char *patnext;
int c;
- Char *bufnext, *bufend, patbuf[MAXPATHLEN];
+ Char *bufnext, *bufend, patbuf[PATH_MAX];
struct glob_lim limit = { 0, 0, 0 };
- if (strnlen(pattern, PATH_MAX) == PATH_MAX)
- return(GLOB_NOMATCH);
-
patnext = (u_char *) pattern;
if (!(flags & GLOB_APPEND)) {
pglob->gl_pathc = 0;
@@ -197,13 +199,15 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
pglob->gl_errfunc = errfunc;
pglob->gl_matchc = 0;
- if (pglob->gl_offs < 0 || pglob->gl_pathc < 0 ||
- pglob->gl_offs >= INT_MAX || pglob->gl_pathc >= INT_MAX ||
- pglob->gl_pathc >= INT_MAX - pglob->gl_offs - 1)
+ if (strnlen(pattern, PATH_MAX) == PATH_MAX)
+ return(GLOB_NOMATCH);
+
+ if (pglob->gl_offs >= SSIZE_MAX || pglob->gl_pathc >= SSIZE_MAX ||
+ pglob->gl_pathc >= SSIZE_MAX - pglob->gl_offs - 1)
return GLOB_NOSPACE;
bufnext = patbuf;
- bufend = bufnext + MAXPATHLEN - 1;
+ bufend = bufnext + PATH_MAX - 1;
if (flags & GLOB_NOESCAPE)
while (bufnext < bufend && (c = *patnext++) != EOS)
*bufnext++ = c;
@@ -260,7 +264,7 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob,
int i, rv;
Char *lm, *ls;
const Char *pe, *pm, *pl;
- Char patbuf[MAXPATHLEN];
+ Char patbuf[PATH_MAX];
/* copy part up to the brace */
for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
@@ -471,10 +475,11 @@ static int
glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
{
const Char *qpatnext;
- int c, err, oldpathc;
- Char *bufnext, patbuf[MAXPATHLEN];
+ int c, err;
+ size_t oldpathc;
+ Char *bufnext, patbuf[PATH_MAX];
- qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
+ qpatnext = globtilde(pattern, patbuf, PATH_MAX, pglob);
oldpathc = pglob->gl_pathc;
bufnext = patbuf;
@@ -544,7 +549,7 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
qprintf("glob0:", patbuf);
#endif
- if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp)) != 0)
+ if ((err = glob1(patbuf, patbuf+PATH_MAX-1, pglob, limitp)) != 0)
return(err);
/*
@@ -565,9 +570,9 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
if ((pglob->gl_flags & GLOB_KEEPSTAT)) {
/* Keep the paths and stat info synced during sort */
struct glob_path_stat *path_stat;
- int i;
- int n = pglob->gl_pathc - oldpathc;
- int o = pglob->gl_offs + oldpathc;
+ size_t i;
+ size_t n = pglob->gl_pathc - oldpathc;
+ size_t o = pglob->gl_offs + oldpathc;
if ((path_stat = calloc(n, sizeof(*path_stat))) == NULL)
return GLOB_NOSPACE;
@@ -608,13 +613,13 @@ compare_gps(const void *_p, const void *_q)
static int
glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp)
{
- Char pathbuf[MAXPATHLEN];
+ Char pathbuf[PATH_MAX];
/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
if (*pattern == EOS)
return(0);
- return(glob2(pathbuf, pathbuf+MAXPATHLEN-1,
- pathbuf, pathbuf+MAXPATHLEN-1,
+ return(glob2(pathbuf, pathbuf+PATH_MAX-1,
+ pathbuf, pathbuf+PATH_MAX-1,
pattern, pattern_last, pglob, limitp));
}
@@ -638,8 +643,6 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
for (anymeta = 0;;) {
if (*pattern == EOS) { /* End of pattern? */
*pathend = EOS;
- if (g_lstat(pathbuf, &sb, pglob))
- return(0);
if ((pglob->gl_flags & GLOB_LIMIT) &&
limitp->glim_stat++ >= GLOB_LIMIT_STAT) {
@@ -648,6 +651,8 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
*pathend = EOS;
return(GLOB_NOSPACE);
}
+ if (g_lstat(pathbuf, &sb, pglob))
+ return(0);
if (((pglob->gl_flags & GLOB_MARK) &&
pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
@@ -699,7 +704,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
struct dirent *dp;
DIR *dirp;
int err;
- char buf[MAXPATHLEN];
+ char buf[PATH_MAX];
/*
* The readdirfunc declaration can't be prototyped, because it is
@@ -759,7 +764,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
break;
}
- if (!match(pathend, pattern, restpattern, GLOB_LIMIT_RECUR)) {
+ if (!match(pathend, pattern, restpattern)) {
*pathend = EOS;
continue;
}
@@ -796,56 +801,51 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp,
struct stat *sb)
{
char **pathv;
- ssize_t i;
- size_t newn, len;
+ size_t i, newn, len;
char *copy = NULL;
const Char *p;
struct stat **statv;
newn = 2 + pglob->gl_pathc + pglob->gl_offs;
- if (pglob->gl_offs >= INT_MAX ||
- pglob->gl_pathc >= INT_MAX ||
- newn >= INT_MAX ||
+ if (pglob->gl_offs >= SSIZE_MAX ||
+ pglob->gl_pathc >= SSIZE_MAX ||
+ newn >= SSIZE_MAX ||
SIZE_MAX / sizeof(*pathv) <= newn ||
SIZE_MAX / sizeof(*statv) <= newn) {
nospace:
- for (i = pglob->gl_offs; i < (ssize_t)(newn - 2); i++) {
+ for (i = pglob->gl_offs; i < newn - 2; i++) {
if (pglob->gl_pathv && pglob->gl_pathv[i])
free(pglob->gl_pathv[i]);
if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 &&
pglob->gl_pathv && pglob->gl_pathv[i])
free(pglob->gl_statv[i]);
}
- if (pglob->gl_pathv) {
- free(pglob->gl_pathv);
- pglob->gl_pathv = NULL;
- }
- if (pglob->gl_statv) {
- free(pglob->gl_statv);
- pglob->gl_statv = NULL;
- }
+ free(pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ free(pglob->gl_statv);
+ pglob->gl_statv = NULL;
return(GLOB_NOSPACE);
}
- pathv = realloc(pglob->gl_pathv, newn * sizeof(*pathv));
+ pathv = reallocarray(pglob->gl_pathv, newn, sizeof(*pathv));
if (pathv == NULL)
goto nospace;
if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
/* first time around -- clear initial gl_offs items */
pathv += pglob->gl_offs;
- for (i = pglob->gl_offs; --i >= 0; )
+ for (i = pglob->gl_offs; i > 0; i--)
*--pathv = NULL;
}
pglob->gl_pathv = pathv;
if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) {
- statv = realloc(pglob->gl_statv, newn * sizeof(*statv));
+ statv = reallocarray(pglob->gl_statv, newn, sizeof(*statv));
if (statv == NULL)
goto nospace;
if (pglob->gl_statv == NULL && pglob->gl_offs > 0) {
/* first time around -- clear initial gl_offs items */
statv += pglob->gl_offs;
- for (i = pglob->gl_offs; --i >= 0; )
+ for (i = pglob->gl_offs; i > 0; i--)
*--statv = NULL;
}
pglob->gl_statv = statv;
@@ -893,17 +893,24 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp,
/*
* pattern matching function for filenames. Each occurrence of the *
- * pattern causes a recursion level.
+ * pattern causes an iteration.
+ *
+ * Note, this function differs from the original as per the discussion
+ * here: https://research.swtch.com/glob
+ *
+ * Basically we removed the recursion and made it use the algorithm
+ * from Russ Cox to not go quadratic on cases like a file called
+ * ("a" x 100) . "x" matched against a pattern like "a*a*a*a*a*a*a*y".
*/
static int
-match(Char *name, Char *pat, Char *patend, int recur)
+match(Char *name, Char *pat, Char *patend)
{
int ok, negate_range;
Char c, k;
+ Char *nextp = NULL;
+ Char *nextn = NULL;
- if (recur-- == 0)
- return(GLOB_NOSPACE);
-
+loop:
while (pat < patend) {
c = *pat++;
switch (c & M_MASK) {
@@ -912,19 +919,19 @@ match(Char *name, Char *pat, Char *patend, int recur)
pat++; /* eat consecutive '*' */
if (pat == patend)
return(1);
- do {
- if (match(name, pat, patend, recur))
- return(1);
- } while (*name++ != EOS);
- return(0);
+ if (*name == EOS)
+ return(0);
+ nextn = name + 1;
+ nextp = pat - 1;
+ break;
case M_ONE:
if (*name++ == EOS)
- return(0);
+ goto fail;
break;
case M_SET:
ok = 0;
if ((k = *name++) == EOS)
- return(0);
+ goto fail;
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
++pat;
while (((c = *pat++) & M_MASK) != M_END) {
@@ -943,36 +950,43 @@ match(Char *name, Char *pat, Char *patend, int recur)
ok = 1;
}
if (ok == negate_range)
- return(0);
+ goto fail;
break;
default:
if (*name++ != c)
- return(0);
+ goto fail;
break;
}
}
- return(*name == EOS);
+ if (*name == EOS)
+ return(1);
+
+fail:
+ if (nextn) {
+ pat = nextp;
+ name = nextn;
+ goto loop;
+ }
+ return(0);
}
/* Free allocated data belonging to a glob_t structure. */
void
globfree(glob_t *pglob)
{
- int i;
+ size_t i;
char **pp;
if (pglob->gl_pathv != NULL) {
pp = pglob->gl_pathv + pglob->gl_offs;
for (i = pglob->gl_pathc; i--; ++pp)
- if (*pp)
- free(*pp);
+ free(*pp);
free(pglob->gl_pathv);
pglob->gl_pathv = NULL;
}
if (pglob->gl_statv != NULL) {
for (i = 0; i < pglob->gl_pathc; i++) {
- if (pglob->gl_statv[i] != NULL)
- free(pglob->gl_statv[i]);
+ free(pglob->gl_statv[i]);
}
free(pglob->gl_statv);
pglob->gl_statv = NULL;
@@ -982,7 +996,7 @@ globfree(glob_t *pglob)
static DIR *
g_opendir(Char *str, glob_t *pglob)
{
- char buf[MAXPATHLEN];
+ char buf[PATH_MAX];
if (!*str)
strlcpy(buf, ".", sizeof buf);
@@ -1000,7 +1014,7 @@ g_opendir(Char *str, glob_t *pglob)
static int
g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
{
- char buf[MAXPATHLEN];
+ char buf[PATH_MAX];
if (g_Ctoc(fn, buf, sizeof(buf)))
return(-1);
@@ -1012,7 +1026,7 @@ g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
static int
g_stat(Char *fn, struct stat *sb, glob_t *pglob)
{
- char buf[MAXPATHLEN];
+ char buf[PATH_MAX];
if (g_Ctoc(fn, buf, sizeof(buf)))
return(-1);
@@ -1032,7 +1046,7 @@ g_strchr(const Char *str, int ch)
}
static int
-g_Ctoc(const Char *str, char *buf, u_int len)
+g_Ctoc(const Char *str, char *buf, size_t len)
{
while (len--) {
diff --git a/openbsd-compat/glob.h b/openbsd-compat/glob.h
index f8a7fa5f..1692d36c 100644
--- a/openbsd-compat/glob.h
+++ b/openbsd-compat/glob.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: glob.h,v 1.11 2010/09/24 13:32:55 djm Exp $ */
+/* $OpenBSD: glob.h,v 1.14 2019/02/04 16:45:40 millert Exp $ */
/* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */
/*
@@ -42,16 +42,21 @@
!defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \
defined(BROKEN_GLOB)
-#ifndef _GLOB_H_
-#define _GLOB_H_
+#ifndef _COMPAT_GLOB_H_
+#define _COMPAT_GLOB_H_
#include <sys/stat.h>
+#include <sys/types.h>
+
+# define glob_t _ssh_compat_glob_t
+# define glob(a, b, c, d) _ssh__compat_glob(a, b, c, d)
+# define globfree(a) _ssh__compat_globfree(a)
struct stat;
typedef struct {
- int gl_pathc; /* Count of total paths so far. */
- int gl_matchc; /* Count of paths matching pattern. */
- int gl_offs; /* Reserved at beginning of gl_pathv. */
+ size_t gl_pathc; /* Count of total paths so far. */
+ size_t gl_matchc; /* Count of paths matching pattern. */
+ size_t gl_offs; /* Reserved at beginning of gl_pathv. */
int gl_flags; /* Copy of flags parameter to glob. */
char **gl_pathv; /* List of paths matching pattern. */
struct stat **gl_statv; /* Stat entries corresponding to gl_pathv */
diff --git a/openbsd-compat/inet_aton.c b/openbsd-compat/inet_aton.c
index 130597e1..093a1720 100644
--- a/openbsd-compat/inet_aton.c
+++ b/openbsd-compat/inet_aton.c
@@ -3,7 +3,7 @@
/*
* Copyright (c) 1983, 1990, 1993
* The Regents of the University of California. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -15,7 +15,7 @@
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -29,14 +29,14 @@
* SUCH DAMAGE.
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
- *
+ *
* 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, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
@@ -77,7 +77,7 @@ inet_addr(const char *cp)
}
#endif
-/*
+/*
* Check whether "cp" is a valid ascii representation
* of an Internet address and convert to a binary address.
* Returns 1 if the address is valid, 0 if not.
diff --git a/openbsd-compat/libressl-api-compat.c b/openbsd-compat/libressl-api-compat.c
new file mode 100644
index 00000000..fdadd4e5
--- /dev/null
+++ b/openbsd-compat/libressl-api-compat.c
@@ -0,0 +1,642 @@
+/* $OpenBSD: dsa_lib.c,v 1.29 2018/04/14 07:09:21 tb Exp $ */
+/* $OpenBSD: rsa_lib.c,v 1.37 2018/04/14 07:09:21 tb Exp $ */
+/* $OpenBSD: evp_lib.c,v 1.17 2018/09/12 06:35:38 djm Exp $ */
+/* $OpenBSD: dh_lib.c,v 1.32 2018/05/02 15:48:38 tb Exp $ */
+/* $OpenBSD: p_lib.c,v 1.24 2018/05/30 15:40:50 tb Exp $ */
+/* $OpenBSD: digest.c,v 1.30 2018/04/14 07:09:21 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* $OpenBSD: dsa_asn1.c,v 1.22 2018/06/14 17:03:19 jsing Exp $ */
+/* $OpenBSD: ecs_asn1.c,v 1.9 2018/03/17 15:24:44 tb Exp $ */
+/* $OpenBSD: digest.c,v 1.30 2018/04/14 07:09:21 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* $OpenBSD: rsa_meth.c,v 1.2 2018/09/12 06:35:38 djm Exp $ */
+/*
+ * Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#ifdef WITH_OPENSSL
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <openssl/dsa.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#ifdef OPENSSL_HAS_ECC
+#include <openssl/ecdsa.h>
+#endif
+#include <openssl/dh.h>
+
+#ifndef HAVE_DSA_GET0_PQG
+void
+DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+ if (p != NULL)
+ *p = d->p;
+ if (q != NULL)
+ *q = d->q;
+ if (g != NULL)
+ *g = d->g;
+}
+#endif /* HAVE_DSA_GET0_PQG */
+
+#ifndef HAVE_DSA_SET0_PQG
+int
+DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+ if ((d->p == NULL && p == NULL) || (d->q == NULL && q == NULL) ||
+ (d->g == NULL && g == NULL))
+ return 0;
+
+ if (p != NULL) {
+ BN_free(d->p);
+ d->p = p;
+ }
+ if (q != NULL) {
+ BN_free(d->q);
+ d->q = q;
+ }
+ if (g != NULL) {
+ BN_free(d->g);
+ d->g = g;
+ }
+
+ return 1;
+}
+#endif /* HAVE_DSA_SET0_PQG */
+
+#ifndef HAVE_DSA_GET0_KEY
+void
+DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+ if (pub_key != NULL)
+ *pub_key = d->pub_key;
+ if (priv_key != NULL)
+ *priv_key = d->priv_key;
+}
+#endif /* HAVE_DSA_GET0_KEY */
+
+#ifndef HAVE_DSA_SET0_KEY
+int
+DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+ if (d->pub_key == NULL && pub_key == NULL)
+ return 0;
+
+ if (pub_key != NULL) {
+ BN_free(d->pub_key);
+ d->pub_key = pub_key;
+ }
+ if (priv_key != NULL) {
+ BN_free(d->priv_key);
+ d->priv_key = priv_key;
+ }
+
+ return 1;
+}
+#endif /* HAVE_DSA_SET0_KEY */
+
+#ifndef HAVE_RSA_GET0_KEY
+void
+RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
+{
+ if (n != NULL)
+ *n = r->n;
+ if (e != NULL)
+ *e = r->e;
+ if (d != NULL)
+ *d = r->d;
+}
+#endif /* HAVE_RSA_GET0_KEY */
+
+#ifndef HAVE_RSA_SET0_KEY
+int
+RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
+{
+ if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL))
+ return 0;
+
+ if (n != NULL) {
+ BN_free(r->n);
+ r->n = n;
+ }
+ if (e != NULL) {
+ BN_free(r->e);
+ r->e = e;
+ }
+ if (d != NULL) {
+ BN_free(r->d);
+ r->d = d;
+ }
+
+ return 1;
+}
+#endif /* HAVE_RSA_SET0_KEY */
+
+#ifndef HAVE_RSA_GET0_CRT_PARAMS
+void
+RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1,
+ const BIGNUM **iqmp)
+{
+ if (dmp1 != NULL)
+ *dmp1 = r->dmp1;
+ if (dmq1 != NULL)
+ *dmq1 = r->dmq1;
+ if (iqmp != NULL)
+ *iqmp = r->iqmp;
+}
+#endif /* HAVE_RSA_GET0_CRT_PARAMS */
+
+#ifndef HAVE_RSA_SET0_CRT_PARAMS
+int
+RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
+{
+ if ((r->dmp1 == NULL && dmp1 == NULL) ||
+ (r->dmq1 == NULL && dmq1 == NULL) ||
+ (r->iqmp == NULL && iqmp == NULL))
+ return 0;
+
+ if (dmp1 != NULL) {
+ BN_free(r->dmp1);
+ r->dmp1 = dmp1;
+ }
+ if (dmq1 != NULL) {
+ BN_free(r->dmq1);
+ r->dmq1 = dmq1;
+ }
+ if (iqmp != NULL) {
+ BN_free(r->iqmp);
+ r->iqmp = iqmp;
+ }
+
+ return 1;
+}
+#endif /* HAVE_RSA_SET0_CRT_PARAMS */
+
+#ifndef HAVE_RSA_GET0_FACTORS
+void
+RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
+{
+ if (p != NULL)
+ *p = r->p;
+ if (q != NULL)
+ *q = r->q;
+}
+#endif /* HAVE_RSA_GET0_FACTORS */
+
+#ifndef HAVE_RSA_SET0_FACTORS
+int
+RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
+{
+ if ((r->p == NULL && p == NULL) || (r->q == NULL && q == NULL))
+ return 0;
+
+ if (p != NULL) {
+ BN_free(r->p);
+ r->p = p;
+ }
+ if (q != NULL) {
+ BN_free(r->q);
+ r->q = q;
+ }
+
+ return 1;
+}
+#endif /* HAVE_RSA_SET0_FACTORS */
+
+#ifndef HAVE_EVP_CIPHER_CTX_GET_IV
+int
+EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, unsigned char *iv, size_t len)
+{
+ if (ctx == NULL)
+ return 0;
+ if (EVP_CIPHER_CTX_iv_length(ctx) < 0)
+ return 0;
+ if (len != (size_t)EVP_CIPHER_CTX_iv_length(ctx))
+ return 0;
+ if (len > EVP_MAX_IV_LENGTH)
+ return 0; /* sanity check; shouldn't happen */
+ /*
+ * Skip the memcpy entirely when the requested IV length is zero,
+ * since the iv pointer may be NULL or invalid.
+ */
+ if (len != 0) {
+ if (iv == NULL)
+ return 0;
+# ifdef HAVE_EVP_CIPHER_CTX_IV
+ memcpy(iv, EVP_CIPHER_CTX_iv(ctx), len);
+# else
+ memcpy(iv, ctx->iv, len);
+# endif /* HAVE_EVP_CIPHER_CTX_IV */
+ }
+ return 1;
+}
+#endif /* HAVE_EVP_CIPHER_CTX_GET_IV */
+
+#ifndef HAVE_EVP_CIPHER_CTX_SET_IV
+int
+EVP_CIPHER_CTX_set_iv(EVP_CIPHER_CTX *ctx, const unsigned char *iv, size_t len)
+{
+ if (ctx == NULL)
+ return 0;
+ if (EVP_CIPHER_CTX_iv_length(ctx) < 0)
+ return 0;
+ if (len != (size_t)EVP_CIPHER_CTX_iv_length(ctx))
+ return 0;
+ if (len > EVP_MAX_IV_LENGTH)
+ return 0; /* sanity check; shouldn't happen */
+ /*
+ * Skip the memcpy entirely when the requested IV length is zero,
+ * since the iv pointer may be NULL or invalid.
+ */
+ if (len != 0) {
+ if (iv == NULL)
+ return 0;
+# ifdef HAVE_EVP_CIPHER_CTX_IV_NOCONST
+ memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, len);
+# else
+ memcpy(ctx->iv, iv, len);
+# endif /* HAVE_EVP_CIPHER_CTX_IV_NOCONST */
+ }
+ return 1;
+}
+#endif /* HAVE_EVP_CIPHER_CTX_SET_IV */
+
+#ifndef HAVE_DSA_SIG_GET0
+void
+DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+ if (pr != NULL)
+ *pr = sig->r;
+ if (ps != NULL)
+ *ps = sig->s;
+}
+#endif /* HAVE_DSA_SIG_GET0 */
+
+#ifndef HAVE_DSA_SIG_SET0
+int
+DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+ if (r == NULL || s == NULL)
+ return 0;
+
+ BN_clear_free(sig->r);
+ sig->r = r;
+ BN_clear_free(sig->s);
+ sig->s = s;
+
+ return 1;
+}
+#endif /* HAVE_DSA_SIG_SET0 */
+
+#ifdef OPENSSL_HAS_ECC
+#ifndef HAVE_ECDSA_SIG_GET0
+void
+ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+ if (pr != NULL)
+ *pr = sig->r;
+ if (ps != NULL)
+ *ps = sig->s;
+}
+#endif /* HAVE_ECDSA_SIG_GET0 */
+
+#ifndef HAVE_ECDSA_SIG_SET0
+int
+ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+ if (r == NULL || s == NULL)
+ return 0;
+
+ BN_clear_free(sig->r);
+ BN_clear_free(sig->s);
+ sig->r = r;
+ sig->s = s;
+ return 1;
+}
+#endif /* HAVE_ECDSA_SIG_SET0 */
+#endif /* OPENSSL_HAS_ECC */
+
+#ifndef HAVE_DH_GET0_PQG
+void
+DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+ if (p != NULL)
+ *p = dh->p;
+ if (q != NULL)
+ *q = dh->q;
+ if (g != NULL)
+ *g = dh->g;
+}
+#endif /* HAVE_DH_GET0_PQG */
+
+#ifndef HAVE_DH_SET0_PQG
+int
+DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+ if ((dh->p == NULL && p == NULL) || (dh->g == NULL && g == NULL))
+ return 0;
+
+ if (p != NULL) {
+ BN_free(dh->p);
+ dh->p = p;
+ }
+ if (q != NULL) {
+ BN_free(dh->q);
+ dh->q = q;
+ }
+ if (g != NULL) {
+ BN_free(dh->g);
+ dh->g = g;
+ }
+
+ return 1;
+}
+#endif /* HAVE_DH_SET0_PQG */
+
+#ifndef HAVE_DH_GET0_KEY
+void
+DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+ if (pub_key != NULL)
+ *pub_key = dh->pub_key;
+ if (priv_key != NULL)
+ *priv_key = dh->priv_key;
+}
+#endif /* HAVE_DH_GET0_KEY */
+
+#ifndef HAVE_DH_SET0_KEY
+int
+DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+ if (pub_key != NULL) {
+ BN_free(dh->pub_key);
+ dh->pub_key = pub_key;
+ }
+ if (priv_key != NULL) {
+ BN_free(dh->priv_key);
+ dh->priv_key = priv_key;
+ }
+
+ return 1;
+}
+#endif /* HAVE_DH_SET0_KEY */
+
+#ifndef HAVE_DH_SET_LENGTH
+int
+DH_set_length(DH *dh, long length)
+{
+ if (length < 0 || length > INT_MAX)
+ return 0;
+
+#if !defined(OPENSSL_IS_BORINGSSL)
+ dh->length = length;
+#endif
+ return 1;
+}
+#endif /* HAVE_DH_SET_LENGTH */
+
+#ifndef HAVE_RSA_METH_FREE
+void
+RSA_meth_free(RSA_METHOD *meth)
+{
+ if (meth != NULL) {
+ free((char *)meth->name);
+ free(meth);
+ }
+}
+#endif /* HAVE_RSA_METH_FREE */
+
+#ifndef HAVE_RSA_METH_DUP
+RSA_METHOD *
+RSA_meth_dup(const RSA_METHOD *meth)
+{
+ RSA_METHOD *copy;
+
+ if ((copy = calloc(1, sizeof(*copy))) == NULL)
+ return NULL;
+ memcpy(copy, meth, sizeof(*copy));
+ if ((copy->name = strdup(meth->name)) == NULL) {
+ free(copy);
+ return NULL;
+ }
+
+ return copy;
+}
+#endif /* HAVE_RSA_METH_DUP */
+
+#ifndef HAVE_RSA_METH_SET1_NAME
+int
+RSA_meth_set1_name(RSA_METHOD *meth, const char *name)
+{
+ char *copy;
+
+ if ((copy = strdup(name)) == NULL)
+ return 0;
+ free((char *)meth->name);
+ meth->name = copy;
+ return 1;
+}
+#endif /* HAVE_RSA_METH_SET1_NAME */
+
+#ifndef HAVE_RSA_METH_GET_FINISH
+int
+(*RSA_meth_get_finish(const RSA_METHOD *meth))(RSA *rsa)
+{
+ return meth->finish;
+}
+#endif /* HAVE_RSA_METH_GET_FINISH */
+
+#ifndef HAVE_RSA_METH_SET_PRIV_ENC
+int
+RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc)(int flen,
+ const unsigned char *from, unsigned char *to, RSA *rsa, int padding))
+{
+ meth->rsa_priv_enc = priv_enc;
+ return 1;
+}
+#endif /* HAVE_RSA_METH_SET_PRIV_ENC */
+
+#ifndef HAVE_RSA_METH_SET_PRIV_DEC
+int
+RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec)(int flen,
+ const unsigned char *from, unsigned char *to, RSA *rsa, int padding))
+{
+ meth->rsa_priv_dec = priv_dec;
+ return 1;
+}
+#endif /* HAVE_RSA_METH_SET_PRIV_DEC */
+
+#ifndef HAVE_RSA_METH_SET_FINISH
+int
+RSA_meth_set_finish(RSA_METHOD *meth, int (*finish)(RSA *rsa))
+{
+ meth->finish = finish;
+ return 1;
+}
+#endif /* HAVE_RSA_METH_SET_FINISH */
+
+#ifndef HAVE_EVP_PKEY_GET0_RSA
+RSA *
+EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
+{
+ if (pkey->type != EVP_PKEY_RSA) {
+ /* EVPerror(EVP_R_EXPECTING_AN_RSA_KEY); */
+ return NULL;
+ }
+ return pkey->pkey.rsa;
+}
+#endif /* HAVE_EVP_PKEY_GET0_RSA */
+
+#ifndef HAVE_EVP_MD_CTX_NEW
+EVP_MD_CTX *
+EVP_MD_CTX_new(void)
+{
+ return calloc(1, sizeof(EVP_MD_CTX));
+}
+#endif /* HAVE_EVP_MD_CTX_NEW */
+
+#ifndef HAVE_EVP_MD_CTX_FREE
+void
+EVP_MD_CTX_free(EVP_MD_CTX *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ EVP_MD_CTX_cleanup(ctx);
+
+ free(ctx);
+}
+#endif /* HAVE_EVP_MD_CTX_FREE */
+
+#endif /* WITH_OPENSSL */
diff --git a/openbsd-compat/memmem.c b/openbsd-compat/memmem.c
new file mode 100644
index 00000000..3e5e6b5e
--- /dev/null
+++ b/openbsd-compat/memmem.c
@@ -0,0 +1,69 @@
+/* $OpenBSD: memmem.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */
+/*-
+ * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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 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.
+ */
+
+#include "includes.h"
+
+#ifndef HAVE_MEMMEM
+
+#include <string.h>
+
+/*
+ * Find the first occurrence of the byte string s in byte string l.
+ */
+
+void *
+memmem(const void *l, size_t l_len, const void *s, size_t s_len)
+{
+ const char *cur, *last;
+ const char *cl = l;
+ const char *cs = s;
+
+ /* a zero length needle should just return the haystack */
+ if (s_len == 0)
+ return (void *)cl;
+
+ /* "s" must be smaller or equal to "l" */
+ if (l_len < s_len)
+ return NULL;
+
+ /* special case where s_len == 1 */
+ if (s_len == 1)
+ return memchr(l, *cs, l_len);
+
+ /* the last position where its possible to find "s" in "l" */
+ last = cl + l_len - s_len;
+
+ for (cur = cl; cur <= last; cur++)
+ if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
+ return (void *)cur;
+
+ return NULL;
+}
+DEF_WEAK(memmem);
+#endif /* HAVE_MEMMEM */
diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h
index 1cffefe0..e5fd6f5b 100644
--- a/openbsd-compat/openbsd-compat.h
+++ b/openbsd-compat/openbsd-compat.h
@@ -1,5 +1,3 @@
-/* $Id: openbsd-compat.h,v 1.62 2014/09/30 23:43:08 djm Exp $ */
-
/*
* Copyright (c) 1999-2003 Damien Miller. All rights reserved.
* Copyright (c) 2003 Ben Lindstrom. All rights reserved.
@@ -36,18 +34,19 @@
#include <sys/socket.h>
+#include <stddef.h> /* for wchar_t */
+
/* OpenBSD function replacements */
#include "base64.h"
#include "sigact.h"
-#include "glob.h"
#include "readpassphrase.h"
#include "vis.h"
#include "getrrsetbyname.h"
#include "sha1.h"
#include "sha2.h"
-#include "rmd160.h"
#include "md5.h"
#include "blf.h"
+#include "fnmatch.h"
#ifndef HAVE_BASENAME
char *basename(const char *path);
@@ -61,31 +60,54 @@ int bindresvport_sa(int sd, struct sockaddr *sa);
void closefrom(int);
#endif
+#ifndef HAVE_GETLINE
+#include <stdio.h>
+ssize_t getline(char **, size_t *, FILE *);
+#endif
+
+#ifndef HAVE_GETPAGESIZE
+int getpagesize(void);
+#endif
+
#ifndef HAVE_GETCWD
char *getcwd(char *pt, size_t size);
-#endif
+#endif
+
+#if defined(HAVE_DECL_MEMMEM) && HAVE_DECL_MEMMEM == 0
+void *memmem(const void *, size_t, const void *, size_t);
+#endif
#ifndef HAVE_REALLOCARRAY
void *reallocarray(void *, size_t, size_t);
#endif
-#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH)
-char *realpath(const char *path, char *resolved);
-#endif
+#ifndef HAVE_RECALLOCARRAY
+void *recallocarray(void *, size_t, size_t, size_t);
+#endif
#ifndef HAVE_RRESVPORT_AF
int rresvport_af(int *alport, sa_family_t af);
#endif
#ifndef HAVE_STRLCPY
-/* #include <sys/types.h> XXX Still needed? */
size_t strlcpy(char *dst, const char *src, size_t siz);
#endif
#ifndef HAVE_STRLCAT
-/* #include <sys/types.h> XXX Still needed? */
size_t strlcat(char *dst, const char *src, size_t siz);
-#endif
+#endif
+
+#ifndef HAVE_STRCASESTR
+char *strcasestr(const char *, const char *);
+#endif
+
+#ifndef HAVE_STRNLEN
+size_t strnlen(const char *, size_t);
+#endif
+
+#ifndef HAVE_STRNDUP
+char *strndup(const char *s, size_t n);
+#endif
#ifndef HAVE_SETENV
int setenv(register const char *name, register const char *value, int rewrite);
@@ -104,11 +126,11 @@ char *strptime(const char *buf, const char *fmt, struct tm *tm);
int mkstemps(char *path, int slen);
int mkstemp(char *path);
char *mkdtemp(char *path);
-#endif
+#endif
#ifndef HAVE_DAEMON
int daemon(int nochdir, int noclose);
-#endif
+#endif
#ifndef HAVE_DIRNAME
char *dirname(const char *path);
@@ -133,7 +155,7 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
#ifndef HAVE_INET_ATON
int inet_aton(const char *cp, struct in_addr *addr);
-#endif
+#endif
#ifndef HAVE_STRSEP
char *strsep(char **stringp, const char *delim);
@@ -145,7 +167,6 @@ void compat_init_setproctitle(int argc, char *argv[]);
#endif
#ifndef HAVE_GETGROUPLIST
-/* #include <grp.h> XXXX Still needed ? */
int getgrouplist(const char *, gid_t, gid_t *, int *);
#endif
@@ -154,20 +175,29 @@ int BSDgetopt(int argc, char * const *argv, const char *opts);
#include "openbsd-compat/getopt.h"
#endif
-#if defined(HAVE_DECL_WRITEV) && HAVE_DECL_WRITEV == 0
+#if ((defined(HAVE_DECL_READV) && HAVE_DECL_READV == 0) || \
+ (defined(HAVE_DECL_WRITEV) && HAVE_DECL_WRITEV == 0))
# include <sys/types.h>
# include <sys/uio.h>
+
+# if defined(HAVE_DECL_READV) && HAVE_DECL_READV == 0
+int readv(int, struct iovec *, int);
+# endif
+
+# if defined(HAVE_DECL_WRITEV) && HAVE_DECL_WRITEV == 0
int writev(int, struct iovec *, int);
+# endif
#endif
/* Home grown routines */
#include "bsd-misc.h"
#include "bsd-setres_id.h"
+#include "bsd-signal.h"
#include "bsd-statvfs.h"
#include "bsd-waitpid.h"
#include "bsd-poll.h"
-#ifndef HAVE_GETPEEREID
+#if defined(HAVE_DECL_GETPEEREID) && HAVE_DECL_GETPEEREID == 0
int getpeereid(int , uid_t *, gid_t *);
#endif
@@ -190,18 +220,16 @@ u_int32_t arc4random_uniform(u_int32_t);
#ifndef HAVE_ASPRINTF
int asprintf(char **, const char *, ...);
-#endif
+#endif
#ifndef HAVE_OPENPTY
# include <sys/ioctl.h> /* for struct winsize */
int openpty(int *, int *, char *, struct termios *, struct winsize *);
#endif /* HAVE_OPENPTY */
-/* #include <sys/types.h> XXX needed? For size_t */
-
#ifndef HAVE_SNPRINTF
int snprintf(char *, size_t, SNPRINTF_CONST char *, ...);
-#endif
+#endif
#ifndef HAVE_STRTOLL
long long strtoll(const char *, char **, int);
@@ -221,13 +249,46 @@ long long strtonum(const char *, long long, long long, const char **);
/* multibyte character support */
#ifndef HAVE_MBLEN
-# define mblen(x, y) 1
+# define mblen(x, y) (1)
+#endif
+
+#ifndef HAVE_WCWIDTH
+# define wcwidth(x) (((x) >= 0x20 && (x) <= 0x7e) ? 1 : -1)
+/* force our no-op nl_langinfo and mbtowc */
+# undef HAVE_NL_LANGINFO
+# undef HAVE_MBTOWC
+# undef HAVE_LANGINFO_H
+#endif
+
+#ifndef HAVE_NL_LANGINFO
+# define nl_langinfo(x) ""
+#endif
+
+#ifndef HAVE_MBTOWC
+int mbtowc(wchar_t *, const char*, size_t);
#endif
#if !defined(HAVE_VASPRINTF) || !defined(HAVE_VSNPRINTF)
# include <stdarg.h>
#endif
+/*
+ * Some platforms unconditionally undefine va_copy() so we define VA_COPY()
+ * instead. This is known to be the case on at least some configurations of
+ * AIX with the xlc compiler.
+ */
+#ifndef VA_COPY
+# ifdef HAVE_VA_COPY
+# define VA_COPY(dest, src) va_copy(dest, src)
+# else
+# ifdef HAVE___VA_COPY
+# define VA_COPY(dest, src) __va_copy(dest, src)
+# else
+# define VA_COPY(dest, src) (dest) = (src)
+# endif
+# endif
+#endif
+
#ifndef HAVE_VASPRINTF
int vasprintf(char **, const char *, va_list);
#endif
@@ -257,7 +318,14 @@ int bcrypt_pbkdf(const char *, size_t, const u_int8_t *, size_t,
void explicit_bzero(void *p, size_t n);
#endif
-void *xmmap(size_t size);
+#ifndef HAVE_FREEZERO
+void freezero(void *, size_t);
+#endif
+
+#ifndef HAVE_LOCALTIME_R
+struct tm *localtime_r(const time_t *, struct tm *);
+#endif
+
char *xcrypt(const char *password, const char *salt);
char *shadow_pw(struct passwd *pw);
@@ -265,14 +333,13 @@ char *shadow_pw(struct passwd *pw);
#include "fake-rfc2553.h"
/* Routines for a single OS platform */
-#include "bsd-cray.h"
#include "bsd-cygwin_util.h"
#include "port-aix.h"
#include "port-irix.h"
#include "port-linux.h"
#include "port-solaris.h"
-#include "port-tun.h"
+#include "port-net.h"
#include "port-uw.h"
/* _FORTIFY_SOURCE breaks FD_ISSET(n)/FD_SET(n) for n > FD_SETSIZE. Avoid. */
diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c
index 63a660c7..a37ca61b 100644
--- a/openbsd-compat/openssl-compat.c
+++ b/openbsd-compat/openssl-compat.c
@@ -1,5 +1,3 @@
-/* $Id: openssl-compat.c,v 1.19 2014/07/02 05:28:07 djm Exp $ */
-
/*
* Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
*
@@ -55,7 +53,7 @@ ssh_compatible_openssl(long headerver, long libver)
mask = 0xfffff00fL; /* major,minor,fix,status */
return (headerver & mask) == (libver & mask);
}
-
+
/*
* For versions >= 1.0.0, major,minor,status must match and library
* fix version must be equal to or newer than the header.
@@ -68,17 +66,31 @@ ssh_compatible_openssl(long headerver, long libver)
return 0;
}
-#ifdef USE_OPENSSL_ENGINE
void
-ssh_OpenSSL_add_all_algorithms(void)
+ssh_libcrypto_init(void)
{
+#if defined(HAVE_OPENSSL_INIT_CRYPTO) && \
+ defined(OPENSSL_INIT_ADD_ALL_CIPHERS) && \
+ defined(OPENSSL_INIT_ADD_ALL_DIGESTS)
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS |
+ OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
+#elif defined(HAVE_OPENSSL_ADD_ALL_ALGORITHMS)
OpenSSL_add_all_algorithms();
+#endif
+#ifdef USE_OPENSSL_ENGINE
/* Enable use of crypto hardware */
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
+
+ /* Load the libcrypto config file to pick up engines defined there */
+# if defined(HAVE_OPENSSL_INIT_CRYPTO) && defined(OPENSSL_INIT_LOAD_CONFIG)
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS |
+ OPENSSL_INIT_ADD_ALL_DIGESTS | OPENSSL_INIT_LOAD_CONFIG, NULL);
+# else
OPENSSL_config(NULL);
+# endif
+#endif /* USE_OPENSSL_ENGINE */
}
-#endif
#endif /* WITH_OPENSSL */
diff --git a/openbsd-compat/openssl-compat.h b/openbsd-compat/openssl-compat.h
index 8917551d..388ae8aa 100644
--- a/openbsd-compat/openssl-compat.h
+++ b/openbsd-compat/openssl-compat.h
@@ -1,5 +1,3 @@
-/* $Id: openssl-compat.h,v 1.31 2014/08/29 18:18:29 djm Exp $ */
-
/*
* Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
*
@@ -23,14 +21,32 @@
#ifdef WITH_OPENSSL
#include <openssl/opensslv.h>
+#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
+#ifdef OPENSSL_HAS_ECC
+#include <openssl/ecdsa.h>
+#endif
+#include <openssl/dh.h>
int ssh_compatible_openssl(long, long);
+void ssh_libcrypto_init(void);
-#if (OPENSSL_VERSION_NUMBER <= 0x0090805fL)
-# error OpenSSL 0.9.8f or greater is required
+#if (OPENSSL_VERSION_NUMBER < 0x1000100fL)
+# error OpenSSL 1.0.1 or greater is required
+#endif
+
+#ifndef OPENSSL_VERSION
+# define OPENSSL_VERSION SSLEAY_VERSION
+#endif
+
+#ifndef HAVE_OPENSSL_VERSION
+# define OpenSSL_version(x) SSLeay_version(x)
+#endif
+
+#ifndef HAVE_OPENSSL_VERSION_NUM
+# define OpenSSL_version_num SSLeay
#endif
#if OPENSSL_VERSION_NUMBER < 0x10000001L
@@ -46,6 +62,12 @@ int ssh_compatible_openssl(long, long);
# define OPENSSL_DSA_MAX_MODULUS_BITS 10000
#endif
+#ifdef LIBRESSL_VERSION_NUMBER
+# if LIBRESSL_VERSION_NUMBER < 0x3010000fL
+# define HAVE_BROKEN_CHACHA20
+# endif
+#endif
+
#ifndef OPENSSL_HAVE_EVPCTR
# define EVP_aes_128_ctr evp_aes_128_ctr
# define EVP_aes_192_ctr evp_aes_128_ctr
@@ -71,26 +93,141 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t);
# endif
#endif
-/*
- * We overload some of the OpenSSL crypto functions with ssh_* equivalents
- * to automatically handle OpenSSL engine initialisation.
- *
- * In order for the compat library to call the real functions, it must
- * define SSH_DONT_OVERLOAD_OPENSSL_FUNCS before including this file and
- * implement the ssh_* equivalents.
- */
-#ifndef SSH_DONT_OVERLOAD_OPENSSL_FUNCS
-
-# ifdef USE_OPENSSL_ENGINE
-# ifdef OpenSSL_add_all_algorithms
-# undef OpenSSL_add_all_algorithms
-# endif
-# define OpenSSL_add_all_algorithms() ssh_OpenSSL_add_all_algorithms()
-# endif
-
-void ssh_OpenSSL_add_all_algorithms(void);
-
-#endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */
+/* LibreSSL/OpenSSL 1.1x API compat */
+#ifndef HAVE_DSA_GET0_PQG
+void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q,
+ const BIGNUM **g);
+#endif /* HAVE_DSA_GET0_PQG */
+
+#ifndef HAVE_DSA_SET0_PQG
+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+#endif /* HAVE_DSA_SET0_PQG */
+
+#ifndef HAVE_DSA_GET0_KEY
+void DSA_get0_key(const DSA *d, const BIGNUM **pub_key,
+ const BIGNUM **priv_key);
+#endif /* HAVE_DSA_GET0_KEY */
+
+#ifndef HAVE_DSA_SET0_KEY
+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
+#endif /* HAVE_DSA_SET0_KEY */
+
+#ifndef HAVE_EVP_CIPHER_CTX_GET_IV
+int EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx,
+ unsigned char *iv, size_t len);
+#endif /* HAVE_EVP_CIPHER_CTX_GET_IV */
+
+#ifndef HAVE_EVP_CIPHER_CTX_SET_IV
+int EVP_CIPHER_CTX_set_iv(EVP_CIPHER_CTX *ctx,
+ const unsigned char *iv, size_t len);
+#endif /* HAVE_EVP_CIPHER_CTX_SET_IV */
+
+#ifndef HAVE_RSA_GET0_KEY
+void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e,
+ const BIGNUM **d);
+#endif /* HAVE_RSA_GET0_KEY */
+
+#ifndef HAVE_RSA_SET0_KEY
+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
+#endif /* HAVE_RSA_SET0_KEY */
+
+#ifndef HAVE_RSA_GET0_CRT_PARAMS
+void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1,
+ const BIGNUM **iqmp);
+#endif /* HAVE_RSA_GET0_CRT_PARAMS */
+
+#ifndef HAVE_RSA_SET0_CRT_PARAMS
+int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
+#endif /* HAVE_RSA_SET0_CRT_PARAMS */
+
+#ifndef HAVE_RSA_GET0_FACTORS
+void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
+#endif /* HAVE_RSA_GET0_FACTORS */
+
+#ifndef HAVE_RSA_SET0_FACTORS
+int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
+#endif /* HAVE_RSA_SET0_FACTORS */
+
+#ifndef DSA_SIG_GET0
+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
+#endif /* DSA_SIG_GET0 */
+
+#ifndef DSA_SIG_SET0
+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+#endif /* DSA_SIG_SET0 */
+
+#ifdef OPENSSL_HAS_ECC
+#ifndef HAVE_ECDSA_SIG_GET0
+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
+#endif /* HAVE_ECDSA_SIG_GET0 */
+
+#ifndef HAVE_ECDSA_SIG_SET0
+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+#endif /* HAVE_ECDSA_SIG_SET0 */
+#endif /* OPENSSL_HAS_ECC */
+
+#ifndef HAVE_DH_GET0_PQG
+void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q,
+ const BIGNUM **g);
+#endif /* HAVE_DH_GET0_PQG */
+
+#ifndef HAVE_DH_SET0_PQG
+int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+#endif /* HAVE_DH_SET0_PQG */
+
+#ifndef HAVE_DH_GET0_KEY
+void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key);
+#endif /* HAVE_DH_GET0_KEY */
+
+#ifndef HAVE_DH_SET0_KEY
+int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
+#endif /* HAVE_DH_SET0_KEY */
+
+#ifndef HAVE_DH_SET_LENGTH
+int DH_set_length(DH *dh, long length);
+#endif /* HAVE_DH_SET_LENGTH */
+
+#ifndef HAVE_RSA_METH_FREE
+void RSA_meth_free(RSA_METHOD *meth);
+#endif /* HAVE_RSA_METH_FREE */
+
+#ifndef HAVE_RSA_METH_DUP
+RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth);
+#endif /* HAVE_RSA_METH_DUP */
+
+#ifndef HAVE_RSA_METH_SET1_NAME
+int RSA_meth_set1_name(RSA_METHOD *meth, const char *name);
+#endif /* HAVE_RSA_METH_SET1_NAME */
+
+#ifndef HAVE_RSA_METH_GET_FINISH
+int (*RSA_meth_get_finish(const RSA_METHOD *meth))(RSA *rsa);
+#endif /* HAVE_RSA_METH_GET_FINISH */
+
+#ifndef HAVE_RSA_METH_SET_PRIV_ENC
+int RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc)(int flen,
+ const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
+#endif /* HAVE_RSA_METH_SET_PRIV_ENC */
+
+#ifndef HAVE_RSA_METH_SET_PRIV_DEC
+int RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec)(int flen,
+ const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
+#endif /* HAVE_RSA_METH_SET_PRIV_DEC */
+
+#ifndef HAVE_RSA_METH_SET_FINISH
+int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish)(RSA *rsa));
+#endif /* HAVE_RSA_METH_SET_FINISH */
+
+#ifndef HAVE_EVP_PKEY_GET0_RSA
+RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
+#endif /* HAVE_EVP_PKEY_GET0_RSA */
+
+#ifndef HAVE_EVP_MD_CTX_new
+EVP_MD_CTX *EVP_MD_CTX_new(void);
+#endif /* HAVE_EVP_MD_CTX_new */
+
+#ifndef HAVE_EVP_MD_CTX_free
+void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
+#endif /* HAVE_EVP_MD_CTX_free */
#endif /* WITH_OPENSSL */
#endif /* _OPENSSL_COMPAT_H */
diff --git a/openbsd-compat/port-aix.c b/openbsd-compat/port-aix.c
index 8da367d4..e0d3eba5 100644
--- a/openbsd-compat/port-aix.c
+++ b/openbsd-compat/port-aix.c
@@ -26,16 +26,18 @@
*/
#include "includes.h"
+#ifdef _AIX
+
#include "xmalloc.h"
-#include "buffer.h"
-#include "key.h"
+#include "sshbuf.h"
+#include "ssherr.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "ssh.h"
+#include "ssh_api.h"
#include "log.h"
-#ifdef _AIX
-
#include <errno.h>
#if defined(HAVE_NETDB_H)
# include <netdb.h>
@@ -171,15 +173,16 @@ aix_valid_authentications(const char *user)
* returns 0.
*/
int
-sys_auth_passwd(Authctxt *ctxt, const char *password)
+sys_auth_passwd(struct ssh *ssh, const char *password)
{
+ Authctxt *ctxt = ssh->authctxt;
char *authmsg = NULL, *msg = NULL, *name = ctxt->pw->pw_name;
- int authsuccess = 0, expired, reenter, result;
+ int r, authsuccess = 0, expired, reenter, result;
do {
result = authenticate((char *)name, (char *)password, &reenter,
&authmsg);
- aix_remove_embedded_newlines(authmsg);
+ aix_remove_embedded_newlines(authmsg);
debug3("AIX/authenticate result %d, authmsg %.100s", result,
authmsg);
} while (reenter);
@@ -201,7 +204,10 @@ sys_auth_passwd(Authctxt *ctxt, const char *password)
*/
expired = passwdexpired(name, &msg);
if (msg && *msg) {
- buffer_append(ctxt->loginmsg, msg, strlen(msg));
+ if ((r = sshbuf_put(ctxt->loginmsg,
+ msg, strlen(msg))) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
aix_remove_embedded_newlines(msg);
}
debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg);
@@ -232,10 +238,10 @@ sys_auth_passwd(Authctxt *ctxt, const char *password)
* Returns 1 if login is allowed, 0 if not allowed.
*/
int
-sys_auth_allowed_user(struct passwd *pw, Buffer *loginmsg)
+sys_auth_allowed_user(struct passwd *pw, struct sshbuf *loginmsg)
{
char *msg = NULL;
- int result, permitted = 0;
+ int r, result, permitted = 0;
struct stat st;
/*
@@ -258,8 +264,10 @@ sys_auth_allowed_user(struct passwd *pw, Buffer *loginmsg)
*/
if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) == 0)
permitted = 1;
- else if (msg != NULL)
- buffer_append(loginmsg, msg, strlen(msg));
+ else if (msg != NULL) {
+ if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ }
if (msg == NULL)
msg = xstrdup("(none)");
aix_remove_embedded_newlines(msg);
@@ -273,7 +281,7 @@ sys_auth_allowed_user(struct passwd *pw, Buffer *loginmsg)
int
sys_auth_record_login(const char *user, const char *host, const char *ttynm,
- Buffer *loginmsg)
+ struct sshbuf *loginmsg)
{
char *msg = NULL;
int success = 0;
@@ -305,7 +313,8 @@ sys_auth_get_lastlogin_msg(const char *user, uid_t uid)
* record_failed_login: generic "login failed" interface function
*/
void
-record_failed_login(const char *user, const char *hostname, const char *ttyname)
+record_failed_login(struct ssh *ssh, const char *user, const char *hostname,
+ const char *ttyname)
{
if (geteuid() != 0)
return;
@@ -337,11 +346,11 @@ aix_setauthdb(const char *user)
debug3("%s: Could not open userdb to read", __func__);
return;
}
-
+
if (getuserattr((char *)user, S_REGISTRY, &registry, SEC_CHAR) == 0) {
if (setauthdb(registry, old_registry) == 0)
debug3("AIX/setauthdb set registry '%s'", registry);
- else
+ else
debug3("AIX/setauthdb set registry '%s' failed: %s",
registry, strerror(errno));
} else
@@ -374,12 +383,13 @@ aix_restoreauthdb(void)
# ifdef USE_AIX_KRB_NAME
/*
- * aix_krb5_get_principal_name: returns the user's kerberos client principal name if
- * configured, otherwise NULL. Caller must free returned string.
+ * aix_krb5_get_principal_name: returns the user's kerberos client principal
+ * name if configured, otherwise NULL. Caller must free returned string.
*/
char *
-aix_krb5_get_principal_name(char *pw_name)
+aix_krb5_get_principal_name(const char *const_pw_name)
{
+ char *pw_name = (char *)const_pw_name;
char *authname = NULL, *authdomain = NULL, *principal = NULL;
setuserdb(S_READ);
@@ -389,7 +399,8 @@ aix_krb5_get_principal_name(char *pw_name)
debug("AIX getuserattr S_AUTHNAME: %s", strerror(errno));
if (authdomain != NULL)
- xasprintf(&principal, "%s@%s", authname ? authname : pw_name, authdomain);
+ xasprintf(&principal, "%s@%s", authname ? authname : pw_name,
+ authdomain);
else if (authname != NULL)
principal = xstrdup(authname);
enduserdb();
diff --git a/openbsd-compat/port-aix.h b/openbsd-compat/port-aix.h
index 53e4e88a..0ee36614 100644
--- a/openbsd-compat/port-aix.h
+++ b/openbsd-compat/port-aix.h
@@ -1,5 +1,3 @@
-/* $Id: port-aix.h,v 1.32 2009/12/20 23:49:22 dtucker Exp $ */
-
/*
*
* Copyright (c) 2001 Gert Doering. All rights reserved.
@@ -32,7 +30,8 @@
# include <sys/socket.h>
#endif
-#include "buffer.h"
+struct ssh;
+struct sshbuf;
/* These should be in the system headers but are not. */
int usrinfo(int, char *, int);
@@ -89,15 +88,16 @@ void aix_usrinfo(struct passwd *);
#ifdef WITH_AIXAUTHENTICATE
# define CUSTOM_SYS_AUTH_PASSWD 1
# define CUSTOM_SYS_AUTH_ALLOWED_USER 1
-int sys_auth_allowed_user(struct passwd *, Buffer *);
+int sys_auth_allowed_user(struct passwd *, struct sshbuf *);
# define CUSTOM_SYS_AUTH_RECORD_LOGIN 1
-int sys_auth_record_login(const char *, const char *, const char *, Buffer *);
+int sys_auth_record_login(const char *, const char *, const char *,
+ struct sshbuf *);
# define CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG
char *sys_auth_get_lastlogin_msg(const char *, uid_t);
# define CUSTOM_FAILED_LOGIN 1
# if defined(S_AUTHDOMAIN) && defined (S_AUTHNAME)
# define USE_AIX_KRB_NAME
-char *aix_krb5_get_principal_name(char *);
+char *aix_krb5_get_principal_name(const char *);
# endif
#endif
diff --git a/openbsd-compat/port-irix.c b/openbsd-compat/port-irix.c
index ba751a53..aebffb01 100644
--- a/openbsd-compat/port-irix.c
+++ b/openbsd-compat/port-irix.c
@@ -43,46 +43,48 @@
# include <sat.h>
#endif /* WITH_IRIX_AUDIT */
+#include "log.h"
+
void
irix_setusercontext(struct passwd *pw)
{
#ifdef WITH_IRIX_PROJECT
- prid_t projid;
+ prid_t projid;
#endif
#ifdef WITH_IRIX_JOBS
- jid_t jid = 0;
+ jid_t jid = 0;
#elif defined(WITH_IRIX_ARRAY)
- int jid = 0;
+ int jid = 0;
#endif
#ifdef WITH_IRIX_JOBS
- jid = jlimit_startjob(pw->pw_name, pw->pw_uid, "interactive");
- if (jid == -1)
- fatal("Failed to create job container: %.100s",
- strerror(errno));
+ jid = jlimit_startjob(pw->pw_name, pw->pw_uid, "interactive");
+ if (jid == -1)
+ fatal("Failed to create job container: %.100s",
+ strerror(errno));
#endif /* WITH_IRIX_JOBS */
#ifdef WITH_IRIX_ARRAY
- /* initialize array session */
- if (jid == 0 && newarraysess() != 0)
- fatal("Failed to set up new array session: %.100s",
- strerror(errno));
+ /* initialize array session */
+ if (jid == 0 && newarraysess() != 0)
+ fatal("Failed to set up new array session: %.100s",
+ strerror(errno));
#endif /* WITH_IRIX_ARRAY */
#ifdef WITH_IRIX_PROJECT
- /* initialize irix project info */
- if ((projid = getdfltprojuser(pw->pw_name)) == -1) {
- debug("Failed to get project id, using projid 0");
- projid = 0;
- }
- if (setprid(projid))
- fatal("Failed to initialize project %d for %s: %.100s",
- (int)projid, pw->pw_name, strerror(errno));
+ /* initialize irix project info */
+ if ((projid = getdfltprojuser(pw->pw_name)) == -1) {
+ debug("Failed to get project id, using projid 0");
+ projid = 0;
+ }
+ if (setprid(projid))
+ fatal("Failed to initialize project %d for %s: %.100s",
+ (int)projid, pw->pw_name, strerror(errno));
#endif /* WITH_IRIX_PROJECT */
#ifdef WITH_IRIX_AUDIT
- if (sysconf(_SC_AUDIT)) {
- debug("Setting sat id to %d", (int) pw->pw_uid);
- if (satsetid(pw->pw_uid))
- debug("error setting satid: %.100s", strerror(errno));
- }
+ if (sysconf(_SC_AUDIT)) {
+ debug("Setting sat id to %d", (int) pw->pw_uid);
+ if (satsetid(pw->pw_uid))
+ debug("error setting satid: %.100s", strerror(errno));
+ }
#endif /* WITH_IRIX_AUDIT */
}
diff --git a/openbsd-compat/port-irix.h b/openbsd-compat/port-irix.h
index 67c48630..bc8cc44a 100644
--- a/openbsd-compat/port-irix.h
+++ b/openbsd-compat/port-irix.h
@@ -1,5 +1,3 @@
-/* $Id: port-irix.h,v 1.4 2003/08/29 16:59:52 mouring Exp $ */
-
/*
* Copyright (c) 2000 Denis Parker. All rights reserved.
* Copyright (c) 2000 Michael Stone. All rights reserved.
diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c
index 4637a7a3..f46094fa 100644
--- a/openbsd-compat/port-linux.c
+++ b/openbsd-compat/port-linux.c
@@ -1,5 +1,3 @@
-/* $Id: port-linux.c,v 1.18 2013/06/01 22:07:32 dtucker Exp $ */
-
/*
* Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com>
* Copyright (c) 2006 Damien Miller <djm@openbsd.org>
@@ -28,6 +26,7 @@
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
#include "log.h"
#include "xmalloc.h"
@@ -35,7 +34,6 @@
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
-#include <selinux/flask.h>
#include <selinux/get_context_list.h>
#ifndef SSH_SELINUX_UNCONFINED_TYPE
@@ -141,6 +139,7 @@ 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;
+ security_class_t chrclass;
if (!ssh_selinux_enabled())
return;
@@ -155,9 +154,12 @@ ssh_selinux_setup_pty(char *pwname, const char *tty)
error("%s: getfilecon: %s", __func__, strerror(errno));
goto out;
}
-
+ if ((chrclass = string_to_security_class("chr_file")) == 0) {
+ error("%s: couldn't get security class for chr_file", __func__);
+ goto out;
+ }
if (security_compute_relabel(user_ctx, old_tty_ctx,
- SECCLASS_CHR_FILE, &new_tty_ctx) != 0) {
+ chrclass, &new_tty_ctx) != 0) {
error("%s: security_compute_relabel: %s",
__func__, strerror(errno));
goto out;
@@ -191,7 +193,7 @@ ssh_selinux_change_context(const char *newname)
}
if ((cx = index(oldctx, ':')) == NULL || (cx = index(cx + 1, ':')) ==
NULL) {
- logit ("%s: unparseable context %s", __func__, oldctx);
+ logit ("%s: unparsable context %s", __func__, oldctx);
return;
}
@@ -278,7 +280,7 @@ oom_adjust_setup(void)
verbose("error writing %s: %s",
oom_adj_path, strerror(errno));
else
- verbose("Set %s from %d to %d",
+ debug("Set %s from %d to %d",
oom_adj_path, oom_adj_save, value);
}
fclose(fp);
@@ -302,7 +304,7 @@ oom_adjust_restore(void)
if (fprintf(fp, "%d\n", oom_adj_save) <= 0)
verbose("error writing %s: %s", oom_adj_path, strerror(errno));
else
- verbose("Set %s to %d", oom_adj_path, oom_adj_save);
+ debug("Set %s to %d", oom_adj_path, oom_adj_save);
fclose(fp);
return;
diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h
index e3d1004a..3c22a854 100644
--- a/openbsd-compat/port-linux.h
+++ b/openbsd-compat/port-linux.h
@@ -1,5 +1,3 @@
-/* $Id: port-linux.h,v 1.5 2011/01/25 01:16:18 djm Exp $ */
-
/*
* Copyright (c) 2006 Damien Miller <djm@openbsd.org>
*
diff --git a/openbsd-compat/port-tun.c b/openbsd-compat/port-net.c
index 49e7b4d9..617bffce 100644
--- a/openbsd-compat/port-tun.c
+++ b/openbsd-compat/port-net.c
@@ -37,6 +37,90 @@
#include "ssherr.h"
/*
+ * This file contains various portability code for network support,
+ * including tun/tap forwarding and routing domains.
+ */
+
+#if defined(SYS_RDOMAIN_LINUX) || defined(SSH_TUN_LINUX)
+#include <linux/if.h>
+#endif
+
+#if defined(SYS_RDOMAIN_LINUX)
+char *
+sys_get_rdomain(int fd)
+{
+ char dev[IFNAMSIZ + 1];
+ socklen_t len = sizeof(dev) - 1;
+
+ if (getsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, dev, &len) == -1) {
+ error("%s: cannot determine VRF for fd=%d : %s",
+ __func__, fd, strerror(errno));
+ return NULL;
+ }
+ dev[len] = '\0';
+ return strdup(dev);
+}
+
+int
+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));
+ return -1;
+ }
+ return 0;
+}
+
+int
+sys_valid_rdomain(const char *name)
+{
+ int fd;
+
+ /*
+ * This is a pretty crappy way to test. It would be better to
+ * check whether "name" represents a VRF device, but apparently
+ * that requires an rtnetlink transaction.
+ */
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ return 0;
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
+ name, strlen(name)) == -1) {
+ close(fd);
+ return 0;
+ }
+ close(fd);
+ return 1;
+}
+#elif defined(SYS_RDOMAIN_XXX)
+/* XXX examples */
+char *
+sys_get_rdomain(int fd)
+{
+ return NULL;
+}
+
+int
+sys_set_rdomain(int fd, const char *name)
+{
+ return -1;
+}
+
+int
+valid_rdomain(const char *name)
+{
+ return 0;
+}
+
+void
+sys_set_process_rdomain(const char *name)
+{
+ fatal("%s: not supported", __func__);
+}
+#endif /* defined(SYS_RDOMAIN_XXX) */
+
+/*
* This is the portable version of the SSH tunnel forwarding, it
* uses some preprocessor definitions for various platform-specific
* settings.
@@ -52,23 +136,25 @@
*/
#if defined(SSH_TUN_LINUX)
-#include <linux/if.h>
#include <linux/if_tun.h>
+#define TUN_CTRL_DEV "/dev/net/tun"
int
-sys_tun_open(int tun, int mode)
+sys_tun_open(int tun, int mode, char **ifname)
{
struct ifreq ifr;
int fd = -1;
const char *name = NULL;
- if ((fd = open("/dev/net/tun", O_RDWR)) == -1) {
- debug("%s: failed to open tunnel control interface: %s",
- __func__, strerror(errno));
+ if (ifname != NULL)
+ *ifname = NULL;
+ if ((fd = open(TUN_CTRL_DEV, O_RDWR)) == -1) {
+ debug("%s: failed to open tunnel control device \"%s\": %s",
+ __func__, TUN_CTRL_DEV, strerror(errno));
return (-1);
}
- bzero(&ifr, sizeof(ifr));
+ bzero(&ifr, sizeof(ifr));
if (mode == SSH_TUNMODE_ETHERNET) {
ifr.ifr_flags = IFF_TAP;
@@ -99,6 +185,9 @@ sys_tun_open(int tun, int mode)
else
debug("%s: %s mode %d fd %d", __func__, ifr.ifr_name, mode, fd);
+ if (ifname != NULL && (*ifname = strdup(ifr.ifr_name)) == NULL)
+ goto failed;
+
return (fd);
failed:
@@ -116,13 +205,16 @@ sys_tun_open(int tun, int mode)
#endif
int
-sys_tun_open(int tun, int mode)
+sys_tun_open(int tun, int mode, char **ifname)
{
struct ifreq ifr;
char name[100];
int fd = -1, sock, flag;
const char *tunbase = "tun";
+ if (ifname != NULL)
+ *ifname = NULL;
+
if (mode == SSH_TUNMODE_ETHERNET) {
#ifdef SSH_TUN_NO_L2
debug("%s: no layer 2 tunnelling support", __func__);
@@ -180,6 +272,9 @@ sys_tun_open(int tun, int mode)
goto failed;
}
+ if (ifname != NULL && (*ifname = strdup(ifr.ifr_name)) == NULL)
+ goto failed;
+
close(sock);
return (fd);
@@ -199,84 +294,81 @@ sys_tun_open(int tun, int mode)
*/
#if defined(SSH_TUN_FILTER)
+/*
+ * The tunnel forwarding protocol prepends the address family of forwarded
+ * IP packets using OpenBSD's numbers.
+ */
#define OPENBSD_AF_INET 2
#define OPENBSD_AF_INET6 24
int
-sys_tun_infilter(struct Channel *c, char *buf, int len)
+sys_tun_infilter(struct ssh *ssh, struct Channel *c, char *buf, int _len)
{
+ int r;
+ size_t len;
+ char *ptr = buf;
#if defined(SSH_TUN_PREPEND_AF)
char rbuf[CHAN_RBUF];
- struct ip *iph;
+ struct ip iph;
#endif
- u_int32_t *af;
- char *ptr = buf;
- int r;
-
-#if defined(SSH_TUN_PREPEND_AF)
- if (len <= 0 || len > (int)(sizeof(rbuf) - sizeof(*af)))
- return (-1);
- ptr = (char *)&rbuf[0];
- bcopy(buf, ptr + sizeof(u_int32_t), len);
- len += sizeof(u_int32_t);
- af = (u_int32_t *)ptr;
-
- iph = (struct ip *)(ptr + sizeof(u_int32_t));
- switch (iph->ip_v) {
- case 6:
- *af = AF_INET6;
- break;
- case 4:
- default:
- *af = AF_INET;
- break;
- }
+#if defined(SSH_TUN_PREPEND_AF) || defined(SSH_TUN_COMPAT_AF)
+ u_int32_t af;
#endif
-#if defined(SSH_TUN_COMPAT_AF)
- if (len < (int)sizeof(u_int32_t))
- return (-1);
+ /* XXX update channel input filter API to use unsigned length */
+ if (_len < 0)
+ return -1;
+ len = _len;
- af = (u_int32_t *)ptr;
- if (*af == htonl(AF_INET6))
- *af = htonl(OPENBSD_AF_INET6);
- else
- *af = htonl(OPENBSD_AF_INET);
+#if defined(SSH_TUN_PREPEND_AF)
+ if (len <= sizeof(iph) || len > sizeof(rbuf) - 4)
+ return -1;
+ /* Determine address family from packet IP header. */
+ memcpy(&iph, buf, sizeof(iph));
+ af = iph.ip_v == 6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET;
+ /* Prepend address family to packet using OpenBSD constants */
+ memcpy(rbuf + 4, buf, len);
+ len += 4;
+ POKE_U32(rbuf, af);
+ ptr = rbuf;
+#elif defined(SSH_TUN_COMPAT_AF)
+ /* Convert existing address family header to OpenBSD value */
+ if (len <= 4)
+ return -1;
+ af = PEEK_U32(buf);
+ /* Put it back */
+ POKE_U32(buf, af == AF_INET6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET);
#endif
- if ((r = sshbuf_put_string(&c->input, ptr, len)) != 0)
+ if ((r = sshbuf_put_string(c->input, ptr, len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
return (0);
}
u_char *
-sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen)
+sys_tun_outfilter(struct ssh *ssh, struct Channel *c,
+ u_char **data, size_t *dlen)
{
u_char *buf;
- u_int32_t *af;
+ u_int32_t af;
int r;
- size_t xxx_dlen;
/* XXX new API is incompatible with this signature. */
- if ((r = sshbuf_get_string(&c->output, data, &xxx_dlen)) != 0)
+ if ((r = sshbuf_get_string(c->output, data, dlen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (dlen != NULL)
- *dlen = xxx_dlen;
- if (*dlen < sizeof(*af))
+ if (*dlen < sizeof(af))
return (NULL);
buf = *data;
#if defined(SSH_TUN_PREPEND_AF)
- *dlen -= sizeof(u_int32_t);
- buf = *data + sizeof(u_int32_t);
+ /* skip address family */
+ *dlen -= sizeof(af);
+ buf = *data + sizeof(af);
#elif defined(SSH_TUN_COMPAT_AF)
- af = ntohl(*(u_int32_t *)buf);
- if (*af == OPENBSD_AF_INET6)
- *af = htonl(AF_INET6);
- else
- *af = htonl(AF_INET);
+ /* translate address family */
+ af = (PEEK_U32(buf) == OPENBSD_AF_INET6) ? AF_INET6 : AF_INET;
+ POKE_U32(buf, af);
#endif
-
return (buf);
}
#endif /* SSH_TUN_FILTER */
diff --git a/openbsd-compat/port-tun.h b/openbsd-compat/port-net.h
index c53df01f..3a0d1104 100644
--- a/openbsd-compat/port-tun.h
+++ b/openbsd-compat/port-net.h
@@ -18,16 +18,31 @@
#define _PORT_TUN_H
struct Channel;
+struct ssh;
#if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD)
# define CUSTOM_SYS_TUN_OPEN
-int sys_tun_open(int, int);
+int sys_tun_open(int, int, char **);
#endif
#if defined(SSH_TUN_COMPAT_AF) || defined(SSH_TUN_PREPEND_AF)
# define SSH_TUN_FILTER
-int sys_tun_infilter(struct Channel *, char *, int);
-u_char *sys_tun_outfilter(struct Channel *, u_char **, u_int *);
+int sys_tun_infilter(struct ssh *, struct Channel *, char *, int);
+u_char *sys_tun_outfilter(struct ssh *, struct Channel *, u_char **, size_t *);
+#endif
+
+#if defined(SYS_RDOMAIN_LINUX)
+# define HAVE_SYS_GET_RDOMAIN
+# define HAVE_SYS_SET_RDOMAIN
+# define HAVE_SYS_VALID_RDOMAIN
+char *sys_get_rdomain(int fd);
+int sys_set_rdomain(int fd, const char *name);
+int sys_valid_rdomain(const char *name);
+#endif
+
+#if defined(SYS_RDOMAIN_XXX)
+# define HAVE_SYS_SET_PROCESS_RDOMAIN
+void sys_set_process_rdomain(const char *name);
#endif
#endif
diff --git a/openbsd-compat/port-solaris.c b/openbsd-compat/port-solaris.c
index 25382f1c..7d5a28cd 100644
--- a/openbsd-compat/port-solaris.c
+++ b/openbsd-compat/port-solaris.c
@@ -1,5 +1,3 @@
-/* $Id: port-solaris.c,v 1.4 2010/11/05 01:03:05 dtucker Exp $ */
-
/*
* Copyright (c) 2006 Chad Mynhier.
*
@@ -215,7 +213,7 @@ solaris_set_default_project(struct passwd *pw)
/* get default project, if we fail just return gracefully */
if ((defaultproject = getdefaultproj(pw->pw_name, &tempproject, &buf,
- sizeof(buf))) > 0) {
+ sizeof(buf))) != NULL) {
/* set default project */
if (setproject(defaultproject->pj_name, pw->pw_name,
TASK_NORMAL) != 0)
@@ -227,3 +225,137 @@ solaris_set_default_project(struct passwd *pw)
}
}
#endif /* USE_SOLARIS_PROJECTS */
+
+#ifdef USE_SOLARIS_PRIVS
+# ifdef HAVE_PRIV_H
+# include <priv.h>
+# endif
+
+priv_set_t *
+solaris_basic_privset(void)
+{
+ priv_set_t *pset;
+
+#ifdef HAVE_PRIV_BASICSET
+ if ((pset = priv_allocset()) == NULL) {
+ error("priv_allocset: %s", strerror(errno));
+ return NULL;
+ }
+ priv_basicset(pset);
+#else
+ if ((pset = priv_str_to_set("basic", ",", NULL)) == NULL) {
+ error("priv_str_to_set: %s", strerror(errno));
+ return NULL;
+ }
+#endif
+ return pset;
+}
+
+void
+solaris_drop_privs_pinfo_net_fork_exec(void)
+{
+ priv_set_t *pset = NULL, *npset = NULL;
+
+ /*
+ * Note: this variant avoids dropping DAC filesystem rights, in case
+ * the process calling it is running as root and should have the
+ * ability to read/write/chown any file on the system.
+ *
+ * We start with the basic set, then *add* the DAC rights to it while
+ * taking away other parts of BASIC we don't need. Then we intersect
+ * this with our existing PERMITTED set. In this way we keep any
+ * DAC rights we had before, while otherwise reducing ourselves to
+ * the minimum set of privileges we need to proceed.
+ *
+ * This also means we drop any other parts of "root" that we don't
+ * need (e.g. the ability to kill any process, create new device nodes
+ * etc etc).
+ */
+
+ if ((pset = priv_allocset()) == NULL)
+ fatal("priv_allocset: %s", strerror(errno));
+ if ((npset = solaris_basic_privset()) == NULL)
+ fatal("solaris_basic_privset: %s", strerror(errno));
+
+ if (priv_addset(npset, PRIV_FILE_CHOWN) != 0 ||
+ priv_addset(npset, PRIV_FILE_DAC_READ) != 0 ||
+ priv_addset(npset, PRIV_FILE_DAC_SEARCH) != 0 ||
+ priv_addset(npset, PRIV_FILE_DAC_WRITE) != 0 ||
+ priv_addset(npset, PRIV_FILE_OWNER) != 0)
+ fatal("priv_addset: %s", strerror(errno));
+
+ if (priv_delset(npset, PRIV_PROC_EXEC) != 0 ||
+#ifdef PRIV_NET_ACCESS
+ priv_delset(npset, PRIV_NET_ACCESS) != 0 ||
+#endif
+ priv_delset(npset, PRIV_PROC_FORK) != 0 ||
+ priv_delset(npset, PRIV_PROC_INFO) != 0 ||
+ priv_delset(npset, PRIV_PROC_SESSION) != 0)
+ fatal("priv_delset: %s", strerror(errno));
+
+ if (getppriv(PRIV_PERMITTED, pset) != 0)
+ fatal("getppriv: %s", strerror(errno));
+
+ priv_intersect(pset, npset);
+
+ if (setppriv(PRIV_SET, PRIV_PERMITTED, npset) != 0 ||
+ setppriv(PRIV_SET, PRIV_LIMIT, npset) != 0 ||
+ setppriv(PRIV_SET, PRIV_INHERITABLE, npset) != 0)
+ fatal("setppriv: %s", strerror(errno));
+
+ priv_freeset(pset);
+ priv_freeset(npset);
+}
+
+void
+solaris_drop_privs_root_pinfo_net(void)
+{
+ priv_set_t *pset = NULL;
+
+ /* Start with "basic" and drop everything we don't need. */
+ if ((pset = solaris_basic_privset()) == NULL)
+ fatal("solaris_basic_privset: %s", strerror(errno));
+
+ if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 ||
+#ifdef PRIV_NET_ACCESS
+ priv_delset(pset, PRIV_NET_ACCESS) != 0 ||
+#endif
+ priv_delset(pset, PRIV_PROC_INFO) != 0 ||
+ priv_delset(pset, PRIV_PROC_SESSION) != 0)
+ fatal("priv_delset: %s", strerror(errno));
+
+ if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) != 0 ||
+ setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0 ||
+ setppriv(PRIV_SET, PRIV_INHERITABLE, pset) != 0)
+ fatal("setppriv: %s", strerror(errno));
+
+ priv_freeset(pset);
+}
+
+void
+solaris_drop_privs_root_pinfo_net_exec(void)
+{
+ priv_set_t *pset = NULL;
+
+
+ /* Start with "basic" and drop everything we don't need. */
+ if ((pset = solaris_basic_privset()) == NULL)
+ fatal("solaris_basic_privset: %s", strerror(errno));
+
+ if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 ||
+#ifdef PRIV_NET_ACCESS
+ priv_delset(pset, PRIV_NET_ACCESS) != 0 ||
+#endif
+ priv_delset(pset, PRIV_PROC_EXEC) != 0 ||
+ priv_delset(pset, PRIV_PROC_INFO) != 0)
+ fatal("priv_delset: %s", strerror(errno));
+
+ if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) != 0 ||
+ setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0 ||
+ setppriv(PRIV_SET, PRIV_INHERITABLE, pset) != 0)
+ fatal("setppriv: %s", strerror(errno));
+
+ priv_freeset(pset);
+}
+
+#endif
diff --git a/openbsd-compat/port-solaris.h b/openbsd-compat/port-solaris.h
index cd442e78..dde1a5b8 100644
--- a/openbsd-compat/port-solaris.h
+++ b/openbsd-compat/port-solaris.h
@@ -1,5 +1,3 @@
-/* $Id: port-solaris.h,v 1.2 2010/11/05 01:03:05 dtucker Exp $ */
-
/*
* Copyright (c) 2006 Chad Mynhier.
*
@@ -26,5 +24,12 @@ void solaris_contract_pre_fork(void);
void solaris_contract_post_fork_child(void);
void solaris_contract_post_fork_parent(pid_t pid);
void solaris_set_default_project(struct passwd *);
+# ifdef USE_SOLARIS_PRIVS
+#include <priv.h>
+priv_set_t *solaris_basic_privset(void);
+void solaris_drop_privs_pinfo_net_fork_exec(void);
+void solaris_drop_privs_root_pinfo_net(void);
+void solaris_drop_privs_root_pinfo_net_exec(void);
+# endif /* USE_SOLARIS_PRIVS */
#endif
diff --git a/openbsd-compat/port-uw.c b/openbsd-compat/port-uw.c
index db24dbb9..13221313 100644
--- a/openbsd-compat/port-uw.c
+++ b/openbsd-compat/port-uw.c
@@ -38,8 +38,6 @@
#include "xmalloc.h"
#include "packet.h"
-#include "buffer.h"
-#include "key.h"
#include "auth-options.h"
#include "log.h"
#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */
@@ -47,12 +45,14 @@
#include "hostfile.h"
#include "auth.h"
#include "ssh.h"
+#include "ssh_api.h"
int nischeck(char *);
int
-sys_auth_passwd(Authctxt *authctxt, const char *password)
+sys_auth_passwd(struct ssh *ssh, const char *password)
{
+ Authctxt *authctxt = ssh->authctxt;
struct passwd *pw = authctxt->pw;
char *salt;
int result;
@@ -60,6 +60,9 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
/* Just use the supplied fake password if authctxt is invalid */
char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd;
+ if (pw_password == NULL)
+ return 0;
+
/* Check for users with no password. */
if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0)
return (1);
@@ -97,7 +100,7 @@ nischeck(char *namep)
if ((fd = fopen (password_file, "r")) == NULL) {
/*
- * If the passwd file has dissapeared we are in a bad state.
+ * If the passwd file has disappeared we are in a bad state.
* However, returning 0 will send us back through the
* authentication scheme that has checked the ia database for
* passwords earlier.
diff --git a/openbsd-compat/pwcache.c b/openbsd-compat/pwcache.c
index 5a8b7880..826c2378 100644
--- a/openbsd-compat/pwcache.c
+++ b/openbsd-compat/pwcache.c
@@ -67,7 +67,7 @@ user_from_uid(uid_t uid, int nouser)
if ((pw = getpwuid(uid)) == NULL) {
if (nouser)
return (NULL);
- (void)snprintf(nbuf, sizeof(nbuf), "%u", uid);
+ (void)snprintf(nbuf, sizeof(nbuf), "%lu", (u_long)uid);
}
cp->uid = uid;
if (cp->name != NULL)
@@ -102,7 +102,7 @@ group_from_gid(gid_t gid, int nogroup)
if ((gr = getgrgid(gid)) == NULL) {
if (nogroup)
return (NULL);
- (void)snprintf(nbuf, sizeof(nbuf), "%u", gid);
+ (void)snprintf(nbuf, sizeof(nbuf), "%lu", (u_long)gid);
}
cp->gid = gid;
if (cp->name != NULL)
diff --git a/openbsd-compat/readpassphrase.c b/openbsd-compat/readpassphrase.c
index d63cdf2f..ff8ff3de 100644
--- a/openbsd-compat/readpassphrase.c
+++ b/openbsd-compat/readpassphrase.c
@@ -1,7 +1,8 @@
-/* $OpenBSD: readpassphrase.c,v 1.22 2010/01/13 10:20:54 dtucker Exp $ */
+/* $OpenBSD: readpassphrase.c,v 1.26 2016/10/18 12:47:18 millert Exp $ */
/*
- * Copyright (c) 2000-2002, 2007 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2000-2002, 2007, 2010
+ * Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -35,10 +36,9 @@
#include <string.h>
#include <unistd.h>
-#ifdef TCSASOFT
-# define _T_FLUSH (TCSAFLUSH|TCSASOFT)
-#else
-# define _T_FLUSH (TCSAFLUSH)
+#ifndef TCSASOFT
+/* If we don't have TCSASOFT define it so that ORing it it below is a no-op. */
+# define TCSASOFT 0
#endif
/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */
@@ -46,14 +46,6 @@
# define _POSIX_VDISABLE VDISABLE
#endif
-#ifndef _NSIG
-# ifdef NSIG
-# define _NSIG NSIG
-# else
-# define _NSIG 128
-# endif
-#endif
-
static volatile sig_atomic_t signo[_NSIG];
static void handler(int);
@@ -95,6 +87,27 @@ restart:
}
/*
+ * Turn off echo if possible.
+ * If we are using a tty but are not the foreground pgrp this will
+ * generate SIGTTOU, so do it *before* installing the signal handlers.
+ */
+ if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
+ memcpy(&term, &oterm, sizeof(term));
+ if (!(flags & RPP_ECHO_ON))
+ term.c_lflag &= ~(ECHO | ECHONL);
+#ifdef VSTATUS
+ if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
+ term.c_cc[VSTATUS] = _POSIX_VDISABLE;
+#endif
+ (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
+ } else {
+ memset(&term, 0, sizeof(term));
+ term.c_lflag |= ECHO;
+ memset(&oterm, 0, sizeof(oterm));
+ oterm.c_lflag |= ECHO;
+ }
+
+ /*
* Catch signals that would otherwise cause the user to end
* up with echo turned off in the shell. Don't worry about
* things like SIGXCPU and SIGVTALRM for now.
@@ -112,53 +125,37 @@ restart:
(void)sigaction(SIGTTIN, &sa, &savettin);
(void)sigaction(SIGTTOU, &sa, &savettou);
- /* Turn off echo if possible. */
- if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
- memcpy(&term, &oterm, sizeof(term));
- if (!(flags & RPP_ECHO_ON))
- term.c_lflag &= ~(ECHO | ECHONL);
-#ifdef VSTATUS
- if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
- term.c_cc[VSTATUS] = _POSIX_VDISABLE;
-#endif
- (void)tcsetattr(input, _T_FLUSH, &term);
- } else {
- memset(&term, 0, sizeof(term));
- term.c_lflag |= ECHO;
- memset(&oterm, 0, sizeof(oterm));
- oterm.c_lflag |= ECHO;
- }
-
- /* No I/O if we are already backgrounded. */
- if (signo[SIGTTOU] != 1 && signo[SIGTTIN] != 1) {
- if (!(flags & RPP_STDIN))
- (void)write(output, prompt, strlen(prompt));
- end = buf + bufsiz - 1;
- p = buf;
- while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
- if (p < end) {
- if ((flags & RPP_SEVENBIT))
- ch &= 0x7f;
- if (isalpha(ch)) {
- if ((flags & RPP_FORCELOWER))
- ch = (char)tolower(ch);
- if ((flags & RPP_FORCEUPPER))
- ch = (char)toupper(ch);
- }
- *p++ = ch;
+ if (!(flags & RPP_STDIN))
+ (void)write(output, prompt, strlen(prompt));
+ end = buf + bufsiz - 1;
+ p = buf;
+ while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
+ if (p < end) {
+ if ((flags & RPP_SEVENBIT))
+ ch &= 0x7f;
+ if (isalpha((unsigned char)ch)) {
+ if ((flags & RPP_FORCELOWER))
+ ch = (char)tolower((unsigned char)ch);
+ if ((flags & RPP_FORCEUPPER))
+ ch = (char)toupper((unsigned char)ch);
}
+ *p++ = ch;
}
- *p = '\0';
- save_errno = errno;
- if (!(term.c_lflag & ECHO))
- (void)write(output, "\n", 1);
}
+ *p = '\0';
+ save_errno = errno;
+ if (!(term.c_lflag & ECHO))
+ (void)write(output, "\n", 1);
/* Restore old terminal settings and signals. */
if (memcmp(&term, &oterm, sizeof(term)) != 0) {
- while (tcsetattr(input, _T_FLUSH, &oterm) == -1 &&
- errno == EINTR)
+ const int sigttou = signo[SIGTTOU];
+
+ /* Ignore SIGTTOU generated when we are not the fg pgrp. */
+ while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 &&
+ errno == EINTR && !signo[SIGTTOU])
continue;
+ signo[SIGTTOU] = sigttou;
}
(void)sigaction(SIGALRM, &savealrm, NULL);
(void)sigaction(SIGHUP, &savehup, NULL);
@@ -194,6 +191,7 @@ restart:
errno = save_errno;
return(nr == -1 ? NULL : buf);
}
+DEF_WEAK(readpassphrase);
#if 0
char *
diff --git a/openbsd-compat/readpassphrase.c.orig b/openbsd-compat/readpassphrase.c.orig
deleted file mode 100644
index d63cdf2f..00000000
--- a/openbsd-compat/readpassphrase.c.orig
+++ /dev/null
@@ -1,213 +0,0 @@
-/* $OpenBSD: readpassphrase.c,v 1.22 2010/01/13 10:20:54 dtucker Exp $ */
-
-/*
- * Copyright (c) 2000-2002, 2007 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * 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.
- *
- * Sponsored in part by the Defense Advanced Research Projects
- * Agency (DARPA) and Air Force Research Laboratory, Air Force
- * Materiel Command, USAF, under agreement number F39502-99-1-0512.
- */
-
-/* OPENBSD ORIGINAL: lib/libc/gen/readpassphrase.c */
-
-#include "includes.h"
-
-#ifndef HAVE_READPASSPHRASE
-
-#include <termios.h>
-#include <signal.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <readpassphrase.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#ifdef TCSASOFT
-# define _T_FLUSH (TCSAFLUSH|TCSASOFT)
-#else
-# define _T_FLUSH (TCSAFLUSH)
-#endif
-
-/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */
-#if !defined(_POSIX_VDISABLE) && defined(VDISABLE)
-# define _POSIX_VDISABLE VDISABLE
-#endif
-
-#ifndef _NSIG
-# ifdef NSIG
-# define _NSIG NSIG
-# else
-# define _NSIG 128
-# endif
-#endif
-
-static volatile sig_atomic_t signo[_NSIG];
-
-static void handler(int);
-
-char *
-readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
-{
- ssize_t nr;
- int input, output, save_errno, i, need_restart;
- char ch, *p, *end;
- struct termios term, oterm;
- struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
- struct sigaction savetstp, savettin, savettou, savepipe;
-
- /* I suppose we could alloc on demand in this case (XXX). */
- if (bufsiz == 0) {
- errno = EINVAL;
- return(NULL);
- }
-
-restart:
- for (i = 0; i < _NSIG; i++)
- signo[i] = 0;
- nr = -1;
- save_errno = 0;
- need_restart = 0;
- /*
- * Read and write to /dev/tty if available. If not, read from
- * stdin and write to stderr unless a tty is required.
- */
- if ((flags & RPP_STDIN) ||
- (input = output = open(_PATH_TTY, O_RDWR)) == -1) {
- if (flags & RPP_REQUIRE_TTY) {
- errno = ENOTTY;
- return(NULL);
- }
- input = STDIN_FILENO;
- output = STDERR_FILENO;
- }
-
- /*
- * Catch signals that would otherwise cause the user to end
- * up with echo turned off in the shell. Don't worry about
- * things like SIGXCPU and SIGVTALRM for now.
- */
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0; /* don't restart system calls */
- sa.sa_handler = handler;
- (void)sigaction(SIGALRM, &sa, &savealrm);
- (void)sigaction(SIGHUP, &sa, &savehup);
- (void)sigaction(SIGINT, &sa, &saveint);
- (void)sigaction(SIGPIPE, &sa, &savepipe);
- (void)sigaction(SIGQUIT, &sa, &savequit);
- (void)sigaction(SIGTERM, &sa, &saveterm);
- (void)sigaction(SIGTSTP, &sa, &savetstp);
- (void)sigaction(SIGTTIN, &sa, &savettin);
- (void)sigaction(SIGTTOU, &sa, &savettou);
-
- /* Turn off echo if possible. */
- if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
- memcpy(&term, &oterm, sizeof(term));
- if (!(flags & RPP_ECHO_ON))
- term.c_lflag &= ~(ECHO | ECHONL);
-#ifdef VSTATUS
- if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
- term.c_cc[VSTATUS] = _POSIX_VDISABLE;
-#endif
- (void)tcsetattr(input, _T_FLUSH, &term);
- } else {
- memset(&term, 0, sizeof(term));
- term.c_lflag |= ECHO;
- memset(&oterm, 0, sizeof(oterm));
- oterm.c_lflag |= ECHO;
- }
-
- /* No I/O if we are already backgrounded. */
- if (signo[SIGTTOU] != 1 && signo[SIGTTIN] != 1) {
- if (!(flags & RPP_STDIN))
- (void)write(output, prompt, strlen(prompt));
- end = buf + bufsiz - 1;
- p = buf;
- while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
- if (p < end) {
- if ((flags & RPP_SEVENBIT))
- ch &= 0x7f;
- if (isalpha(ch)) {
- if ((flags & RPP_FORCELOWER))
- ch = (char)tolower(ch);
- if ((flags & RPP_FORCEUPPER))
- ch = (char)toupper(ch);
- }
- *p++ = ch;
- }
- }
- *p = '\0';
- save_errno = errno;
- if (!(term.c_lflag & ECHO))
- (void)write(output, "\n", 1);
- }
-
- /* Restore old terminal settings and signals. */
- if (memcmp(&term, &oterm, sizeof(term)) != 0) {
- while (tcsetattr(input, _T_FLUSH, &oterm) == -1 &&
- errno == EINTR)
- continue;
- }
- (void)sigaction(SIGALRM, &savealrm, NULL);
- (void)sigaction(SIGHUP, &savehup, NULL);
- (void)sigaction(SIGINT, &saveint, NULL);
- (void)sigaction(SIGQUIT, &savequit, NULL);
- (void)sigaction(SIGPIPE, &savepipe, NULL);
- (void)sigaction(SIGTERM, &saveterm, NULL);
- (void)sigaction(SIGTSTP, &savetstp, NULL);
- (void)sigaction(SIGTTIN, &savettin, NULL);
- (void)sigaction(SIGTTOU, &savettou, NULL);
- if (input != STDIN_FILENO)
- (void)close(input);
-
- /*
- * If we were interrupted by a signal, resend it to ourselves
- * now that we have restored the signal handlers.
- */
- for (i = 0; i < _NSIG; i++) {
- if (signo[i]) {
- kill(getpid(), i);
- switch (i) {
- case SIGTSTP:
- case SIGTTIN:
- case SIGTTOU:
- need_restart = 1;
- }
- }
- }
- if (need_restart)
- goto restart;
-
- if (save_errno)
- errno = save_errno;
- return(nr == -1 ? NULL : buf);
-}
-
-#if 0
-char *
-getpass(const char *prompt)
-{
- static char buf[_PASSWORD_LEN + 1];
-
- return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF));
-}
-#endif
-
-static void handler(int s)
-{
-
- signo[s] = 1;
-}
-#endif /* HAVE_READPASSPHRASE */
diff --git a/openbsd-compat/recallocarray.c b/openbsd-compat/recallocarray.c
new file mode 100644
index 00000000..3e1156ce
--- /dev/null
+++ b/openbsd-compat/recallocarray.c
@@ -0,0 +1,90 @@
+/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */
+/*
+ * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */
+
+#include "includes.h"
+#ifndef HAVE_RECALLOCARRAY
+
+#include <errno.h>
+#include <stdlib.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
+
+void *
+recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
+{
+ size_t oldsize, newsize;
+ void *newptr;
+
+ if (ptr == NULL)
+ return calloc(newnmemb, size);
+
+ if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+ newnmemb > 0 && SIZE_MAX / newnmemb < size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ newsize = newnmemb * size;
+
+ if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+ oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
+ errno = EINVAL;
+ return NULL;
+ }
+ oldsize = oldnmemb * size;
+
+ /*
+ * Don't bother too much if we're shrinking just a bit,
+ * we do not shrink for series of small steps, oh well.
+ */
+ if (newsize <= oldsize) {
+ size_t d = oldsize - newsize;
+
+ if (d < oldsize / 2 && d < (size_t)getpagesize()) {
+ memset((char *)ptr + newsize, 0, d);
+ return ptr;
+ }
+ }
+
+ newptr = malloc(newsize);
+ if (newptr == NULL)
+ return NULL;
+
+ if (newsize > oldsize) {
+ memcpy(newptr, ptr, oldsize);
+ memset((char *)newptr + oldsize, 0, newsize - oldsize);
+ } else
+ memcpy(newptr, ptr, newsize);
+
+ explicit_bzero(ptr, oldsize);
+ free(ptr);
+
+ return newptr;
+}
+/* DEF_WEAK(recallocarray); */
+
+#endif /* HAVE_RECALLOCARRAY */
diff --git a/openbsd-compat/regress/.cvsignore b/openbsd-compat/regress/.cvsignore
deleted file mode 100644
index 33074f4a..00000000
--- a/openbsd-compat/regress/.cvsignore
+++ /dev/null
@@ -1,6 +0,0 @@
-Makefile
-snprintftest
-strduptest
-strtonumtest
-closefromtest
-opensslvertest
diff --git a/openbsd-compat/regress/Makefile.in b/openbsd-compat/regress/Makefile.in
index dabdb091..c5aae61e 100644
--- a/openbsd-compat/regress/Makefile.in
+++ b/openbsd-compat/regress/Makefile.in
@@ -1,5 +1,3 @@
-# $Id: Makefile.in,v 1.5 2014/06/17 13:06:08 dtucker Exp $
-
sysconfdir=@sysconfdir@
piddir=@piddir@
srcdir=@srcdir@
@@ -16,7 +14,7 @@ LIBS=@LIBS@
LDFLAGS=@LDFLAGS@ $(LIBCOMPAT)
TESTPROGS=closefromtest$(EXEEXT) snprintftest$(EXEEXT) strduptest$(EXEEXT) \
- strtonumtest$(EXEEXT) opensslvertest$(EXEEXT)
+ strtonumtest$(EXEEXT) opensslvertest$(EXEEXT) utimensattest$(EXEEXT)
all: t-exec ${OTHERTESTS}
diff --git a/openbsd-compat/regress/snprintftest.c b/openbsd-compat/regress/snprintftest.c
index 4ca63e18..6dc2e222 100644
--- a/openbsd-compat/regress/snprintftest.c
+++ b/openbsd-compat/regress/snprintftest.c
@@ -47,7 +47,7 @@ int
main(void)
{
char b[5];
- char *src;
+ char *src = NULL;
snprintf(b,5,"123456789");
if (b[4] != '\0')
@@ -69,5 +69,6 @@ main(void)
if (x_snprintf(b, 1, "%s %d", "hello", 12345) != 11)
fail("vsnprintf does not return required length");
+ free(src);
return failed;
}
diff --git a/openbsd-compat/regress/utimensattest.c b/openbsd-compat/regress/utimensattest.c
new file mode 100644
index 00000000..24312e5d
--- /dev/null
+++ b/openbsd-compat/regress/utimensattest.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2019 Darren Tucker
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define TMPFILE "utimensat.tmp"
+#define TMPFILE2 "utimensat.tmp2"
+
+#ifndef AT_SYMLINK_NOFOLLOW
+# define AT_SYMLINK_NOFOLLOW 0x80000000
+#endif
+
+int utimensat(int, const char *, const struct timespec[2], int);
+
+static void
+cleanup(void)
+{
+ (void)unlink(TMPFILE);
+ (void)unlink(TMPFILE2);
+}
+
+static void
+fail(char *msg, long expect, long got)
+{
+ int saved_errno = errno;
+
+ if (expect == got && got == 0)
+ fprintf(stderr, "utimensat: %s: %s\n", msg,
+ strerror(saved_errno));
+ else
+ fprintf(stderr, "utimensat: %s: expected %ld got %ld\n",
+ msg, expect, got);
+ cleanup();
+ exit(1);
+}
+
+int
+main(void)
+{
+ int fd;
+ struct stat sb;
+ struct timespec ts[2];
+
+ cleanup();
+ if ((fd = open(TMPFILE, O_CREAT, 0600)) == -1)
+ fail("open", 0, 0);
+ close(fd);
+
+ ts[0].tv_sec = 12345678;
+ ts[0].tv_nsec = 23456789;
+ ts[1].tv_sec = 34567890;
+ ts[1].tv_nsec = 45678901;
+ if (utimensat(AT_FDCWD, TMPFILE, ts, AT_SYMLINK_NOFOLLOW) == -1)
+ fail("utimensat", 0, 0);
+
+ if (stat(TMPFILE, &sb) == -1)
+ fail("stat", 0, 0 );
+ if (sb.st_atime != 12345678)
+ fail("st_atime", 0, 0 );
+ if (sb.st_mtime != 34567890)
+ fail("st_mtime", 0, 0 );
+#if 0
+ /*
+ * Results expected to be rounded to the nearest microsecond.
+ * Depends on timestamp precision in kernel and filesystem so
+ * disabled by default.
+ */
+ if (sb.st_atim.tv_nsec != 23456000)
+ fail("atim.tv_nsec", 23456000, sb.st_atim.tv_nsec);
+ if (sb.st_mtim.tv_nsec != 45678000)
+ fail("mtim.tv_nsec", 45678000, sb.st_mtim.tv_nsec);
+#endif
+
+ /*
+ * POSIX specifies that when given a symlink, AT_SYMLINK_NOFOLLOW
+ * should update the symlink and not the destination. The compat
+ * code doesn't have a way to do this, so where possible it fails
+ * with instead of following a symlink when explicitly asked not to.
+ * Here we just test that it does not update the destination.
+ */
+ if (rename(TMPFILE, TMPFILE2) == -1)
+ fail("rename", 0, 0);
+ if (symlink(TMPFILE2, TMPFILE) == -1)
+ fail("symlink", 0, 0);
+ ts[0].tv_sec = 11223344;
+ ts[1].tv_sec = 55667788;
+ (void)utimensat(AT_FDCWD, TMPFILE, ts, AT_SYMLINK_NOFOLLOW);
+ if (stat(TMPFILE2, &sb) == -1)
+ fail("stat", 0, 0 );
+ if (sb.st_atime == 11223344)
+ fail("utimensat symlink st_atime", 0, 0 );
+ if (sb.st_mtime == 55667788)
+ fail("utimensat symlink st_mtime", 0, 0 );
+
+ cleanup();
+ exit(0);
+}
diff --git a/openbsd-compat/rmd160.c b/openbsd-compat/rmd160.c
deleted file mode 100644
index 2a14dd7b..00000000
--- a/openbsd-compat/rmd160.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * Preneel, Bosselaers, Dobbertin, "The Cryptographic Hash Function RIPEMD-160",
- * RSA Laboratories, CryptoBytes, Volume 3, Number 2, Autumn 1997,
- * ftp://ftp.rsasecurity.com/pub/cryptobytes/crypto3n2.pdf
- */
-
-#include "includes.h"
-
-#ifndef WITH_OPENSSL
-
-#include <sys/types.h>
-#include <endian.h>
-#include <string.h>
-#include <rmd160.h>
-
-#define PUT_64BIT_LE(cp, value) do { \
- (cp)[7] = (value) >> 56; \
- (cp)[6] = (value) >> 48; \
- (cp)[5] = (value) >> 40; \
- (cp)[4] = (value) >> 32; \
- (cp)[3] = (value) >> 24; \
- (cp)[2] = (value) >> 16; \
- (cp)[1] = (value) >> 8; \
- (cp)[0] = (value); } while (0)
-
-#define PUT_32BIT_LE(cp, value) do { \
- (cp)[3] = (value) >> 24; \
- (cp)[2] = (value) >> 16; \
- (cp)[1] = (value) >> 8; \
- (cp)[0] = (value); } while (0)
-
-#define H0 0x67452301U
-#define H1 0xEFCDAB89U
-#define H2 0x98BADCFEU
-#define H3 0x10325476U
-#define H4 0xC3D2E1F0U
-
-#define K0 0x00000000U
-#define K1 0x5A827999U
-#define K2 0x6ED9EBA1U
-#define K3 0x8F1BBCDCU
-#define K4 0xA953FD4EU
-
-#define KK0 0x50A28BE6U
-#define KK1 0x5C4DD124U
-#define KK2 0x6D703EF3U
-#define KK3 0x7A6D76E9U
-#define KK4 0x00000000U
-
-/* rotate x left n bits. */
-#define ROL(n, x) (((x) << (n)) | ((x) >> (32-(n))))
-
-#define F0(x, y, z) ((x) ^ (y) ^ (z))
-#define F1(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define F2(x, y, z) (((x) | (~y)) ^ (z))
-#define F3(x, y, z) (((x) & (z)) | ((y) & (~z)))
-#define F4(x, y, z) ((x) ^ ((y) | (~z)))
-
-#define R(a, b, c, d, e, Fj, Kj, sj, rj) \
- do { \
- a = ROL(sj, a + Fj(b,c,d) + X(rj) + Kj) + e; \
- c = ROL(10, c); \
- } while(0)
-
-#define X(i) x[i]
-
-static u_int8_t PADDING[RMD160_BLOCK_LENGTH] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-void
-RMD160Init(RMD160_CTX *ctx)
-{
- ctx->count = 0;
- ctx->state[0] = H0;
- ctx->state[1] = H1;
- ctx->state[2] = H2;
- ctx->state[3] = H3;
- ctx->state[4] = H4;
-}
-
-void
-RMD160Update(RMD160_CTX *ctx, const u_int8_t *input, size_t len)
-{
- size_t have, off, need;
-
- have = (ctx->count / 8) % RMD160_BLOCK_LENGTH;
- need = RMD160_BLOCK_LENGTH - have;
- ctx->count += 8 * len;
- off = 0;
-
- if (len >= need) {
- if (have) {
- memcpy(ctx->buffer + have, input, need);
- RMD160Transform(ctx->state, ctx->buffer);
- off = need;
- have = 0;
- }
- /* now the buffer is empty */
- while (off + RMD160_BLOCK_LENGTH <= len) {
- RMD160Transform(ctx->state, input+off);
- off += RMD160_BLOCK_LENGTH;
- }
- }
- if (off < len)
- memcpy(ctx->buffer + have, input+off, len-off);
-}
-
-void
-RMD160Pad(RMD160_CTX *ctx)
-{
- u_int8_t size[8];
- size_t padlen;
-
- PUT_64BIT_LE(size, ctx->count);
-
- /*
- * pad to RMD160_BLOCK_LENGTH byte blocks, at least one byte from
- * PADDING plus 8 bytes for the size
- */
- padlen = RMD160_BLOCK_LENGTH - ((ctx->count / 8) % RMD160_BLOCK_LENGTH);
- if (padlen < 1 + 8)
- padlen += RMD160_BLOCK_LENGTH;
- RMD160Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */
- RMD160Update(ctx, size, 8);
-}
-
-void
-RMD160Final(u_int8_t digest[RMD160_DIGEST_LENGTH], RMD160_CTX *ctx)
-{
- int i;
-
- RMD160Pad(ctx);
- for (i = 0; i < 5; i++)
- PUT_32BIT_LE(digest + i*4, ctx->state[i]);
- memset(ctx, 0, sizeof (*ctx));
-}
-
-void
-RMD160Transform(u_int32_t state[5], const u_int8_t block[RMD160_BLOCK_LENGTH])
-{
- u_int32_t a, b, c, d, e, aa, bb, cc, dd, ee, t, x[16];
-
-#if BYTE_ORDER == LITTLE_ENDIAN
- memcpy(x, block, RMD160_BLOCK_LENGTH);
-#else
- int i;
-
- for (i = 0; i < 16; i++)
- x[i] = (u_int32_t)(
- (u_int32_t)(block[i*4 + 0]) |
- (u_int32_t)(block[i*4 + 1]) << 8 |
- (u_int32_t)(block[i*4 + 2]) << 16 |
- (u_int32_t)(block[i*4 + 3]) << 24);
-#endif
-
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
-
- /* Round 1 */
- R(a, b, c, d, e, F0, K0, 11, 0);
- R(e, a, b, c, d, F0, K0, 14, 1);
- R(d, e, a, b, c, F0, K0, 15, 2);
- R(c, d, e, a, b, F0, K0, 12, 3);
- R(b, c, d, e, a, F0, K0, 5, 4);
- R(a, b, c, d, e, F0, K0, 8, 5);
- R(e, a, b, c, d, F0, K0, 7, 6);
- R(d, e, a, b, c, F0, K0, 9, 7);
- R(c, d, e, a, b, F0, K0, 11, 8);
- R(b, c, d, e, a, F0, K0, 13, 9);
- R(a, b, c, d, e, F0, K0, 14, 10);
- R(e, a, b, c, d, F0, K0, 15, 11);
- R(d, e, a, b, c, F0, K0, 6, 12);
- R(c, d, e, a, b, F0, K0, 7, 13);
- R(b, c, d, e, a, F0, K0, 9, 14);
- R(a, b, c, d, e, F0, K0, 8, 15); /* #15 */
- /* Round 2 */
- R(e, a, b, c, d, F1, K1, 7, 7);
- R(d, e, a, b, c, F1, K1, 6, 4);
- R(c, d, e, a, b, F1, K1, 8, 13);
- R(b, c, d, e, a, F1, K1, 13, 1);
- R(a, b, c, d, e, F1, K1, 11, 10);
- R(e, a, b, c, d, F1, K1, 9, 6);
- R(d, e, a, b, c, F1, K1, 7, 15);
- R(c, d, e, a, b, F1, K1, 15, 3);
- R(b, c, d, e, a, F1, K1, 7, 12);
- R(a, b, c, d, e, F1, K1, 12, 0);
- R(e, a, b, c, d, F1, K1, 15, 9);
- R(d, e, a, b, c, F1, K1, 9, 5);
- R(c, d, e, a, b, F1, K1, 11, 2);
- R(b, c, d, e, a, F1, K1, 7, 14);
- R(a, b, c, d, e, F1, K1, 13, 11);
- R(e, a, b, c, d, F1, K1, 12, 8); /* #31 */
- /* Round 3 */
- R(d, e, a, b, c, F2, K2, 11, 3);
- R(c, d, e, a, b, F2, K2, 13, 10);
- R(b, c, d, e, a, F2, K2, 6, 14);
- R(a, b, c, d, e, F2, K2, 7, 4);
- R(e, a, b, c, d, F2, K2, 14, 9);
- R(d, e, a, b, c, F2, K2, 9, 15);
- R(c, d, e, a, b, F2, K2, 13, 8);
- R(b, c, d, e, a, F2, K2, 15, 1);
- R(a, b, c, d, e, F2, K2, 14, 2);
- R(e, a, b, c, d, F2, K2, 8, 7);
- R(d, e, a, b, c, F2, K2, 13, 0);
- R(c, d, e, a, b, F2, K2, 6, 6);
- R(b, c, d, e, a, F2, K2, 5, 13);
- R(a, b, c, d, e, F2, K2, 12, 11);
- R(e, a, b, c, d, F2, K2, 7, 5);
- R(d, e, a, b, c, F2, K2, 5, 12); /* #47 */
- /* Round 4 */
- R(c, d, e, a, b, F3, K3, 11, 1);
- R(b, c, d, e, a, F3, K3, 12, 9);
- R(a, b, c, d, e, F3, K3, 14, 11);
- R(e, a, b, c, d, F3, K3, 15, 10);
- R(d, e, a, b, c, F3, K3, 14, 0);
- R(c, d, e, a, b, F3, K3, 15, 8);
- R(b, c, d, e, a, F3, K3, 9, 12);
- R(a, b, c, d, e, F3, K3, 8, 4);
- R(e, a, b, c, d, F3, K3, 9, 13);
- R(d, e, a, b, c, F3, K3, 14, 3);
- R(c, d, e, a, b, F3, K3, 5, 7);
- R(b, c, d, e, a, F3, K3, 6, 15);
- R(a, b, c, d, e, F3, K3, 8, 14);
- R(e, a, b, c, d, F3, K3, 6, 5);
- R(d, e, a, b, c, F3, K3, 5, 6);
- R(c, d, e, a, b, F3, K3, 12, 2); /* #63 */
- /* Round 5 */
- R(b, c, d, e, a, F4, K4, 9, 4);
- R(a, b, c, d, e, F4, K4, 15, 0);
- R(e, a, b, c, d, F4, K4, 5, 5);
- R(d, e, a, b, c, F4, K4, 11, 9);
- R(c, d, e, a, b, F4, K4, 6, 7);
- R(b, c, d, e, a, F4, K4, 8, 12);
- R(a, b, c, d, e, F4, K4, 13, 2);
- R(e, a, b, c, d, F4, K4, 12, 10);
- R(d, e, a, b, c, F4, K4, 5, 14);
- R(c, d, e, a, b, F4, K4, 12, 1);
- R(b, c, d, e, a, F4, K4, 13, 3);
- R(a, b, c, d, e, F4, K4, 14, 8);
- R(e, a, b, c, d, F4, K4, 11, 11);
- R(d, e, a, b, c, F4, K4, 8, 6);
- R(c, d, e, a, b, F4, K4, 5, 15);
- R(b, c, d, e, a, F4, K4, 6, 13); /* #79 */
-
- aa = a ; bb = b; cc = c; dd = d; ee = e;
-
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
-
- /* Parallel round 1 */
- R(a, b, c, d, e, F4, KK0, 8, 5);
- R(e, a, b, c, d, F4, KK0, 9, 14);
- R(d, e, a, b, c, F4, KK0, 9, 7);
- R(c, d, e, a, b, F4, KK0, 11, 0);
- R(b, c, d, e, a, F4, KK0, 13, 9);
- R(a, b, c, d, e, F4, KK0, 15, 2);
- R(e, a, b, c, d, F4, KK0, 15, 11);
- R(d, e, a, b, c, F4, KK0, 5, 4);
- R(c, d, e, a, b, F4, KK0, 7, 13);
- R(b, c, d, e, a, F4, KK0, 7, 6);
- R(a, b, c, d, e, F4, KK0, 8, 15);
- R(e, a, b, c, d, F4, KK0, 11, 8);
- R(d, e, a, b, c, F4, KK0, 14, 1);
- R(c, d, e, a, b, F4, KK0, 14, 10);
- R(b, c, d, e, a, F4, KK0, 12, 3);
- R(a, b, c, d, e, F4, KK0, 6, 12); /* #15 */
- /* Parallel round 2 */
- R(e, a, b, c, d, F3, KK1, 9, 6);
- R(d, e, a, b, c, F3, KK1, 13, 11);
- R(c, d, e, a, b, F3, KK1, 15, 3);
- R(b, c, d, e, a, F3, KK1, 7, 7);
- R(a, b, c, d, e, F3, KK1, 12, 0);
- R(e, a, b, c, d, F3, KK1, 8, 13);
- R(d, e, a, b, c, F3, KK1, 9, 5);
- R(c, d, e, a, b, F3, KK1, 11, 10);
- R(b, c, d, e, a, F3, KK1, 7, 14);
- R(a, b, c, d, e, F3, KK1, 7, 15);
- R(e, a, b, c, d, F3, KK1, 12, 8);
- R(d, e, a, b, c, F3, KK1, 7, 12);
- R(c, d, e, a, b, F3, KK1, 6, 4);
- R(b, c, d, e, a, F3, KK1, 15, 9);
- R(a, b, c, d, e, F3, KK1, 13, 1);
- R(e, a, b, c, d, F3, KK1, 11, 2); /* #31 */
- /* Parallel round 3 */
- R(d, e, a, b, c, F2, KK2, 9, 15);
- R(c, d, e, a, b, F2, KK2, 7, 5);
- R(b, c, d, e, a, F2, KK2, 15, 1);
- R(a, b, c, d, e, F2, KK2, 11, 3);
- R(e, a, b, c, d, F2, KK2, 8, 7);
- R(d, e, a, b, c, F2, KK2, 6, 14);
- R(c, d, e, a, b, F2, KK2, 6, 6);
- R(b, c, d, e, a, F2, KK2, 14, 9);
- R(a, b, c, d, e, F2, KK2, 12, 11);
- R(e, a, b, c, d, F2, KK2, 13, 8);
- R(d, e, a, b, c, F2, KK2, 5, 12);
- R(c, d, e, a, b, F2, KK2, 14, 2);
- R(b, c, d, e, a, F2, KK2, 13, 10);
- R(a, b, c, d, e, F2, KK2, 13, 0);
- R(e, a, b, c, d, F2, KK2, 7, 4);
- R(d, e, a, b, c, F2, KK2, 5, 13); /* #47 */
- /* Parallel round 4 */
- R(c, d, e, a, b, F1, KK3, 15, 8);
- R(b, c, d, e, a, F1, KK3, 5, 6);
- R(a, b, c, d, e, F1, KK3, 8, 4);
- R(e, a, b, c, d, F1, KK3, 11, 1);
- R(d, e, a, b, c, F1, KK3, 14, 3);
- R(c, d, e, a, b, F1, KK3, 14, 11);
- R(b, c, d, e, a, F1, KK3, 6, 15);
- R(a, b, c, d, e, F1, KK3, 14, 0);
- R(e, a, b, c, d, F1, KK3, 6, 5);
- R(d, e, a, b, c, F1, KK3, 9, 12);
- R(c, d, e, a, b, F1, KK3, 12, 2);
- R(b, c, d, e, a, F1, KK3, 9, 13);
- R(a, b, c, d, e, F1, KK3, 12, 9);
- R(e, a, b, c, d, F1, KK3, 5, 7);
- R(d, e, a, b, c, F1, KK3, 15, 10);
- R(c, d, e, a, b, F1, KK3, 8, 14); /* #63 */
- /* Parallel round 5 */
- R(b, c, d, e, a, F0, KK4, 8, 12);
- R(a, b, c, d, e, F0, KK4, 5, 15);
- R(e, a, b, c, d, F0, KK4, 12, 10);
- R(d, e, a, b, c, F0, KK4, 9, 4);
- R(c, d, e, a, b, F0, KK4, 12, 1);
- R(b, c, d, e, a, F0, KK4, 5, 5);
- R(a, b, c, d, e, F0, KK4, 14, 8);
- R(e, a, b, c, d, F0, KK4, 6, 7);
- R(d, e, a, b, c, F0, KK4, 8, 6);
- R(c, d, e, a, b, F0, KK4, 13, 2);
- R(b, c, d, e, a, F0, KK4, 6, 13);
- R(a, b, c, d, e, F0, KK4, 5, 14);
- R(e, a, b, c, d, F0, KK4, 15, 0);
- R(d, e, a, b, c, F0, KK4, 13, 3);
- R(c, d, e, a, b, F0, KK4, 11, 9);
- R(b, c, d, e, a, F0, KK4, 11, 11); /* #79 */
-
- t = state[1] + cc + d;
- state[1] = state[2] + dd + e;
- state[2] = state[3] + ee + a;
- state[3] = state[4] + aa + b;
- state[4] = state[0] + bb + c;
- state[0] = t;
-}
-
-#endif /* !WITH_OPENSSL */
diff --git a/openbsd-compat/rmd160.h b/openbsd-compat/rmd160.h
deleted file mode 100644
index 99c1dcdc..00000000
--- a/openbsd-compat/rmd160.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* $OpenBSD: rmd160.h,v 1.17 2012/12/05 23:19:57 deraadt Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _RMD160_H
-#define _RMD160_H
-
-#ifndef WITH_OPENSSL
-
-#define RMD160_BLOCK_LENGTH 64
-#define RMD160_DIGEST_LENGTH 20
-#define RMD160_DIGEST_STRING_LENGTH (RMD160_DIGEST_LENGTH * 2 + 1)
-
-/* RMD160 context. */
-typedef struct RMD160Context {
- u_int32_t state[5]; /* state */
- u_int64_t count; /* number of bits, mod 2^64 */
- u_int8_t buffer[RMD160_BLOCK_LENGTH]; /* input buffer */
-} RMD160_CTX;
-
-void RMD160Init(RMD160_CTX *);
-void RMD160Transform(u_int32_t [5], const u_int8_t [RMD160_BLOCK_LENGTH])
- __attribute__((__bounded__(__minbytes__,1,5)))
- __attribute__((__bounded__(__minbytes__,2,RMD160_BLOCK_LENGTH)));
-void RMD160Update(RMD160_CTX *, const u_int8_t *, size_t)
- __attribute__((__bounded__(__string__,2,3)));
-void RMD160Pad(RMD160_CTX *);
-void RMD160Final(u_int8_t [RMD160_DIGEST_LENGTH], RMD160_CTX *)
- __attribute__((__bounded__(__minbytes__,1,RMD160_DIGEST_LENGTH)));
-char *RMD160End(RMD160_CTX *, char *)
- __attribute__((__bounded__(__minbytes__,2,RMD160_DIGEST_STRING_LENGTH)));
-char *RMD160File(const char *, char *)
- __attribute__((__bounded__(__minbytes__,2,RMD160_DIGEST_STRING_LENGTH)));
-char *RMD160FileChunk(const char *, char *, off_t, off_t)
- __attribute__((__bounded__(__minbytes__,2,RMD160_DIGEST_STRING_LENGTH)));
-char *RMD160Data(const u_int8_t *, size_t, char *)
- __attribute__((__bounded__(__string__,1,2)))
- __attribute__((__bounded__(__minbytes__,3,RMD160_DIGEST_STRING_LENGTH)));
-
-#endif /* !WITH_OPENSSL */
-#endif /* _RMD160_H */
diff --git a/openbsd-compat/setproctitle.c b/openbsd-compat/setproctitle.c
index 9f7ca14c..e4064323 100644
--- a/openbsd-compat/setproctitle.c
+++ b/openbsd-compat/setproctitle.c
@@ -36,6 +36,7 @@
#ifndef HAVE_SETPROCTITLE
#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef HAVE_SYS_PSTAT_H
@@ -76,7 +77,7 @@ compat_init_setproctitle(int argc, char *argv[])
/*
* NB: This assumes that argv has already been copied out of the
- * way. This is true for sshd, but may not be true for other
+ * way. This is true for sshd, but may not be true for other
* programs. Beware.
*/
@@ -92,7 +93,7 @@ compat_init_setproctitle(int argc, char *argv[])
}
/*
- * Find the last argv string or environment variable within
+ * Find the last argv string or environment variable within
* our process memory area.
*/
for (i = 0; i < argc; i++) {
@@ -108,8 +109,8 @@ compat_init_setproctitle(int argc, char *argv[])
argv_start = argv[0];
argv_env_len = lastargv - argv[0] - 1;
- /*
- * Copy environment
+ /*
+ * Copy environment
* XXX - will truncate env on strdup fail
*/
for (i = 0; envp[i] != NULL; i++)
@@ -125,7 +126,7 @@ setproctitle(const char *fmt, ...)
#if SPT_TYPE != SPT_NONE
va_list ap;
char buf[1024], ptitle[1024];
- size_t len;
+ size_t len = 0;
int r;
extern char *__progname;
#if SPT_TYPE == SPT_PSTAT
@@ -156,7 +157,7 @@ setproctitle(const char *fmt, ...)
pst.pst_command = ptitle;
pstat(PSTAT_SETCMD, pst, strlen(ptitle), 0, 0);
#elif SPT_TYPE == SPT_REUSEARGV
-/* debug("setproctitle: copy \"%s\" into len %d",
+/* debug("setproctitle: copy \"%s\" into len %d",
buf, argv_env_len); */
len = strlcpy(argv_start, ptitle, argv_env_len);
for(; len < argv_env_len; len++)
diff --git a/openbsd-compat/sha1.c b/openbsd-compat/sha1.c
index 4b5381f8..73f89748 100644
--- a/openbsd-compat/sha1.c
+++ b/openbsd-compat/sha1.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sha1.c,v 1.23 2014/01/08 06:14:57 tedu Exp $ */
+/* $OpenBSD: sha1.c,v 1.27 2019/06/07 22:56:36 dtucker Exp $ */
/*
* SHA-1 in C
@@ -18,7 +18,7 @@
#ifndef WITH_OPENSSL
-#include <sys/param.h>
+#include <sys/types.h>
#include <string.h>
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
@@ -101,6 +101,7 @@ SHA1Transform(u_int32_t state[5], const u_int8_t buffer[SHA1_BLOCK_LENGTH])
/* Wipe variables */
a = b = c = d = e = 0;
}
+DEF_WEAK(SHA1Transform);
/*
@@ -118,6 +119,7 @@ SHA1Init(SHA1_CTX *context)
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
}
+DEF_WEAK(SHA1Init);
/*
@@ -129,7 +131,7 @@ SHA1Update(SHA1_CTX *context, const u_int8_t *data, size_t len)
size_t i, j;
j = (size_t)((context->count >> 3) & 63);
- context->count += (len << 3);
+ context->count += ((u_int64_t)len << 3);
if ((j + len) > 63) {
(void)memcpy(&context->buffer[j], data, (i = 64-j));
SHA1Transform(context->state, context->buffer);
@@ -141,6 +143,7 @@ SHA1Update(SHA1_CTX *context, const u_int8_t *data, size_t len)
}
(void)memcpy(&context->buffer[j], &data[i], len - i);
}
+DEF_WEAK(SHA1Update);
/*
@@ -161,6 +164,7 @@ SHA1Pad(SHA1_CTX *context)
SHA1Update(context, (u_int8_t *)"\0", 1);
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
}
+DEF_WEAK(SHA1Pad);
void
SHA1Final(u_int8_t digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context)
@@ -172,6 +176,7 @@ SHA1Final(u_int8_t digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context)
digest[i] = (u_int8_t)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
- memset(context, 0, sizeof(*context));
+ explicit_bzero(context, sizeof(*context));
}
+DEF_WEAK(SHA1Final);
#endif /* !WITH_OPENSSL */
diff --git a/openbsd-compat/sha2.c b/openbsd-compat/sha2.c
index 737935d4..e36cc24e 100644
--- a/openbsd-compat/sha2.c
+++ b/openbsd-compat/sha2.c
@@ -1,4 +1,4 @@
-/* from OpenBSD: sha2.c,v 1.11 2005/08/08 08:05:35 espie Exp */
+/* $OpenBSD: sha2.c,v 1.28 2019/07/23 12:35:22 dtucker Exp $ */
/*
* FILE: sha2.c
@@ -38,18 +38,14 @@
#include "includes.h"
-#ifdef WITH_OPENSSL
-# include <openssl/opensslv.h>
-# if !defined(HAVE_EVP_SHA256) && (OPENSSL_VERSION_NUMBER >= 0x00907000L)
-# define _NEED_SHA2 1
-# endif
-#else
-# define _NEED_SHA2 1
-#endif
+#if !defined(HAVE_SHA256UPDATE) || !defined(HAVE_SHA384UPDATE) || \
+ !defined(HAVE_SHA512UPDATE)
-#if defined(_NEED_SHA2) && !defined(HAVE_SHA256_UPDATE)
+/* no-op out, similar to DEF_WEAK but only needed here */
+#define MAKE_CLONE(x, y) void __ssh_compat_make_clone_##x_##y(void)
#include <string.h>
+#include <sha2.h>
/*
* UNROLLED TRANSFORM LOOP NOTE:
@@ -64,15 +60,20 @@
* #define SHA2_UNROLL_TRANSFORM
*
*/
+#ifndef SHA2_SMALL
+#if defined(__amd64__) || defined(__i386__)
+#define SHA2_UNROLL_TRANSFORM
+#endif
+#endif
-/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+/*** SHA-224/256/384/512 Machine Architecture Definitions *****************/
/*
* BYTE_ORDER NOTE:
*
* Please make sure that your system defines BYTE_ORDER. If your
* architecture is little-endian, make sure it also defines
* LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
- * equivilent.
+ * equivalent.
*
* If your system does not define the above, then you can do so by
* hand like this:
@@ -98,8 +99,9 @@
#endif
-/*** SHA-256/384/512 Various Length Definitions ***********************/
+/*** SHA-224/256/384/512 Various Length Definitions ***********************/
/* NOTE: Most of these are in sha2.h */
+#define SHA224_SHORT_BLOCK_LENGTH (SHA224_BLOCK_LENGTH - 8)
#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16)
#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
@@ -152,22 +154,22 @@
* Bit shifting and rotation (used by the six SHA-XYZ logical functions:
*
* NOTE: The naming of R and S appears backwards here (R is a SHIFT and
- * S is a ROTATION) because the SHA-256/384/512 description document
+ * S is a ROTATION) because the SHA-224/256/384/512 description document
* (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
* same "backwards" definition.
*/
-/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+/* Shift-right (used in SHA-224, SHA-256, SHA-384, and SHA-512): */
#define R(b,x) ((x) >> (b))
-/* 32-bit Rotate-right (used in SHA-256): */
+/* 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): */
#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b))))
-/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+/* Two of six logical functions used in SHA-224, SHA-256, SHA-384, and SHA-512: */
#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
-/* Four of six logical functions used in SHA-256: */
+/* Four of six logical functions used in SHA-224 and SHA-256: */
#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x)))
#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x)))
#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x)))
@@ -181,8 +183,8 @@
/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
-/* Hash constant words K for SHA-256: */
-const static u_int32_t K256[64] = {
+/* Hash constant words K for SHA-224 and SHA-256: */
+static const u_int32_t K256[64] = {
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
@@ -202,7 +204,7 @@ const static u_int32_t K256[64] = {
};
/* Initial hash value H for SHA-256: */
-const static u_int32_t sha256_initial_hash_value[8] = {
+static const u_int32_t sha256_initial_hash_value[8] = {
0x6a09e667UL,
0xbb67ae85UL,
0x3c6ef372UL,
@@ -214,7 +216,7 @@ const static u_int32_t sha256_initial_hash_value[8] = {
};
/* Hash constant words K for SHA-384 and SHA-512: */
-const static u_int64_t K512[80] = {
+static const u_int64_t K512[80] = {
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
@@ -257,8 +259,35 @@ const static u_int64_t K512[80] = {
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
};
+/* Initial hash value H for SHA-512 */
+static const u_int64_t sha512_initial_hash_value[8] = {
+ 0x6a09e667f3bcc908ULL,
+ 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL,
+ 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL,
+ 0x5be0cd19137e2179ULL
+};
+
+#if !defined(SHA2_SMALL)
+#if 0
+/* Initial hash value H for SHA-224: */
+static const u_int32_t sha224_initial_hash_value[8] = {
+ 0xc1059ed8UL,
+ 0x367cd507UL,
+ 0x3070dd17UL,
+ 0xf70e5939UL,
+ 0xffc00b31UL,
+ 0x68581511UL,
+ 0x64f98fa7UL,
+ 0xbefa4fa4UL
+};
+#endif /* 0 */
+
/* Initial hash value H for SHA-384 */
-const static u_int64_t sha384_initial_hash_value[8] = {
+static const u_int64_t sha384_initial_hash_value[8] = {
0xcbbb9d5dc1059ed8ULL,
0x629a292a367cd507ULL,
0x9159015a3070dd17ULL,
@@ -269,30 +298,67 @@ const static u_int64_t sha384_initial_hash_value[8] = {
0x47b5481dbefa4fa4ULL
};
-/* Initial hash value H for SHA-512 */
-const static u_int64_t sha512_initial_hash_value[8] = {
- 0x6a09e667f3bcc908ULL,
- 0xbb67ae8584caa73bULL,
- 0x3c6ef372fe94f82bULL,
- 0xa54ff53a5f1d36f1ULL,
- 0x510e527fade682d1ULL,
- 0x9b05688c2b3e6c1fULL,
- 0x1f83d9abfb41bd6bULL,
- 0x5be0cd19137e2179ULL
+#if 0
+/* Initial hash value H for SHA-512-256 */
+static const u_int64_t sha512_256_initial_hash_value[8] = {
+ 0x22312194fc2bf72cULL,
+ 0x9f555fa3c84c64c2ULL,
+ 0x2393b86b6f53b151ULL,
+ 0x963877195940eabdULL,
+ 0x96283ee2a88effe3ULL,
+ 0xbe5e1e2553863992ULL,
+ 0x2b0199fc2c85b8aaULL,
+ 0x0eb72ddc81c52ca2ULL
};
+/*** SHA-224: *********************************************************/
+void
+SHA224Init(SHA2_CTX *context)
+{
+ memcpy(context->state.st32, sha224_initial_hash_value,
+ sizeof(sha224_initial_hash_value));
+ memset(context->buffer, 0, sizeof(context->buffer));
+ context->bitcount[0] = 0;
+}
+DEF_WEAK(SHA224Init);
+
+MAKE_CLONE(SHA224Transform, SHA256Transform);
+MAKE_CLONE(SHA224Update, SHA256Update);
+MAKE_CLONE(SHA224Pad, SHA256Pad);
+DEF_WEAK(SHA224Transform);
+DEF_WEAK(SHA224Update);
+DEF_WEAK(SHA224Pad);
+
+void
+SHA224Final(u_int8_t digest[SHA224_DIGEST_LENGTH], SHA2_CTX *context)
+{
+ SHA224Pad(context);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ int i;
+
+ /* Convert TO host byte order */
+ for (i = 0; i < 7; i++)
+ BE_32_TO_8(digest + i * 4, context->state.st32[i]);
+#else
+ memcpy(digest, context->state.st32, SHA224_DIGEST_LENGTH);
+#endif
+ explicit_bzero(context, sizeof(*context));
+}
+DEF_WEAK(SHA224Final);
+#endif /* !defined(SHA2_SMALL) */
+#endif /* 0 */
/*** SHA-256: *********************************************************/
void
-SHA256_Init(SHA256_CTX *context)
+SHA256Init(SHA2_CTX *context)
{
- if (context == NULL)
- return;
- memcpy(context->state, sha256_initial_hash_value,
+ memcpy(context->state.st32, sha256_initial_hash_value,
sizeof(sha256_initial_hash_value));
memset(context->buffer, 0, sizeof(context->buffer));
- context->bitcount = 0;
+ context->bitcount[0] = 0;
}
+DEF_WEAK(SHA256Init);
#ifdef SHA2_UNROLL_TRANSFORM
@@ -320,7 +386,7 @@ SHA256_Init(SHA256_CTX *context)
} while(0)
void
-SHA256_Transform(u_int32_t state[8], const u_int8_t data[SHA256_BLOCK_LENGTH])
+SHA256Transform(u_int32_t state[8], const u_int8_t data[SHA256_BLOCK_LENGTH])
{
u_int32_t a, b, c, d, e, f, g, h, s0, s1;
u_int32_t T1, W256[16];
@@ -378,7 +444,7 @@ SHA256_Transform(u_int32_t state[8], const u_int8_t data[SHA256_BLOCK_LENGTH])
#else /* SHA2_UNROLL_TRANSFORM */
void
-SHA256_Transform(u_int32_t state[8], const u_int8_t data[SHA256_BLOCK_LENGTH])
+SHA256Transform(u_int32_t state[8], const u_int8_t data[SHA256_BLOCK_LENGTH])
{
u_int32_t a, b, c, d, e, f, g, h, s0, s1;
u_int32_t T1, T2, W256[16];
@@ -451,17 +517,18 @@ SHA256_Transform(u_int32_t state[8], const u_int8_t data[SHA256_BLOCK_LENGTH])
}
#endif /* SHA2_UNROLL_TRANSFORM */
+DEF_WEAK(SHA256Transform);
void
-SHA256_Update(SHA256_CTX *context, const u_int8_t *data, size_t len)
+SHA256Update(SHA2_CTX *context, const u_int8_t *data, size_t len)
{
- size_t freespace, usedspace;
+ u_int64_t freespace, usedspace;
/* Calling with no data is valid (we do nothing) */
if (len == 0)
return;
- usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+ usedspace = (context->bitcount[0] >> 3) % SHA256_BLOCK_LENGTH;
if (usedspace > 0) {
/* Calculate how much free space is available in the buffer */
freespace = SHA256_BLOCK_LENGTH - usedspace;
@@ -469,14 +536,14 @@ SHA256_Update(SHA256_CTX *context, const u_int8_t *data, size_t len)
if (len >= freespace) {
/* Fill the buffer completely and process it */
memcpy(&context->buffer[usedspace], data, freespace);
- context->bitcount += freespace << 3;
+ context->bitcount[0] += freespace << 3;
len -= freespace;
data += freespace;
- SHA256_Transform(context->state, context->buffer);
+ SHA256Transform(context->state.st32, context->buffer);
} else {
/* The buffer is not yet full */
memcpy(&context->buffer[usedspace], data, len);
- context->bitcount += len << 3;
+ context->bitcount[0] += (u_int64_t)len << 3;
/* Clean up: */
usedspace = freespace = 0;
return;
@@ -484,26 +551,27 @@ SHA256_Update(SHA256_CTX *context, const u_int8_t *data, size_t len)
}
while (len >= SHA256_BLOCK_LENGTH) {
/* Process as many complete blocks as we can */
- SHA256_Transform(context->state, data);
- context->bitcount += SHA256_BLOCK_LENGTH << 3;
+ SHA256Transform(context->state.st32, data);
+ context->bitcount[0] += SHA256_BLOCK_LENGTH << 3;
len -= SHA256_BLOCK_LENGTH;
data += SHA256_BLOCK_LENGTH;
}
if (len > 0) {
/* There's left-overs, so save 'em */
memcpy(context->buffer, data, len);
- context->bitcount += len << 3;
+ context->bitcount[0] += len << 3;
}
/* Clean up: */
usedspace = freespace = 0;
}
+DEF_WEAK(SHA256Update);
void
-SHA256_Pad(SHA256_CTX *context)
+SHA256Pad(SHA2_CTX *context)
{
unsigned int usedspace;
- usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+ usedspace = (context->bitcount[0] >> 3) % SHA256_BLOCK_LENGTH;
if (usedspace > 0) {
/* Begin padding with a 1 bit: */
context->buffer[usedspace++] = 0x80;
@@ -518,7 +586,7 @@ SHA256_Pad(SHA256_CTX *context)
SHA256_BLOCK_LENGTH - usedspace);
}
/* Do second-to-last transform: */
- SHA256_Transform(context->state, context->buffer);
+ SHA256Transform(context->state.st32, context->buffer);
/* Prepare for last transform: */
memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);
@@ -532,47 +600,45 @@ SHA256_Pad(SHA256_CTX *context)
}
/* Store the length of input data (in bits) in big endian format: */
BE_64_TO_8(&context->buffer[SHA256_SHORT_BLOCK_LENGTH],
- context->bitcount);
+ context->bitcount[0]);
/* Final transform: */
- SHA256_Transform(context->state, context->buffer);
+ SHA256Transform(context->state.st32, context->buffer);
/* Clean up: */
usedspace = 0;
}
+DEF_WEAK(SHA256Pad);
void
-SHA256_Final(u_int8_t digest[SHA256_DIGEST_LENGTH], SHA256_CTX *context)
+SHA256Final(u_int8_t digest[SHA256_DIGEST_LENGTH], SHA2_CTX *context)
{
- SHA256_Pad(context);
+ SHA256Pad(context);
- /* If no digest buffer is passed, we don't bother doing this: */
- if (digest != NULL) {
#if BYTE_ORDER == LITTLE_ENDIAN
- int i;
+ int i;
- /* Convert TO host byte order */
- for (i = 0; i < 8; i++)
- BE_32_TO_8(digest + i * 4, context->state[i]);
+ /* Convert TO host byte order */
+ for (i = 0; i < 8; i++)
+ BE_32_TO_8(digest + i * 4, context->state.st32[i]);
#else
- memcpy(digest, context->state, SHA256_DIGEST_LENGTH);
+ memcpy(digest, context->state.st32, SHA256_DIGEST_LENGTH);
#endif
- memset(context, 0, sizeof(*context));
- }
+ explicit_bzero(context, sizeof(*context));
}
+DEF_WEAK(SHA256Final);
/*** SHA-512: *********************************************************/
void
-SHA512_Init(SHA512_CTX *context)
+SHA512Init(SHA2_CTX *context)
{
- if (context == NULL)
- return;
- memcpy(context->state, sha512_initial_hash_value,
+ memcpy(context->state.st64, sha512_initial_hash_value,
sizeof(sha512_initial_hash_value));
memset(context->buffer, 0, sizeof(context->buffer));
context->bitcount[0] = context->bitcount[1] = 0;
}
+DEF_WEAK(SHA512Init);
#ifdef SHA2_UNROLL_TRANSFORM
@@ -601,7 +667,7 @@ SHA512_Init(SHA512_CTX *context)
} while(0)
void
-SHA512_Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
+SHA512Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
{
u_int64_t a, b, c, d, e, f, g, h, s0, s1;
u_int64_t T1, W512[16];
@@ -659,7 +725,7 @@ SHA512_Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
#else /* SHA2_UNROLL_TRANSFORM */
void
-SHA512_Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
+SHA512Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
{
u_int64_t a, b, c, d, e, f, g, h, s0, s1;
u_int64_t T1, T2, W512[16];
@@ -732,9 +798,10 @@ SHA512_Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
}
#endif /* SHA2_UNROLL_TRANSFORM */
+DEF_WEAK(SHA512Transform);
void
-SHA512_Update(SHA512_CTX *context, const u_int8_t *data, size_t len)
+SHA512Update(SHA2_CTX *context, const u_int8_t *data, size_t len)
{
size_t freespace, usedspace;
@@ -753,7 +820,7 @@ SHA512_Update(SHA512_CTX *context, const u_int8_t *data, size_t len)
ADDINC128(context->bitcount, freespace << 3);
len -= freespace;
data += freespace;
- SHA512_Transform(context->state, context->buffer);
+ SHA512Transform(context->state.st64, context->buffer);
} else {
/* The buffer is not yet full */
memcpy(&context->buffer[usedspace], data, len);
@@ -765,7 +832,7 @@ SHA512_Update(SHA512_CTX *context, const u_int8_t *data, size_t len)
}
while (len >= SHA512_BLOCK_LENGTH) {
/* Process as many complete blocks as we can */
- SHA512_Transform(context->state, data);
+ SHA512Transform(context->state.st64, data);
ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
len -= SHA512_BLOCK_LENGTH;
data += SHA512_BLOCK_LENGTH;
@@ -778,9 +845,10 @@ SHA512_Update(SHA512_CTX *context, const u_int8_t *data, size_t len)
/* Clean up: */
usedspace = freespace = 0;
}
+DEF_WEAK(SHA512Update);
void
-SHA512_Pad(SHA512_CTX *context)
+SHA512Pad(SHA2_CTX *context)
{
unsigned int usedspace;
@@ -797,7 +865,7 @@ SHA512_Pad(SHA512_CTX *context)
memset(&context->buffer[usedspace], 0, SHA512_BLOCK_LENGTH - usedspace);
}
/* Do second-to-last transform: */
- SHA512_Transform(context->state, context->buffer);
+ SHA512Transform(context->state.st64, context->buffer);
/* And set-up for the last transform: */
memset(context->buffer, 0, SHA512_BLOCK_LENGTH - 2);
@@ -816,89 +884,127 @@ SHA512_Pad(SHA512_CTX *context)
context->bitcount[0]);
/* Final transform: */
- SHA512_Transform(context->state, context->buffer);
+ SHA512Transform(context->state.st64, context->buffer);
/* Clean up: */
usedspace = 0;
}
+DEF_WEAK(SHA512Pad);
void
-SHA512_Final(u_int8_t digest[SHA512_DIGEST_LENGTH], SHA512_CTX *context)
+SHA512Final(u_int8_t digest[SHA512_DIGEST_LENGTH], SHA2_CTX *context)
{
- SHA512_Pad(context);
+ SHA512Pad(context);
- /* If no digest buffer is passed, we don't bother doing this: */
- if (digest != NULL) {
#if BYTE_ORDER == LITTLE_ENDIAN
- int i;
+ int i;
- /* Convert TO host byte order */
- for (i = 0; i < 8; i++)
- BE_64_TO_8(digest + i * 8, context->state[i]);
+ /* Convert TO host byte order */
+ for (i = 0; i < 8; i++)
+ BE_64_TO_8(digest + i * 8, context->state.st64[i]);
#else
- memcpy(digest, context->state, SHA512_DIGEST_LENGTH);
+ memcpy(digest, context->state.st64, SHA512_DIGEST_LENGTH);
#endif
- memset(context, 0, sizeof(*context));
- }
+ explicit_bzero(context, sizeof(*context));
}
+DEF_WEAK(SHA512Final);
+#if !defined(SHA2_SMALL)
/*** SHA-384: *********************************************************/
void
-SHA384_Init(SHA384_CTX *context)
+SHA384Init(SHA2_CTX *context)
{
- if (context == NULL)
- return;
- memcpy(context->state, sha384_initial_hash_value,
+ memcpy(context->state.st64, sha384_initial_hash_value,
sizeof(sha384_initial_hash_value));
memset(context->buffer, 0, sizeof(context->buffer));
context->bitcount[0] = context->bitcount[1] = 0;
}
+DEF_WEAK(SHA384Init);
-#if 0
-__weak_alias(SHA384_Transform, SHA512_Transform);
-__weak_alias(SHA384_Update, SHA512_Update);
-__weak_alias(SHA384_Pad, SHA512_Pad);
-#endif
+MAKE_CLONE(SHA384Transform, SHA512Transform);
+MAKE_CLONE(SHA384Update, SHA512Update);
+MAKE_CLONE(SHA384Pad, SHA512Pad);
+DEF_WEAK(SHA384Transform);
+DEF_WEAK(SHA384Update);
+DEF_WEAK(SHA384Pad);
+/* Equivalent of MAKE_CLONE (which is a no-op) for SHA384 funcs */
void
-SHA384_Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
+SHA384Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
{
- return SHA512_Transform(state, data);
+ SHA512Transform(state, data);
}
void
-SHA384_Update(SHA512_CTX *context, const u_int8_t *data, size_t len)
+SHA384Update(SHA2_CTX *context, const u_int8_t *data, size_t len)
{
- SHA512_Update(context, data, len);
+ SHA512Update(context, data, len);
}
void
-SHA384_Pad(SHA512_CTX *context)
+SHA384Pad(SHA2_CTX *context)
{
- SHA512_Pad(context);
+ SHA512Pad(context);
}
void
-SHA384_Final(u_int8_t digest[SHA384_DIGEST_LENGTH], SHA384_CTX *context)
+SHA384Final(u_int8_t digest[SHA384_DIGEST_LENGTH], SHA2_CTX *context)
{
- SHA384_Pad(context);
+ SHA384Pad(context);
- /* If no digest buffer is passed, we don't bother doing this: */
- if (digest != NULL) {
#if BYTE_ORDER == LITTLE_ENDIAN
- int i;
+ int i;
- /* Convert TO host byte order */
- for (i = 0; i < 6; i++)
- BE_64_TO_8(digest + i * 8, context->state[i]);
+ /* Convert TO host byte order */
+ for (i = 0; i < 6; i++)
+ BE_64_TO_8(digest + i * 8, context->state.st64[i]);
#else
- memcpy(digest, context->state, SHA384_DIGEST_LENGTH);
+ memcpy(digest, context->state.st64, SHA384_DIGEST_LENGTH);
#endif
- }
+ /* Zero out state data */
+ explicit_bzero(context, sizeof(*context));
+}
+DEF_WEAK(SHA384Final);
+
+#if 0
+/*** SHA-512/256: *********************************************************/
+void
+SHA512_256Init(SHA2_CTX *context)
+{
+ memcpy(context->state.st64, sha512_256_initial_hash_value,
+ sizeof(sha512_256_initial_hash_value));
+ memset(context->buffer, 0, sizeof(context->buffer));
+ context->bitcount[0] = context->bitcount[1] = 0;
+}
+DEF_WEAK(SHA512_256Init);
+MAKE_CLONE(SHA512_256Transform, SHA512Transform);
+MAKE_CLONE(SHA512_256Update, SHA512Update);
+MAKE_CLONE(SHA512_256Pad, SHA512Pad);
+DEF_WEAK(SHA512_256Transform);
+DEF_WEAK(SHA512_256Update);
+DEF_WEAK(SHA512_256Pad);
+
+void
+SHA512_256Final(u_int8_t digest[SHA512_256_DIGEST_LENGTH], SHA2_CTX *context)
+{
+ SHA512_256Pad(context);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ int i;
+
+ /* Convert TO host byte order */
+ for (i = 0; i < 4; i++)
+ BE_64_TO_8(digest + i * 8, context->state.st64[i]);
+#else
+ memcpy(digest, context->state.st64, SHA512_256_DIGEST_LENGTH);
+#endif
/* Zero out state data */
- memset(context, 0, sizeof(*context));
+ explicit_bzero(context, sizeof(*context));
}
+DEF_WEAK(SHA512_256Final);
+#endif /* !defined(SHA2_SMALL) */
+#endif /* 0 */
-#endif /* defined(_NEED_SHA2) && !defined(HAVE_SHA256_UPDATE) */
+#endif /* HAVE_SHA{256,384,512}UPDATE */
diff --git a/openbsd-compat/sha2.h b/openbsd-compat/sha2.h
index c8bfc3cd..d051e96e 100644
--- a/openbsd-compat/sha2.h
+++ b/openbsd-compat/sha2.h
@@ -1,4 +1,4 @@
-/* OpenBSD: sha2.h,v 1.6 2004/06/22 01:57:30 jfb Exp */
+/* $OpenBSD: sha2.h,v 1.10 2016/09/03 17:00:29 tedu Exp $ */
/*
* FILE: sha2.h
@@ -41,18 +41,13 @@
#include "includes.h"
-#ifdef WITH_OPENSSL
-# include <openssl/opensslv.h>
-# if !defined(HAVE_EVP_SHA256) && (OPENSSL_VERSION_NUMBER >= 0x00907000L)
-# define _NEED_SHA2 1
-# endif
-#else
-# define _NEED_SHA2 1
-#endif
-
-#if defined(_NEED_SHA2) && !defined(HAVE_SHA256_UPDATE)
+#if !defined(HAVE_SHA256UPDATE) || !defined(HAVE_SHA384UPDATE) || \
+ !defined(HAVE_SHA512UPDATE)
/*** SHA-256/384/512 Various Length Definitions ***********************/
+#define SHA224_BLOCK_LENGTH 64
+#define SHA224_DIGEST_LENGTH 28
+#define SHA224_DIGEST_STRING_LENGTH (SHA224_DIGEST_LENGTH * 2 + 1)
#define SHA256_BLOCK_LENGTH 64
#define SHA256_DIGEST_LENGTH 32
#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
@@ -62,73 +57,118 @@
#define SHA512_BLOCK_LENGTH 128
#define SHA512_DIGEST_LENGTH 64
#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
+#define SHA512_256_BLOCK_LENGTH 128
+#define SHA512_256_DIGEST_LENGTH 32
+#define SHA512_256_DIGEST_STRING_LENGTH (SHA512_256_DIGEST_LENGTH * 2 + 1)
-/*** SHA-256/384/512 Context Structures *******************************/
-typedef struct _SHA256_CTX {
- u_int32_t state[8];
- u_int64_t bitcount;
- u_int8_t buffer[SHA256_BLOCK_LENGTH];
-} SHA256_CTX;
-typedef struct _SHA512_CTX {
- u_int64_t state[8];
+/*** SHA-224/256/384/512 Context Structure *******************************/
+typedef struct _SHA2_CTX {
+ union {
+ u_int32_t st32[8];
+ u_int64_t st64[8];
+ } state;
u_int64_t bitcount[2];
u_int8_t buffer[SHA512_BLOCK_LENGTH];
-} SHA512_CTX;
+} SHA2_CTX;
-typedef SHA512_CTX SHA384_CTX;
+#if 0
+__BEGIN_DECLS
+void SHA224Init(SHA2_CTX *);
+void SHA224Transform(u_int32_t state[8], const u_int8_t [SHA224_BLOCK_LENGTH]);
+void SHA224Update(SHA2_CTX *, const u_int8_t *, size_t)
+ __attribute__((__bounded__(__string__,2,3)));
+void SHA224Pad(SHA2_CTX *);
+void SHA224Final(u_int8_t [SHA224_DIGEST_LENGTH], SHA2_CTX *)
+ __attribute__((__bounded__(__minbytes__,1,SHA224_DIGEST_LENGTH)));
+char *SHA224End(SHA2_CTX *, char *)
+ __attribute__((__bounded__(__minbytes__,2,SHA224_DIGEST_STRING_LENGTH)));
+char *SHA224File(const char *, char *)
+ __attribute__((__bounded__(__minbytes__,2,SHA224_DIGEST_STRING_LENGTH)));
+char *SHA224FileChunk(const char *, char *, off_t, off_t)
+ __attribute__((__bounded__(__minbytes__,2,SHA224_DIGEST_STRING_LENGTH)));
+char *SHA224Data(const u_int8_t *, size_t, char *)
+ __attribute__((__bounded__(__string__,1,2)))
+ __attribute__((__bounded__(__minbytes__,3,SHA224_DIGEST_STRING_LENGTH)));
+#endif /* 0 */
-void SHA256_Init(SHA256_CTX *);
-void SHA256_Transform(u_int32_t state[8], const u_int8_t [SHA256_BLOCK_LENGTH]);
-void SHA256_Update(SHA256_CTX *, const u_int8_t *, size_t)
+#ifndef HAVE_SHA256UPDATE
+void SHA256Init(SHA2_CTX *);
+void SHA256Transform(u_int32_t state[8], const u_int8_t [SHA256_BLOCK_LENGTH]);
+void SHA256Update(SHA2_CTX *, const u_int8_t *, size_t)
__attribute__((__bounded__(__string__,2,3)));
-void SHA256_Pad(SHA256_CTX *);
-void SHA256_Final(u_int8_t [SHA256_DIGEST_LENGTH], SHA256_CTX *)
+void SHA256Pad(SHA2_CTX *);
+void SHA256Final(u_int8_t [SHA256_DIGEST_LENGTH], SHA2_CTX *)
__attribute__((__bounded__(__minbytes__,1,SHA256_DIGEST_LENGTH)));
-char *SHA256_End(SHA256_CTX *, char *)
+char *SHA256End(SHA2_CTX *, char *)
__attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH)));
-char *SHA256_File(const char *, char *)
+char *SHA256File(const char *, char *)
__attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH)));
-char *SHA256_FileChunk(const char *, char *, off_t, off_t)
+char *SHA256FileChunk(const char *, char *, off_t, off_t)
__attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH)));
-char *SHA256_Data(const u_int8_t *, size_t, char *)
+char *SHA256Data(const u_int8_t *, size_t, char *)
__attribute__((__bounded__(__string__,1,2)))
__attribute__((__bounded__(__minbytes__,3,SHA256_DIGEST_STRING_LENGTH)));
+#endif /* HAVE_SHA256UPDATE */
-void SHA384_Init(SHA384_CTX *);
-void SHA384_Transform(u_int64_t state[8], const u_int8_t [SHA384_BLOCK_LENGTH]);
-void SHA384_Update(SHA384_CTX *, const u_int8_t *, size_t)
+#ifndef HAVE_SHA384UPDATE
+void SHA384Init(SHA2_CTX *);
+void SHA384Transform(u_int64_t state[8], const u_int8_t [SHA384_BLOCK_LENGTH]);
+void SHA384Update(SHA2_CTX *, const u_int8_t *, size_t)
__attribute__((__bounded__(__string__,2,3)));
-void SHA384_Pad(SHA384_CTX *);
-void SHA384_Final(u_int8_t [SHA384_DIGEST_LENGTH], SHA384_CTX *)
+void SHA384Pad(SHA2_CTX *);
+void SHA384Final(u_int8_t [SHA384_DIGEST_LENGTH], SHA2_CTX *)
__attribute__((__bounded__(__minbytes__,1,SHA384_DIGEST_LENGTH)));
-char *SHA384_End(SHA384_CTX *, char *)
+char *SHA384End(SHA2_CTX *, char *)
__attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH)));
-char *SHA384_File(const char *, char *)
+char *SHA384File(const char *, char *)
__attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH)));
-char *SHA384_FileChunk(const char *, char *, off_t, off_t)
+char *SHA384FileChunk(const char *, char *, off_t, off_t)
__attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH)));
-char *SHA384_Data(const u_int8_t *, size_t, char *)
+char *SHA384Data(const u_int8_t *, size_t, char *)
__attribute__((__bounded__(__string__,1,2)))
__attribute__((__bounded__(__minbytes__,3,SHA384_DIGEST_STRING_LENGTH)));
+#endif /* HAVE_SHA384UPDATE */
-void SHA512_Init(SHA512_CTX *);
-void SHA512_Transform(u_int64_t state[8], const u_int8_t [SHA512_BLOCK_LENGTH]);
-void SHA512_Update(SHA512_CTX *, const u_int8_t *, size_t)
+#ifndef HAVE_SHA512UPDATE
+void SHA512Init(SHA2_CTX *);
+void SHA512Transform(u_int64_t state[8], const u_int8_t [SHA512_BLOCK_LENGTH]);
+void SHA512Update(SHA2_CTX *, const u_int8_t *, size_t)
__attribute__((__bounded__(__string__,2,3)));
-void SHA512_Pad(SHA512_CTX *);
-void SHA512_Final(u_int8_t [SHA512_DIGEST_LENGTH], SHA512_CTX *)
+void SHA512Pad(SHA2_CTX *);
+void SHA512Final(u_int8_t [SHA512_DIGEST_LENGTH], SHA2_CTX *)
__attribute__((__bounded__(__minbytes__,1,SHA512_DIGEST_LENGTH)));
-char *SHA512_End(SHA512_CTX *, char *)
+char *SHA512End(SHA2_CTX *, char *)
__attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH)));
-char *SHA512_File(const char *, char *)
+char *SHA512File(const char *, char *)
__attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH)));
-char *SHA512_FileChunk(const char *, char *, off_t, off_t)
+char *SHA512FileChunk(const char *, char *, off_t, off_t)
__attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH)));
-char *SHA512_Data(const u_int8_t *, size_t, char *)
+char *SHA512Data(const u_int8_t *, size_t, char *)
__attribute__((__bounded__(__string__,1,2)))
__attribute__((__bounded__(__minbytes__,3,SHA512_DIGEST_STRING_LENGTH)));
+#endif /* HAVE_SHA512UPDATE */
+
+#if 0
+void SHA512_256Init(SHA2_CTX *);
+void SHA512_256Transform(u_int64_t state[8], const u_int8_t [SHA512_256_BLOCK_LENGTH]);
+void SHA512_256Update(SHA2_CTX *, const u_int8_t *, size_t)
+ __attribute__((__bounded__(__string__,2,3)));
+void SHA512_256Pad(SHA2_CTX *);
+void SHA512_256Final(u_int8_t [SHA512_256_DIGEST_LENGTH], SHA2_CTX *)
+ __attribute__((__bounded__(__minbytes__,1,SHA512_256_DIGEST_LENGTH)));
+char *SHA512_256End(SHA2_CTX *, char *)
+ __attribute__((__bounded__(__minbytes__,2,SHA512_256_DIGEST_STRING_LENGTH)));
+char *SHA512_256File(const char *, char *)
+ __attribute__((__bounded__(__minbytes__,2,SHA512_256_DIGEST_STRING_LENGTH)));
+char *SHA512_256FileChunk(const char *, char *, off_t, off_t)
+ __attribute__((__bounded__(__minbytes__,2,SHA512_256_DIGEST_STRING_LENGTH)));
+char *SHA512_256Data(const u_int8_t *, size_t, char *)
+ __attribute__((__bounded__(__string__,1,2)))
+ __attribute__((__bounded__(__minbytes__,3,SHA512_256_DIGEST_STRING_LENGTH)));
+__END_DECLS
+#endif /* 0 */
-#endif /* defined(_NEED_SHA2) && !defined(HAVE_SHA256_UPDATE) */
+#endif /* HAVE_SHA{256,384,512}UPDATE */
#endif /* _SSHSHA2_H */
diff --git a/openbsd-compat/strcasestr.c b/openbsd-compat/strcasestr.c
new file mode 100644
index 00000000..4c4d1475
--- /dev/null
+++ b/openbsd-compat/strcasestr.c
@@ -0,0 +1,69 @@
+/* $OpenBSD: strcasestr.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */
+/* $NetBSD: strcasestr.c,v 1.2 2005/02/09 21:35:47 kleink Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/string/strcasestr.c */
+
+#include "includes.h"
+
+#ifndef HAVE_STRCASESTR
+
+#include <ctype.h>
+#include <string.h>
+
+/*
+ * Find the first occurrence of find in s, ignore case.
+ */
+char *
+strcasestr(const char *s, const char *find)
+{
+ char c, sc;
+ size_t len;
+
+ if ((c = *find++) != 0) {
+ c = (char)tolower((unsigned char)c);
+ len = strlen(find);
+ do {
+ do {
+ if ((sc = *s++) == 0)
+ return (NULL);
+ } while ((char)tolower((unsigned char)sc) != c);
+ } while (strncasecmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
+DEF_WEAK(strcasestr);
+
+#endif
diff --git a/openbsd-compat/strndup.c b/openbsd-compat/strndup.c
new file mode 100644
index 00000000..30ac6f04
--- /dev/null
+++ b/openbsd-compat/strndup.c
@@ -0,0 +1,43 @@
+/* $OpenBSD: strndup.c,v 1.2 2015/08/31 02:53:57 guenther Exp $ */
+
+/*
+ * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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"
+#if !defined(HAVE_STRNDUP) || defined(BROKEN_STRNDUP)
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *
+strndup(const char *str, size_t maxlen)
+{
+ char *copy;
+ size_t len;
+
+ len = strnlen(str, maxlen);
+ copy = malloc(len + 1);
+ if (copy != NULL) {
+ (void)memcpy(copy, str, len);
+ copy[len] = '\0';
+ }
+
+ return copy;
+}
+DEF_WEAK(strndup);
+#endif /* HAVE_STRNDUP */
diff --git a/openbsd-compat/strnlen.c b/openbsd-compat/strnlen.c
index 93d51559..7ad3573a 100644
--- a/openbsd-compat/strnlen.c
+++ b/openbsd-compat/strnlen.c
@@ -18,8 +18,8 @@
/* OPENBSD ORIGINAL: lib/libc/string/strnlen.c */
-#include "config.h"
-#ifndef HAVE_STRNLEN
+#include "includes.h"
+#if !defined(HAVE_STRNLEN) || defined(BROKEN_STRNLEN)
#include <sys/types.h>
#include <string.h>
diff --git a/openbsd-compat/sys-queue.h b/openbsd-compat/sys-queue.h
index 28aaaa37..5108f394 100644
--- a/openbsd-compat/sys-queue.h
+++ b/openbsd-compat/sys-queue.h
@@ -45,6 +45,7 @@
#undef SLIST_HEAD_INITIALIZER
#undef SLIST_ENTRY
#undef SLIST_FOREACH_PREVPTR
+#undef SLIST_FOREACH_SAFE
#undef SLIST_FIRST
#undef SLIST_END
#undef SLIST_EMPTY
@@ -54,6 +55,7 @@
#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
@@ -64,6 +66,7 @@
#undef LIST_EMPTY
#undef LIST_NEXT
#undef LIST_FOREACH
+#undef LIST_FOREACH_SAFE
#undef LIST_INIT
#undef LIST_INSERT_AFTER
#undef LIST_INSERT_BEFORE
@@ -78,6 +81,7 @@
#undef SIMPLEQ_EMPTY
#undef SIMPLEQ_NEXT
#undef SIMPLEQ_FOREACH
+#undef SIMPLEQ_FOREACH_SAFE
#undef SIMPLEQ_INIT
#undef SIMPLEQ_INSERT_HEAD
#undef SIMPLEQ_INSERT_TAIL
@@ -94,6 +98,8 @@
#undef TAILQ_EMPTY
#undef TAILQ_FOREACH
#undef TAILQ_FOREACH_REVERSE
+#undef TAILQ_FOREACH_SAFE
+#undef TAILQ_FOREACH_REVERSE_SAFE
#undef TAILQ_INIT
#undef TAILQ_INSERT_HEAD
#undef TAILQ_INSERT_TAIL
diff --git a/openbsd-compat/vis.c b/openbsd-compat/vis.c
index f6f5665c..0e04ed02 100644
--- a/openbsd-compat/vis.c
+++ b/openbsd-compat/vis.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vis.c,v 1.19 2005/09/01 17:15:49 millert Exp $ */
+/* $OpenBSD: vis.c,v 1.25 2015/09/13 11:32:51 guenther Exp $ */
/*-
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -33,13 +33,18 @@
#include "includes.h"
#if !defined(HAVE_STRNVIS) || defined(BROKEN_STRNVIS)
+#include <sys/types.h>
+#include <errno.h>
#include <ctype.h>
+#include <limits.h>
#include <string.h>
+#include <stdlib.h>
#include "vis.h"
#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
-#define isvisible(c) \
+#define isvisible(c,flag) \
+ (((c) == '\\' || (flag & VIS_ALL) == 0) && \
(((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) && \
(((c) != '*' && (c) != '?' && (c) != '[' && (c) != '#') || \
(flag & VIS_GLOB) == 0) && isgraph((u_char)(c))) || \
@@ -48,7 +53,7 @@
((flag & VIS_NL) == 0 && (c) == '\n') || \
((flag & VIS_SAFE) && ((c) == '\b' || \
(c) == '\007' || (c) == '\r' || \
- isgraph((u_char)(c)))))
+ isgraph((u_char)(c))))))
/*
* vis - visually encode characters
@@ -56,10 +61,11 @@
char *
vis(char *dst, int c, int flag, int nextc)
{
- if (isvisible(c)) {
- *dst++ = c;
- if (c == '\\' && (flag & VIS_NOSLASH) == 0)
+ if (isvisible(c, flag)) {
+ if ((c == '"' && (flag & VIS_DQ) != 0) ||
+ (c == '\\' && (flag & VIS_NOSLASH) == 0))
*dst++ = '\\';
+ *dst++ = c;
*dst = '\0';
return (dst);
}
@@ -136,6 +142,7 @@ done:
*dst = '\0';
return (dst);
}
+DEF_WEAK(vis);
/*
* strvis, strnvis, strvisx - visually encode characters from src into dst
@@ -161,6 +168,7 @@ strvis(char *dst, const char *src, int flag)
*dst = '\0';
return (dst - start);
}
+DEF_WEAK(strvis);
int
strnvis(char *dst, const char *src, size_t siz, int flag)
@@ -171,19 +179,18 @@ strnvis(char *dst, const char *src, size_t siz, int flag)
i = 0;
for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
- if (isvisible(c)) {
- i = 1;
- *dst++ = c;
- if (c == '\\' && (flag & VIS_NOSLASH) == 0) {
+ if (isvisible(c, flag)) {
+ if ((c == '"' && (flag & VIS_DQ) != 0) ||
+ (c == '\\' && (flag & VIS_NOSLASH) == 0)) {
/* need space for the extra '\\' */
- if (dst < end)
- *dst++ = '\\';
- else {
- dst--;
+ if (dst + 1 >= end) {
i = 2;
break;
}
+ *dst++ = '\\';
}
+ i = 1;
+ *dst++ = c;
src++;
} else {
i = vis(tbuf, c, flag, *++src) - tbuf;
@@ -207,6 +214,25 @@ strnvis(char *dst, const char *src, size_t siz, int flag)
}
int
+stravis(char **outp, const char *src, int flag)
+{
+ char *buf;
+ int len, serrno;
+
+ buf = reallocarray(NULL, 4, strlen(src) + 1);
+ if (buf == NULL)
+ return -1;
+ len = strvis(buf, src, flag);
+ serrno = errno;
+ *outp = realloc(buf, len + 1);
+ if (*outp == NULL) {
+ *outp = buf;
+ errno = serrno;
+ }
+ return (len);
+}
+
+int
strvisx(char *dst, const char *src, size_t len, int flag)
{
char c;
diff --git a/openbsd-compat/vis.h b/openbsd-compat/vis.h
index d1286c99..2cdfd364 100644
--- a/openbsd-compat/vis.h
+++ b/openbsd-compat/vis.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vis.h,v 1.11 2005/08/09 19:38:31 millert Exp $ */
+/* $OpenBSD: vis.h,v 1.15 2015/07/20 01:52:27 millert Exp $ */
/* $NetBSD: vis.h,v 1.4 1994/10/26 00:56:41 cgd Exp $ */
/*-
@@ -58,6 +58,8 @@
#define VIS_NL 0x10 /* also encode newline */
#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
#define VIS_SAFE 0x20 /* only encode "unsafe" characters */
+#define VIS_DQ 0x200 /* backslash-escape double quotes */
+#define VIS_ALL 0x400 /* encode all characters */
/*
* other
@@ -81,6 +83,7 @@
char *vis(char *, int, int, int);
int strvis(char *, const char *, int);
+int stravis(char **, const char *, int);
int strnvis(char *, const char *, size_t, int)
__attribute__ ((__bounded__(__string__,1,3)));
int strvisx(char *, const char *, size_t, int)
diff --git a/openbsd-compat/xcrypt.c b/openbsd-compat/xcrypt.c
index 8577cbd8..360b187a 100644
--- a/openbsd-compat/xcrypt.c
+++ b/openbsd-compat/xcrypt.c
@@ -25,6 +25,7 @@
#include "includes.h"
#include <sys/types.h>
+#include <string.h>
#include <unistd.h>
#include <pwd.h>
@@ -41,7 +42,7 @@
# include <sys/security.h>
# include <sys/audit.h>
# include <prot.h>
-# endif
+# endif
# if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
# include <shadow.h>
@@ -62,26 +63,66 @@
# define crypt DES_crypt
# endif
+/*
+ * Pick an appropriate password encryption type and salt for the running
+ * system by searching through accounts until we find one that has a valid
+ * salt. Usually this will be root unless the root account is locked out.
+ * If we don't find one we return a traditional DES-based salt.
+ */
+static const char *
+pick_salt(void)
+{
+ struct passwd *pw;
+ char *passwd, *p;
+ size_t typelen;
+ static char salt[32];
+
+ if (salt[0] != '\0')
+ return salt;
+ strlcpy(salt, "xx", sizeof(salt));
+ setpwent();
+ while ((pw = getpwent()) != NULL) {
+ if ((passwd = shadow_pw(pw)) == NULL)
+ continue;
+ if (passwd[0] == '$' && (p = strrchr(passwd+1, '$')) != NULL) {
+ typelen = p - passwd + 1;
+ strlcpy(salt, passwd, MIN(typelen, sizeof(salt)));
+ explicit_bzero(passwd, strlen(passwd));
+ goto out;
+ }
+ }
+ out:
+ endpwent();
+ return salt;
+}
+
char *
xcrypt(const char *password, const char *salt)
{
char *crypted;
+ /*
+ * If we don't have a salt we are encrypting a fake password for
+ * for timing purposes. Pick an appropriate salt.
+ */
+ if (salt == NULL)
+ salt = pick_salt();
+
# ifdef HAVE_MD5_PASSWORDS
- if (is_md5_salt(salt))
- crypted = md5_crypt(password, salt);
- else
- crypted = crypt(password, salt);
+ if (is_md5_salt(salt))
+ crypted = md5_crypt(password, salt);
+ else
+ crypted = crypt(password, salt);
# elif defined(__hpux) && !defined(HAVE_SECUREWARE)
if (iscomsec())
- crypted = bigcrypt(password, salt);
- else
- crypted = crypt(password, salt);
+ crypted = bigcrypt(password, salt);
+ else
+ crypted = crypt(password, salt);
# elif defined(HAVE_SECUREWARE)
- crypted = bigcrypt(password, salt);
+ crypted = bigcrypt(password, salt);
# else
- crypted = crypt(password, salt);
-# endif
+ crypted = crypt(password, salt);
+# endif
return crypted;
}
diff --git a/openbsd-compat/xmmap.c b/openbsd-compat/xmmap.c
deleted file mode 100644
index 04c6babc..00000000
--- a/openbsd-compat/xmmap.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2002 Tim Rice. All rights reserved.
- * MAP_FAILED code by Solar Designer.
- *
- * 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.
- */
-
-/* $Id: xmmap.c,v 1.15 2009/02/16 04:21:40 djm Exp $ */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-#include <sys/stat.h>
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-#include <errno.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "log.h"
-
-void *
-xmmap(size_t size)
-{
-#ifdef HAVE_MMAP
- void *address;
-
-# ifdef MAP_ANON
- address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED,
- -1, (off_t)0);
-# else
- address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED,
- open("/dev/zero", O_RDWR), (off_t)0);
-# endif
-
-#define MM_SWAP_TEMPLATE "/var/run/sshd.mm.XXXXXXXX"
- if (address == (void *)MAP_FAILED) {
- char tmpname[sizeof(MM_SWAP_TEMPLATE)] = MM_SWAP_TEMPLATE;
- int tmpfd;
- mode_t old_umask;
-
- old_umask = umask(0177);
- tmpfd = mkstemp(tmpname);
- umask(old_umask);
- if (tmpfd == -1)
- fatal("mkstemp(\"%s\"): %s",
- MM_SWAP_TEMPLATE, strerror(errno));
- unlink(tmpname);
- if (ftruncate(tmpfd, size) != 0)
- fatal("%s: ftruncate: %s", __func__, strerror(errno));
- address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED,
- tmpfd, (off_t)0);
- close(tmpfd);
- }
-
- return (address);
-#else
- fatal("%s: UsePrivilegeSeparation=yes and Compression=yes not supported",
- __func__);
-#endif /* HAVE_MMAP */
-
-}
-
diff --git a/opensshd.init.in b/opensshd.init.in
index 517345bf..99e5a51a 100755
--- a/opensshd.init.in
+++ b/opensshd.init.in
@@ -17,7 +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_RSA1=$sysconfdir/ssh_host_key
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
@@ -25,9 +24,6 @@ HOST_KEY_ED25519=$sysconfdir/ssh_host_ed25519_key
checkkeys() {
- if [ ! -f $HOST_KEY_RSA1 ]; then
- ${SSH_KEYGEN} -t rsa1 -f ${HOST_KEY_RSA1} -N ""
- fi
if [ ! -f $HOST_KEY_DSA ]; then
${SSH_KEYGEN} -t dsa -f ${HOST_KEY_DSA} -N ""
fi
diff --git a/packet.c b/packet.c
index b1219c85..e7abb341 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.208 2015/02/13 18:57:00 markus Exp $ */
+/* $OpenBSD: packet.c,v 1.291 2020/03/06 18:20:44 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -38,8 +38,7 @@
*/
#include "includes.h"
-
-#include <sys/param.h> /* MIN roundup */
+
#include <sys/types.h>
#include "openbsd-compat/sys-queue.h"
#include <sys/socket.h>
@@ -52,25 +51,37 @@
#include <arpa/inet.h>
#include <errno.h>
+#include <netdb.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
#include <signal.h>
#include <time.h>
-#include <zlib.h>
+/*
+ * Explicitly include OpenSSL before zlib as some versions of OpenSSL have
+ * "free_func" in their headers, which zlib typedefs.
+ */
+#ifdef WITH_OPENSSL
+# include <openssl/bn.h>
+# include <openssl/evp.h>
+# ifdef OPENSSL_HAS_ECC
+# include <openssl/ec.h>
+# endif
+#endif
-#include "buffer.h" /* typedefs XXX */
-#include "key.h" /* typedefs XXX */
+#ifdef WITH_ZLIB
+#include <zlib.h>
+#endif
#include "xmalloc.h"
-#include "crc32.h"
-#include "deattack.h"
#include "compat.h"
-#include "ssh1.h"
#include "ssh2.h"
#include "cipher.h"
#include "sshkey.h"
@@ -83,7 +94,6 @@
#include "channels.h"
#include "ssh.h"
#include "packet.h"
-#include "roaming.h"
#include "ssherr.h"
#include "sshbuf.h"
@@ -122,10 +132,10 @@ struct session_state {
u_int remote_protocol_flags;
/* Encryption context for receiving data. Only used for decryption. */
- struct sshcipher_ctx receive_context;
+ struct sshcipher_ctx *receive_context;
/* Encryption context for sending data. Only used for encryption. */
- struct sshcipher_ctx send_context;
+ struct sshcipher_ctx *send_context;
/* Buffer for raw input data from the socket. */
struct sshbuf *input;
@@ -142,20 +152,16 @@ struct session_state {
/* Scratch buffer for packet compression/decompression. */
struct sshbuf *compression_buffer;
+#ifdef WITH_ZLIB
/* Incoming/outgoing compression dictionaries */
z_stream compression_in_stream;
z_stream compression_out_stream;
+#endif
int compression_in_started;
int compression_out_started;
int compression_in_failures;
int compression_out_failures;
- /*
- * Flag indicating whether packet compression/decompression is
- * enabled.
- */
- int packet_compression;
-
/* default maximum packet size */
u_int max_packet_size;
@@ -181,22 +187,18 @@ struct session_state {
struct packet_state p_read, p_send;
/* Volume-based rekeying */
- u_int64_t max_blocks_in, max_blocks_out;
- u_int32_t rekey_limit;
+ u_int64_t max_blocks_in, max_blocks_out, rekey_limit;
/* Time-based rekeying */
u_int32_t rekey_interval; /* how often in seconds */
time_t rekey_time; /* time of last rekeying */
- /* Session key for protocol v1 */
- u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
- u_int ssh1_keylen;
-
/* roundup current message to extra_pad bytes */
u_char extra_pad;
/* XXX discard incoming data after MAC error */
u_int packet_discard;
+ size_t packet_discard_mac_already;
struct sshmac *packet_discard_mac;
/* Used in packet_read_poll2() */
@@ -205,6 +207,9 @@ struct session_state {
/* Used in packet_send2 */
int rekeying;
+ /* Used in ssh_packet_send_mux() */
+ int mux;
+
/* Used in packet_set_interactive */
int set_interactive_called;
@@ -214,8 +219,9 @@ struct session_state {
/* One-off warning about weak ciphers */
int cipher_warning_done;
- /* SSH1 CRC compensation attack detector */
- struct deattack_ctx deattack;
+ /* Hook for fuzzing inbound packets */
+ ssh_packet_hook_fn *hook_in;
+ void *hook_in_ctx;
TAILQ_HEAD(, packet) outgoing;
};
@@ -228,6 +234,7 @@ ssh_alloc_session_state(void)
if ((ssh = calloc(1, sizeof(*ssh))) == NULL ||
(state = calloc(1, sizeof(*state))) == NULL ||
+ (ssh->kex = kex_new()) == NULL ||
(state->input = sshbuf_new()) == NULL ||
(state->output = sshbuf_new()) == NULL ||
(state->outgoing_packet = sshbuf_new()) == NULL ||
@@ -250,6 +257,10 @@ ssh_alloc_session_state(void)
ssh->state = state;
return ssh;
fail:
+ if (ssh) {
+ kex_free(ssh->kex);
+ free(ssh);
+ }
if (state) {
sshbuf_free(state->input);
sshbuf_free(state->output);
@@ -257,13 +268,25 @@ ssh_alloc_session_state(void)
sshbuf_free(state->outgoing_packet);
free(state);
}
- free(ssh);
return NULL;
}
+void
+ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx)
+{
+ ssh->state->hook_in = hook;
+ ssh->state->hook_in_ctx = ctx;
+}
+
+/* Returns nonzero if rekeying is in progress */
+int
+ssh_packet_is_rekeying(struct ssh *ssh)
+{
+ return ssh->state->rekeying || ssh->kex->done == 0;
+}
+
/*
- * Sets the descriptors used for communication. Disables encryption until
- * packet_set_encryption_key is called.
+ * Sets the descriptors used for communication.
*/
struct ssh *
ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
@@ -279,7 +302,7 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
if (ssh == NULL)
ssh = ssh_alloc_session_state();
if (ssh == NULL) {
- error("%s: cound not allocate state", __func__);
+ error("%s: could not allocate state", __func__);
return NULL;
}
state = ssh->state;
@@ -290,10 +313,10 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
(r = cipher_init(&state->receive_context, none,
(const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) {
error("%s: cipher_init failed: %s", __func__, ssh_err(r));
+ free(ssh); /* XXX need ssh_free_session_state? */
return NULL;
}
state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL;
- deattack_init(&state->deattack);
/*
* Cache the IP address of the remote connection for use in error
* messages that might be generated after the connection has closed.
@@ -317,6 +340,38 @@ ssh_packet_set_timeout(struct ssh *ssh, int timeout, int count)
state->packet_timeout_ms = timeout * count * 1000;
}
+void
+ssh_packet_set_mux(struct ssh *ssh)
+{
+ ssh->state->mux = 1;
+ ssh->state->rekeying = 0;
+}
+
+int
+ssh_packet_get_mux(struct ssh *ssh)
+{
+ return ssh->state->mux;
+}
+
+int
+ssh_packet_set_log_preamble(struct ssh *ssh, const char *fmt, ...)
+{
+ va_list args;
+ int r;
+
+ free(ssh->log_preamble);
+ if (fmt == NULL)
+ ssh->log_preamble = NULL;
+ else {
+ va_start(args, fmt);
+ r = vasprintf(&ssh->log_preamble, fmt, args);
+ va_end(args);
+ if (r < 0 || ssh->log_preamble == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ return 0;
+}
+
int
ssh_packet_stop_discard(struct ssh *ssh)
{
@@ -325,25 +380,28 @@ ssh_packet_stop_discard(struct ssh *ssh)
if (state->packet_discard_mac) {
char buf[1024];
+ size_t dlen = PACKET_MAX_SIZE;
+ if (dlen > state->packet_discard_mac_already)
+ dlen -= state->packet_discard_mac_already;
memset(buf, 'a', sizeof(buf));
- while (sshbuf_len(state->incoming_packet) <
- PACKET_MAX_SIZE)
+ while (sshbuf_len(state->incoming_packet) < dlen)
if ((r = sshbuf_put(state->incoming_packet, buf,
sizeof(buf))) != 0)
return r;
(void) mac_compute(state->packet_discard_mac,
state->p_read.seqnr,
- sshbuf_ptr(state->incoming_packet), PACKET_MAX_SIZE,
+ sshbuf_ptr(state->incoming_packet), dlen,
NULL, 0);
}
- logit("Finished discarding for %.200s", ssh_remote_ipaddr(ssh));
+ logit("Finished discarding for %.200s port %d",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
return SSH_ERR_MAC_INVALID;
}
static int
ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc,
- struct sshmac *mac, u_int packet_length, u_int discard)
+ struct sshmac *mac, size_t mac_already, u_int discard)
{
struct session_state *state = ssh->state;
int r;
@@ -353,11 +411,16 @@ ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc,
return r;
return SSH_ERR_MAC_INVALID;
}
- if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled)
+ /*
+ * Record number of bytes over which the mac has already
+ * been computed in order to minimize timing attacks.
+ */
+ if (mac && mac->enabled) {
state->packet_discard_mac = mac;
- if (sshbuf_len(state->input) >= discard &&
- (r = ssh_packet_stop_discard(ssh)) != 0)
- return r;
+ state->packet_discard_mac_already = mac_already;
+ }
+ if (sshbuf_len(state->input) >= discard)
+ return ssh_packet_stop_discard(ssh);
state->packet_discard = discard - sshbuf_len(state->input);
return 0;
}
@@ -367,22 +430,28 @@ ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc,
int
ssh_packet_connection_is_on_socket(struct ssh *ssh)
{
- struct session_state *state = ssh->state;
+ struct session_state *state;
struct sockaddr_storage from, to;
socklen_t fromlen, tolen;
+ if (ssh == NULL || ssh->state == NULL)
+ return 0;
+
+ state = ssh->state;
+ if (state->connection_in == -1 || state->connection_out == -1)
+ return 0;
/* filedescriptors in and out are the same, so it's a socket */
if (state->connection_in == state->connection_out)
return 1;
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(state->connection_in, (struct sockaddr *)&from,
- &fromlen) < 0)
+ &fromlen) == -1)
return 0;
tolen = sizeof(to);
memset(&to, 0, sizeof(to));
if (getpeername(state->connection_out, (struct sockaddr *)&to,
- &tolen) < 0)
+ &tolen) == -1)
return 0;
if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
return 0;
@@ -408,7 +477,7 @@ ssh_packet_connection_af(struct ssh *ssh)
memset(&to, 0, sizeof(to));
if (getsockname(ssh->state->connection_out, (struct sockaddr *)&to,
- &tolen) < 0)
+ &tolen) == -1)
return 0;
#ifdef IPV4_IN_IPV6
if (to.ss_family == AF_INET6 &&
@@ -454,42 +523,99 @@ ssh_packet_get_connection_out(struct ssh *ssh)
const char *
ssh_remote_ipaddr(struct ssh *ssh)
{
+ int sock;
+
/* Check whether we have cached the ipaddr. */
- if (ssh->remote_ipaddr == NULL)
- ssh->remote_ipaddr = ssh_packet_connection_is_on_socket(ssh) ?
- get_peer_ipaddr(ssh->state->connection_in) :
- strdup("UNKNOWN");
- if (ssh->remote_ipaddr == NULL)
- return "UNKNOWN";
+ if (ssh->remote_ipaddr == NULL) {
+ if (ssh_packet_connection_is_on_socket(ssh)) {
+ sock = ssh->state->connection_in;
+ ssh->remote_ipaddr = get_peer_ipaddr(sock);
+ ssh->remote_port = get_peer_port(sock);
+ ssh->local_ipaddr = get_local_ipaddr(sock);
+ ssh->local_port = get_local_port(sock);
+ } else {
+ ssh->remote_ipaddr = xstrdup("UNKNOWN");
+ ssh->remote_port = 65535;
+ ssh->local_ipaddr = xstrdup("UNKNOWN");
+ ssh->local_port = 65535;
+ }
+ }
return ssh->remote_ipaddr;
}
+/* Returns the port number of the remote host. */
+
+int
+ssh_remote_port(struct ssh *ssh)
+{
+ (void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
+ return ssh->remote_port;
+}
+
+/*
+ * Returns the IP-address of the local host as a string. The returned
+ * string must not be freed.
+ */
+
+const char *
+ssh_local_ipaddr(struct ssh *ssh)
+{
+ (void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
+ return ssh->local_ipaddr;
+}
+
+/* Returns the port number of the local host. */
+
+int
+ssh_local_port(struct ssh *ssh)
+{
+ (void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
+ return ssh->local_port;
+}
+
+/* Returns the routing domain of the input socket, or NULL if unavailable */
+const char *
+ssh_packet_rdomain_in(struct ssh *ssh)
+{
+ if (ssh->rdomain_in != NULL)
+ return ssh->rdomain_in;
+ if (!ssh_packet_connection_is_on_socket(ssh))
+ return NULL;
+ ssh->rdomain_in = get_rdomain(ssh->state->connection_in);
+ return ssh->rdomain_in;
+}
+
/* Closes the connection and clears and frees internal data structures. */
-void
-ssh_packet_close(struct ssh *ssh)
+static void
+ssh_packet_close_internal(struct ssh *ssh, int do_close)
{
struct session_state *state = ssh->state;
- int r;
u_int mode;
if (!state->initialized)
return;
state->initialized = 0;
- if (state->connection_in == state->connection_out) {
- shutdown(state->connection_out, SHUT_RDWR);
- close(state->connection_out);
- } else {
- close(state->connection_in);
- close(state->connection_out);
+ if (do_close) {
+ if (state->connection_in == state->connection_out) {
+ close(state->connection_out);
+ } else {
+ close(state->connection_in);
+ close(state->connection_out);
+ }
}
sshbuf_free(state->input);
sshbuf_free(state->output);
sshbuf_free(state->outgoing_packet);
sshbuf_free(state->incoming_packet);
- for (mode = 0; mode < MODE_MAX; mode++)
- kex_free_newkeys(state->newkeys[mode]);
- if (state->compression_buffer) {
+ for (mode = 0; mode < MODE_MAX; mode++) {
+ kex_free_newkeys(state->newkeys[mode]); /* current keys */
+ state->newkeys[mode] = NULL;
+ ssh_clear_newkeys(ssh, mode); /* next keys */
+ }
+#ifdef WITH_ZLIB
+ /* compression state is in shared mem, so we can only release it once */
+ if (do_close && state->compression_buffer) {
sshbuf_free(state->compression_buffer);
if (state->compression_out_started) {
z_streamp stream = &state->compression_out_stream;
@@ -503,7 +629,7 @@ ssh_packet_close(struct ssh *ssh)
deflateEnd(stream);
}
if (state->compression_in_started) {
- z_streamp stream = &state->compression_out_stream;
+ z_streamp stream = &state->compression_in_stream;
debug("compress incoming: "
"raw data %llu, compressed %llu, factor %.2f",
(unsigned long long)stream->total_out,
@@ -514,16 +640,30 @@ ssh_packet_close(struct ssh *ssh)
inflateEnd(stream);
}
}
- if ((r = cipher_cleanup(&state->send_context)) != 0)
- error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r));
- if ((r = cipher_cleanup(&state->receive_context)) != 0)
- error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r));
- if (ssh->remote_ipaddr) {
+#endif /* WITH_ZLIB */
+ cipher_free(state->send_context);
+ cipher_free(state->receive_context);
+ state->send_context = state->receive_context = NULL;
+ if (do_close) {
+ free(ssh->local_ipaddr);
+ ssh->local_ipaddr = NULL;
free(ssh->remote_ipaddr);
ssh->remote_ipaddr = NULL;
+ free(ssh->state);
+ ssh->state = NULL;
}
- free(ssh->state);
- ssh->state = NULL;
+}
+
+void
+ssh_packet_close(struct ssh *ssh)
+{
+ ssh_packet_close_internal(ssh, 1);
+}
+
+void
+ssh_packet_clear_keys(struct ssh *ssh)
+{
+ ssh_packet_close_internal(ssh, 0);
}
/* Sets remote side protocol flags. */
@@ -556,6 +696,7 @@ ssh_packet_init_compression(struct ssh *ssh)
return 0;
}
+#ifdef WITH_ZLIB
static int
start_compression_out(struct ssh *ssh, int level)
{
@@ -593,21 +734,6 @@ start_compression_in(struct ssh *ssh)
return 0;
}
-int
-ssh_packet_start_compression(struct ssh *ssh, int level)
-{
- int r;
-
- if (ssh->state->packet_compression && !compat20)
- return SSH_ERR_INTERNAL_ERROR;
- ssh->state->packet_compression = 1;
- if ((r = ssh_packet_init_compression(ssh)) != 0 ||
- (r = start_compression_in(ssh)) != 0 ||
- (r = start_compression_out(ssh, level)) != 0)
- return r;
- return 0;
-}
-
/* XXX remove need for separate compression buffer */
static int
compress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out)
@@ -702,214 +828,40 @@ uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out)
/* NOTREACHED */
}
-/* Serialise compression state into a blob for privsep */
+#else /* WITH_ZLIB */
+
static int
-ssh_packet_get_compress_state(struct sshbuf *m, struct ssh *ssh)
+start_compression_out(struct ssh *ssh, int level)
{
- struct session_state *state = ssh->state;
- struct sshbuf *b;
- int r;
-
- if ((b = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if (state->compression_in_started) {
- if ((r = sshbuf_put_string(b, &state->compression_in_stream,
- sizeof(state->compression_in_stream))) != 0)
- goto out;
- } else if ((r = sshbuf_put_string(b, NULL, 0)) != 0)
- goto out;
- if (state->compression_out_started) {
- if ((r = sshbuf_put_string(b, &state->compression_out_stream,
- sizeof(state->compression_out_stream))) != 0)
- goto out;
- } else if ((r = sshbuf_put_string(b, NULL, 0)) != 0)
- goto out;
- r = sshbuf_put_stringb(m, b);
- out:
- sshbuf_free(b);
- return r;
+ return SSH_ERR_INTERNAL_ERROR;
}
-/* Deserialise compression state from a blob for privsep */
static int
-ssh_packet_set_compress_state(struct ssh *ssh, struct sshbuf *m)
+start_compression_in(struct ssh *ssh)
{
- struct session_state *state = ssh->state;
- struct sshbuf *b = NULL;
- int r;
- const u_char *inblob, *outblob;
- size_t inl, outl;
-
- if ((r = sshbuf_froms(m, &b)) != 0)
- goto out;
- if ((r = sshbuf_get_string_direct(b, &inblob, &inl)) != 0 ||
- (r = sshbuf_get_string_direct(b, &outblob, &outl)) != 0)
- goto out;
- if (inl == 0)
- state->compression_in_started = 0;
- else if (inl != sizeof(state->compression_in_stream)) {
- r = SSH_ERR_INTERNAL_ERROR;
- goto out;
- } else {
- state->compression_in_started = 1;
- memcpy(&state->compression_in_stream, inblob, inl);
- }
- if (outl == 0)
- state->compression_out_started = 0;
- else if (outl != sizeof(state->compression_out_stream)) {
- r = SSH_ERR_INTERNAL_ERROR;
- goto out;
- } else {
- state->compression_out_started = 1;
- memcpy(&state->compression_out_stream, outblob, outl);
- }
- r = 0;
- out:
- sshbuf_free(b);
- return r;
+ return SSH_ERR_INTERNAL_ERROR;
}
-void
-ssh_packet_set_compress_hooks(struct ssh *ssh, void *ctx,
- void *(*allocfunc)(void *, u_int, u_int),
- void (*freefunc)(void *, void *))
+static int
+compress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out)
{
- ssh->state->compression_out_stream.zalloc = (alloc_func)allocfunc;
- ssh->state->compression_out_stream.zfree = (free_func)freefunc;
- ssh->state->compression_out_stream.opaque = ctx;
- ssh->state->compression_in_stream.zalloc = (alloc_func)allocfunc;
- ssh->state->compression_in_stream.zfree = (free_func)freefunc;
- ssh->state->compression_in_stream.opaque = ctx;
+ return SSH_ERR_INTERNAL_ERROR;
}
-/*
- * Causes any further packets to be encrypted using the given key. The same
- * key is used for both sending and reception. However, both directions are
- * encrypted independently of each other.
- */
-
-void
-ssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen, int number)
+static int
+uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out)
{
-#ifdef WITH_SSH1
- struct session_state *state = ssh->state;
- const struct sshcipher *cipher = cipher_by_number(number);
- int r;
- const char *wmsg;
-
- if (cipher == NULL)
- fatal("%s: unknown cipher number %d", __func__, number);
- if (keylen < 20)
- fatal("%s: keylen too small: %d", __func__, keylen);
- if (keylen > SSH_SESSION_KEY_LENGTH)
- fatal("%s: keylen too big: %d", __func__, keylen);
- memcpy(state->ssh1_key, key, keylen);
- state->ssh1_keylen = keylen;
- if ((r = cipher_init(&state->send_context, cipher, key, keylen,
- NULL, 0, CIPHER_ENCRYPT)) != 0 ||
- (r = cipher_init(&state->receive_context, cipher, key, keylen,
- NULL, 0, CIPHER_DECRYPT) != 0))
- fatal("%s: cipher_init failed: %s", __func__, ssh_err(r));
- if (!state->cipher_warning_done &&
- ((wmsg = cipher_warning_message(&state->send_context)) != NULL ||
- (wmsg = cipher_warning_message(&state->send_context)) != NULL)) {
- error("Warning: %s", wmsg);
- state->cipher_warning_done = 1;
- }
-#endif /* WITH_SSH1 */
+ return SSH_ERR_INTERNAL_ERROR;
}
+#endif /* WITH_ZLIB */
-/*
- * Finalizes and sends the packet. If the encryption key has been set,
- * encrypts the packet before sending.
- */
-
-int
-ssh_packet_send1(struct ssh *ssh)
+void
+ssh_clear_newkeys(struct ssh *ssh, int mode)
{
- struct session_state *state = ssh->state;
- u_char buf[8], *cp;
- int r, padding, len;
- u_int checksum;
-
- /*
- * If using packet compression, compress the payload of the outgoing
- * packet.
- */
- if (state->packet_compression) {
- sshbuf_reset(state->compression_buffer);
- /* Skip padding. */
- if ((r = sshbuf_consume(state->outgoing_packet, 8)) != 0)
- goto out;
- /* padding */
- if ((r = sshbuf_put(state->compression_buffer,
- "\0\0\0\0\0\0\0\0", 8)) != 0)
- goto out;
- if ((r = compress_buffer(ssh, state->outgoing_packet,
- state->compression_buffer)) != 0)
- goto out;
- sshbuf_reset(state->outgoing_packet);
- if ((r = sshbuf_putb(state->outgoing_packet,
- state->compression_buffer)) != 0)
- goto out;
+ if (ssh->kex && ssh->kex->newkeys[mode]) {
+ kex_free_newkeys(ssh->kex->newkeys[mode]);
+ ssh->kex->newkeys[mode] = NULL;
}
- /* Compute packet length without padding (add checksum, remove padding). */
- len = sshbuf_len(state->outgoing_packet) + 4 - 8;
-
- /* Insert padding. Initialized to zero in packet_start1() */
- padding = 8 - len % 8;
- if (!state->send_context.plaintext) {
- cp = sshbuf_mutable_ptr(state->outgoing_packet);
- if (cp == NULL) {
- r = SSH_ERR_INTERNAL_ERROR;
- goto out;
- }
- arc4random_buf(cp + 8 - padding, padding);
- }
- if ((r = sshbuf_consume(state->outgoing_packet, 8 - padding)) != 0)
- goto out;
-
- /* Add check bytes. */
- checksum = ssh_crc32(sshbuf_ptr(state->outgoing_packet),
- sshbuf_len(state->outgoing_packet));
- POKE_U32(buf, checksum);
- if ((r = sshbuf_put(state->outgoing_packet, buf, 4)) != 0)
- goto out;
-
-#ifdef PACKET_DEBUG
- fprintf(stderr, "packet_send plain: ");
- sshbuf_dump(state->outgoing_packet, stderr);
-#endif
-
- /* Append to output. */
- POKE_U32(buf, len);
- if ((r = sshbuf_put(state->output, buf, 4)) != 0)
- goto out;
- if ((r = sshbuf_reserve(state->output,
- sshbuf_len(state->outgoing_packet), &cp)) != 0)
- goto out;
- if ((r = cipher_crypt(&state->send_context, 0, cp,
- sshbuf_ptr(state->outgoing_packet),
- sshbuf_len(state->outgoing_packet), 0, 0)) != 0)
- goto out;
-
-#ifdef PACKET_DEBUG
- fprintf(stderr, "encrypted: ");
- sshbuf_dump(state->output, stderr);
-#endif
- state->p_send.packets++;
- state->p_send.bytes += len +
- sshbuf_len(state->outgoing_packet);
- sshbuf_reset(state->outgoing_packet);
-
- /*
- * Note that the packet is now only buffered in output. It won't be
- * actually sent until ssh_packet_write_wait or ssh_packet_write_poll
- * is called.
- */
- r = 0;
- out:
- return r;
}
int
@@ -919,43 +871,38 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
struct sshenc *enc;
struct sshmac *mac;
struct sshcomp *comp;
- struct sshcipher_ctx *cc;
+ struct sshcipher_ctx **ccp;
+ struct packet_state *ps;
u_int64_t *max_blocks;
const char *wmsg;
int r, crypt_type;
+ const char *dir = mode == MODE_OUT ? "out" : "in";
debug2("set_newkeys: mode %d", mode);
if (mode == MODE_OUT) {
- cc = &state->send_context;
+ ccp = &state->send_context;
crypt_type = CIPHER_ENCRYPT;
- state->p_send.packets = state->p_send.blocks = 0;
+ ps = &state->p_send;
max_blocks = &state->max_blocks_out;
} else {
- cc = &state->receive_context;
+ ccp = &state->receive_context;
crypt_type = CIPHER_DECRYPT;
- state->p_read.packets = state->p_read.blocks = 0;
+ ps = &state->p_read;
max_blocks = &state->max_blocks_in;
}
if (state->newkeys[mode] != NULL) {
- debug("set_newkeys: rekeying");
- if ((r = cipher_cleanup(cc)) != 0)
- return r;
- enc = &state->newkeys[mode]->enc;
- mac = &state->newkeys[mode]->mac;
- comp = &state->newkeys[mode]->comp;
- mac_clear(mac);
- explicit_bzero(enc->iv, enc->iv_len);
- explicit_bzero(enc->key, enc->key_len);
- explicit_bzero(mac->key, mac->key_len);
- free(enc->name);
- free(enc->iv);
- free(enc->key);
- free(mac->name);
- free(mac->key);
- free(comp->name);
- free(state->newkeys[mode]);
+ 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);
+ kex_free_newkeys(state->newkeys[mode]);
+ state->newkeys[mode] = NULL;
}
+ /* note that both bytes and the seqnr are not reset */
+ ps->packets = ps->blocks = 0;
/* move newkeys from kex to state */
if ((state->newkeys[mode] = ssh->kex->newkeys[mode]) == NULL)
return SSH_ERR_INTERNAL_ERROR;
@@ -968,12 +915,14 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
return r;
}
mac->enabled = 1;
- DBG(debug("cipher_init_context: %d", mode));
- if ((r = cipher_init(cc, enc->cipher, enc->key, enc->key_len,
+ DBG(debug("%s: cipher_init_context: %s", __func__, dir));
+ cipher_free(*ccp);
+ *ccp = NULL;
+ if ((r = cipher_init(ccp, enc->cipher, enc->key, enc->key_len,
enc->iv, enc->iv_len, crypt_type)) != 0)
return r;
if (!state->cipher_warning_done &&
- (wmsg = cipher_warning_message(cc)) != NULL) {
+ (wmsg = cipher_warning_message(*ccp)) != NULL) {
error("Warning: %s", wmsg);
state->cipher_warning_done = 1;
}
@@ -997,18 +946,69 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
}
/*
* The 2^(blocksize*2) limit is too expensive for 3DES,
- * blowfish, etc, so enforce a 1GB limit for small blocksizes.
+ * so enforce a 1GB limit for small blocksizes.
+ * See RFC4344 section 3.2.
*/
if (enc->block_size >= 16)
*max_blocks = (u_int64_t)1 << (enc->block_size*2);
else
*max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
if (state->rekey_limit)
- *max_blocks = MIN(*max_blocks,
+ *max_blocks = MINIMUM(*max_blocks,
state->rekey_limit / enc->block_size);
+ debug("rekey %s after %llu blocks", dir,
+ (unsigned long long)*max_blocks);
return 0;
}
+#define MAX_PACKETS (1U<<31)
+static int
+ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len)
+{
+ struct session_state *state = ssh->state;
+ u_int32_t out_blocks;
+
+ /* XXX client can't cope with rekeying pre-auth */
+ if (!state->after_authentication)
+ return 0;
+
+ /* Haven't keyed yet or KEX in progress. */
+ if (ssh_packet_is_rekeying(ssh))
+ return 0;
+
+ /* Peer can't rekey */
+ if (ssh->compat & SSH_BUG_NOREKEY)
+ return 0;
+
+ /*
+ * Permit one packet in or out per rekey - this allows us to
+ * make progress when rekey limits are very small.
+ */
+ if (state->p_send.packets == 0 && state->p_read.packets == 0)
+ return 0;
+
+ /* Time-based rekeying */
+ if (state->rekey_interval != 0 &&
+ (int64_t)state->rekey_time + state->rekey_interval <= monotime())
+ return 1;
+
+ /*
+ * Always rekey when MAX_PACKETS sent in either direction
+ * As per RFC4344 section 3.1 we do this after 2^31 packets.
+ */
+ if (state->p_send.packets > MAX_PACKETS ||
+ state->p_read.packets > MAX_PACKETS)
+ return 1;
+
+ /* Rekey after (cipher-specific) maximum blocks */
+ out_blocks = ROUNDUP(outbound_packet_len,
+ state->newkeys[MODE_OUT]->enc.block_size);
+ return (state->max_blocks_out &&
+ (state->p_send.blocks + out_blocks > state->max_blocks_out)) ||
+ (state->max_blocks_in &&
+ (state->p_read.blocks > state->max_blocks_in));
+}
+
/*
* Delayed compression for SSH2 is enabled after authentication:
* This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent,
@@ -1047,6 +1047,20 @@ ssh_packet_enable_delayed_compress(struct ssh *ssh)
return 0;
}
+/* Used to mute debug logging for noisy packet types */
+int
+ssh_packet_log_type(u_char type)
+{
+ switch (type) {
+ case SSH2_MSG_CHANNEL_DATA:
+ case SSH2_MSG_CHANNEL_EXTENDED_DATA:
+ case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
+ return 0;
+ default:
+ return 1;
+ }
+}
+
/*
* Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
*/
@@ -1055,7 +1069,7 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
{
struct session_state *state = ssh->state;
u_char type, *cp, macbuf[SSH_DIGEST_MAX_LENGTH];
- u_char padlen, pad = 0;
+ u_char tmp, padlen, pad = 0;
u_int authlen = 0, aadlen = 0;
u_int len;
struct sshenc *enc = NULL;
@@ -1075,7 +1089,8 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
type = (sshbuf_ptr(state->outgoing_packet))[5];
-
+ if (ssh_packet_log_type(type))
+ debug3("send packet: type %u", type);
#ifdef PACKET_DEBUG
fprintf(stderr, "plain: ");
sshbuf_dump(state->outgoing_packet, stderr);
@@ -1112,19 +1127,29 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
if (padlen < 4)
padlen += block_size;
if (state->extra_pad) {
- /* will wrap if extra_pad+padlen > 255 */
+ tmp = state->extra_pad;
state->extra_pad =
- roundup(state->extra_pad, block_size);
- pad = state->extra_pad -
- ((len + padlen) % state->extra_pad);
+ ROUNDUP(state->extra_pad, block_size);
+ /* check if roundup overflowed */
+ if (state->extra_pad < tmp)
+ return SSH_ERR_INVALID_ARGUMENT;
+ tmp = (len + padlen) % state->extra_pad;
+ /* Check whether pad calculation below will underflow */
+ if (tmp > state->extra_pad)
+ return SSH_ERR_INVALID_ARGUMENT;
+ pad = state->extra_pad - tmp;
DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)",
__func__, pad, len, padlen, state->extra_pad));
+ tmp = padlen;
padlen += pad;
+ /* Check whether padlen calculation overflowed */
+ if (padlen < tmp)
+ return SSH_ERR_INVALID_ARGUMENT; /* overflow */
state->extra_pad = 0;
}
if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0)
goto out;
- if (enc && !state->send_context.plaintext) {
+ if (enc && !cipher_ctx_is_plaintext(state->send_context)) {
/* random padding */
arc4random_buf(cp, padlen);
} else {
@@ -1156,7 +1181,7 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
if ((r = sshbuf_reserve(state->output,
sshbuf_len(state->outgoing_packet) + authlen, &cp)) != 0)
goto out;
- if ((r = cipher_crypt(&state->send_context, state->p_send.seqnr, cp,
+ if ((r = cipher_crypt(state->send_context, state->p_send.seqnr, cp,
sshbuf_ptr(state->outgoing_packet),
len - aadlen, aadlen, authlen)) != 0)
goto out;
@@ -1197,34 +1222,58 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
return r;
}
+/* returns non-zero if the specified packet type is usec by KEX */
+static int
+ssh_packet_type_is_kex(u_char type)
+{
+ return
+ type >= SSH2_MSG_TRANSPORT_MIN &&
+ type <= SSH2_MSG_TRANSPORT_MAX &&
+ type != SSH2_MSG_SERVICE_REQUEST &&
+ type != SSH2_MSG_SERVICE_ACCEPT &&
+ type != SSH2_MSG_EXT_INFO;
+}
+
int
ssh_packet_send2(struct ssh *ssh)
{
struct session_state *state = ssh->state;
struct packet *p;
u_char type;
- int r;
+ int r, need_rekey;
+ if (sshbuf_len(state->outgoing_packet) < 6)
+ return SSH_ERR_INTERNAL_ERROR;
type = sshbuf_ptr(state->outgoing_packet)[5];
+ need_rekey = !ssh_packet_type_is_kex(type) &&
+ ssh_packet_need_rekeying(ssh, sshbuf_len(state->outgoing_packet));
- /* during rekeying we can only send key exchange messages */
- if (state->rekeying) {
- if ((type < SSH2_MSG_TRANSPORT_MIN) ||
- (type > SSH2_MSG_TRANSPORT_MAX) ||
- (type == SSH2_MSG_SERVICE_REQUEST) ||
- (type == SSH2_MSG_SERVICE_ACCEPT)) {
- debug("enqueue packet: %u", type);
- p = calloc(1, sizeof(*p));
- if (p == NULL)
- return SSH_ERR_ALLOC_FAIL;
- p->type = type;
- p->payload = state->outgoing_packet;
- TAILQ_INSERT_TAIL(&state->outgoing, p, next);
- state->outgoing_packet = sshbuf_new();
- if (state->outgoing_packet == NULL)
- return SSH_ERR_ALLOC_FAIL;
- return 0;
+ /*
+ * During rekeying we can only send key exchange messages.
+ * Queue everything else.
+ */
+ if ((need_rekey || state->rekeying) && !ssh_packet_type_is_kex(type)) {
+ if (need_rekey)
+ debug3("%s: rekex triggered", __func__);
+ debug("enqueue packet: %u", type);
+ p = calloc(1, sizeof(*p));
+ if (p == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ p->type = type;
+ p->payload = state->outgoing_packet;
+ TAILQ_INSERT_TAIL(&state->outgoing, p, next);
+ state->outgoing_packet = sshbuf_new();
+ if (state->outgoing_packet == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if (need_rekey) {
+ /*
+ * This packet triggered a rekey, so send the
+ * KEXINIT now.
+ * NB. reenters this function via kex_start_rekex().
+ */
+ return kex_start_rekex(ssh);
}
+ return 0;
}
/* rekeying starts with sending KEXINIT */
@@ -1240,10 +1289,22 @@ ssh_packet_send2(struct ssh *ssh)
state->rekey_time = monotime();
while ((p = TAILQ_FIRST(&state->outgoing))) {
type = p->type;
+ /*
+ * If this packet triggers a rekex, then skip the
+ * remaining packets in the queue for now.
+ * NB. re-enters this function via kex_start_rekex.
+ */
+ if (ssh_packet_need_rekeying(ssh,
+ sshbuf_len(p->payload))) {
+ debug3("%s: queued packet triggered rekex",
+ __func__);
+ return kex_start_rekex(ssh);
+ }
debug("dequeue packet: %u", type);
sshbuf_free(state->outgoing_packet);
state->outgoing_packet = p->payload;
TAILQ_REMOVE(&state->outgoing, p, next);
+ memset(p, 0, sizeof(*p));
free(p);
if ((r = ssh_packet_send2_wrapped(ssh)) != 0)
return r;
@@ -1262,14 +1323,14 @@ int
ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
{
struct session_state *state = ssh->state;
- int len, r, ms_remain, cont;
+ int len, r, ms_remain;
fd_set *setp;
char buf[8192];
struct timeval timeout, start, *timeoutp = NULL;
DBG(debug("packet_read()"));
- setp = (fd_set *)calloc(howmany(state->connection_in + 1,
+ setp = calloc(howmany(state->connection_in + 1,
NFDBITS), sizeof(fd_mask));
if (setp == NULL)
return SSH_ERR_ALLOC_FAIL;
@@ -1279,7 +1340,7 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
* been sent.
*/
if ((r = ssh_packet_write_wait(ssh)) != 0)
- return r;
+ goto out;
/* Stay in the loop until we have received a complete packet. */
for (;;) {
@@ -1287,13 +1348,6 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p);
if (r != 0)
break;
- if (!compat20 && (
- *typep == SSH_SMSG_SUCCESS
- || *typep == SSH_SMSG_FAILURE
- || *typep == SSH_CMSG_EOF
- || *typep == SSH_CMSG_EXIT_CONFIRMATION))
- if ((r = sshpkt_get_end(ssh)) != 0)
- break;
/* If we got a packet, return it. */
if (*typep != SSH_MSG_NONE)
break;
@@ -1311,17 +1365,19 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
}
/* Wait for some data to arrive. */
for (;;) {
- if (state->packet_timeout_ms != -1) {
+ if (state->packet_timeout_ms > 0) {
ms_to_timeval(&timeout, ms_remain);
- gettimeofday(&start, NULL);
+ monotime_tv(&start);
}
if ((r = select(state->connection_in + 1, setp,
NULL, NULL, timeoutp)) >= 0)
break;
if (errno != EAGAIN && errno != EINTR &&
- errno != EWOULDBLOCK)
- break;
- if (state->packet_timeout_ms == -1)
+ errno != EWOULDBLOCK) {
+ r = SSH_ERR_SYSTEM_ERROR;
+ goto out;
+ }
+ if (state->packet_timeout_ms <= 0)
continue;
ms_subtract_diff(&start, &ms_remain);
if (ms_remain <= 0) {
@@ -1329,23 +1385,26 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
break;
}
}
- if (r == 0)
- return SSH_ERR_CONN_TIMEOUT;
+ if (r == 0) {
+ r = SSH_ERR_CONN_TIMEOUT;
+ goto out;
+ }
/* Read data from the socket. */
- do {
- cont = 0;
- len = roaming_read(state->connection_in, buf,
- sizeof(buf), &cont);
- } while (len == 0 && cont);
- if (len == 0)
- return SSH_ERR_CONN_CLOSED;
- if (len < 0)
- return SSH_ERR_SYSTEM_ERROR;
+ len = read(state->connection_in, buf, sizeof(buf));
+ if (len == 0) {
+ r = SSH_ERR_CONN_CLOSED;
+ goto out;
+ }
+ if (len == -1) {
+ r = SSH_ERR_SYSTEM_ERROR;
+ goto out;
+ }
/* Append it to the buffer. */
if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0)
- return r;
+ goto out;
}
+ out:
free(setp);
return r;
}
@@ -1384,150 +1443,41 @@ ssh_packet_read_expect(struct ssh *ssh, u_int expected_type)
return 0;
}
-/* Checks if a full packet is available in the data received so far via
- * packet_process_incoming. If so, reads the packet; otherwise returns
- * SSH_MSG_NONE. This does not wait for data from the connection.
- *
- * SSH_MSG_DISCONNECT is handled specially here. Also,
- * SSH_MSG_IGNORE messages are skipped by this function and are never returned
- * to higher levels.
- */
-
-int
-ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
+static int
+ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
{
struct session_state *state = ssh->state;
- u_int len, padded_len;
- const char *emsg;
const u_char *cp;
- u_char *p;
- u_int checksum, stored_checksum;
+ size_t need;
int r;
+ if (ssh->kex)
+ return SSH_ERR_INTERNAL_ERROR;
*typep = SSH_MSG_NONE;
-
- /* Check if input size is less than minimum packet size. */
- if (sshbuf_len(state->input) < 4 + 8)
- return 0;
- /* Get length of incoming packet. */
- len = PEEK_U32(sshbuf_ptr(state->input));
- if (len < 1 + 2 + 2 || len > 256 * 1024) {
- if ((r = sshpkt_disconnect(ssh, "Bad packet length %u",
- len)) != 0)
- return r;
- return SSH_ERR_CONN_CORRUPT;
- }
- padded_len = (len + 8) & ~7;
-
- /* Check if the packet has been entirely received. */
- if (sshbuf_len(state->input) < 4 + padded_len)
- return 0;
-
- /* The entire packet is in buffer. */
-
- /* Consume packet length. */
- if ((r = sshbuf_consume(state->input, 4)) != 0)
- goto out;
-
- /*
- * Cryptographic attack detector for ssh
- * (C)1998 CORE-SDI, Buenos Aires Argentina
- * Ariel Futoransky(futo@core-sdi.com)
- */
- if (!state->receive_context.plaintext) {
- emsg = NULL;
- switch (detect_attack(&state->deattack,
- sshbuf_ptr(state->input), padded_len)) {
- case DEATTACK_OK:
- break;
- case DEATTACK_DETECTED:
- emsg = "crc32 compensation attack detected";
- break;
- case DEATTACK_DOS_DETECTED:
- emsg = "deattack denial of service detected";
- break;
- default:
- emsg = "deattack error";
- break;
- }
- if (emsg != NULL) {
- error("%s", emsg);
- if ((r = sshpkt_disconnect(ssh, "%s", emsg)) != 0 ||
- (r = ssh_packet_write_wait(ssh)) != 0)
- return r;
- return SSH_ERR_CONN_CORRUPT;
- }
- }
-
- /* Decrypt data to incoming_packet. */
+ cp = sshbuf_ptr(state->input);
+ if (state->packlen == 0) {
+ if (sshbuf_len(state->input) < 4 + 1)
+ return 0; /* packet is incomplete */
+ state->packlen = PEEK_U32(cp);
+ if (state->packlen < 4 + 1 ||
+ state->packlen > PACKET_MAX_SIZE)
+ return SSH_ERR_MESSAGE_INCOMPLETE;
+ }
+ need = state->packlen + 4;
+ if (sshbuf_len(state->input) < need)
+ return 0; /* packet is incomplete */
sshbuf_reset(state->incoming_packet);
- if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &p)) != 0)
- goto out;
- if ((r = cipher_crypt(&state->receive_context, 0, p,
- sshbuf_ptr(state->input), padded_len, 0, 0)) != 0)
- goto out;
-
- if ((r = sshbuf_consume(state->input, padded_len)) != 0)
- goto out;
-
-#ifdef PACKET_DEBUG
- fprintf(stderr, "read_poll plain: ");
- sshbuf_dump(state->incoming_packet, stderr);
-#endif
-
- /* Compute packet checksum. */
- checksum = ssh_crc32(sshbuf_ptr(state->incoming_packet),
- sshbuf_len(state->incoming_packet) - 4);
-
- /* Skip padding. */
- if ((r = sshbuf_consume(state->incoming_packet, 8 - len % 8)) != 0)
- goto out;
-
- /* Test check bytes. */
- if (len != sshbuf_len(state->incoming_packet)) {
- error("%s: len %d != sshbuf_len %zd", __func__,
- len, sshbuf_len(state->incoming_packet));
- if ((r = sshpkt_disconnect(ssh, "invalid packet length")) != 0 ||
- (r = ssh_packet_write_wait(ssh)) != 0)
- return r;
- return SSH_ERR_CONN_CORRUPT;
- }
-
- cp = sshbuf_ptr(state->incoming_packet) + len - 4;
- stored_checksum = PEEK_U32(cp);
- if (checksum != stored_checksum) {
- error("Corrupted check bytes on input");
- if ((r = sshpkt_disconnect(ssh, "connection corrupted")) != 0 ||
- (r = ssh_packet_write_wait(ssh)) != 0)
- return r;
- return SSH_ERR_CONN_CORRUPT;
- }
- if ((r = sshbuf_consume_end(state->incoming_packet, 4)) < 0)
- goto out;
-
- if (state->packet_compression) {
- sshbuf_reset(state->compression_buffer);
- if ((r = uncompress_buffer(ssh, state->incoming_packet,
- state->compression_buffer)) != 0)
- goto out;
- sshbuf_reset(state->incoming_packet);
- if ((r = sshbuf_putb(state->incoming_packet,
- state->compression_buffer)) != 0)
- goto out;
- }
- state->p_read.packets++;
- state->p_read.bytes += padded_len + 4;
- if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
- goto out;
- if (*typep < SSH_MSG_MIN || *typep > SSH_MSG_MAX) {
- error("Invalid ssh1 packet type: %d", *typep);
- if ((r = sshpkt_disconnect(ssh, "invalid packet type")) != 0 ||
- (r = ssh_packet_write_wait(ssh)) != 0)
- return r;
- return SSH_ERR_PROTOCOL_ERROR;
- }
- r = 0;
- out:
+ if ((r = sshbuf_put(state->incoming_packet, cp + 4,
+ state->packlen)) != 0 ||
+ (r = sshbuf_consume(state->input, need)) != 0 ||
+ (r = sshbuf_get_u8(state->incoming_packet, NULL)) != 0 ||
+ (r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
+ return r;
+ if (ssh_packet_log_type(*typep))
+ debug3("%s: type %u", __func__, *typep);
+ /* sshbuf_dump(state->incoming_packet, stderr); */
+ /* reset for next packet */
+ state->packlen = 0;
return r;
}
@@ -1536,13 +1486,16 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
{
struct session_state *state = ssh->state;
u_int padlen, need;
- u_char *cp, macbuf[SSH_DIGEST_MAX_LENGTH];
+ u_char *cp;
u_int maclen, aadlen = 0, authlen = 0, block_size;
struct sshenc *enc = NULL;
struct sshmac *mac = NULL;
struct sshcomp *comp = NULL;
int r;
+ if (state->mux)
+ return ssh_packet_read_poll2_mux(ssh, typep, seqnr_p);
+
*typep = SSH_MSG_NONE;
if (state->packet_discard)
@@ -1561,7 +1514,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
if (aadlen && state->packlen == 0) {
- if (cipher_get_length(&state->receive_context,
+ if (cipher_get_length(state->receive_context,
&state->packlen, state->p_read.seqnr,
sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0)
return 0;
@@ -1573,6 +1526,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
logit("Bad packet length %u.", state->packlen);
if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0)
return r;
+ return SSH_ERR_CONN_CORRUPT;
}
sshbuf_reset(state->incoming_packet);
} else if (state->packlen == 0) {
@@ -1586,7 +1540,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
if ((r = sshbuf_reserve(state->incoming_packet, block_size,
&cp)) != 0)
goto out;
- if ((r = cipher_crypt(&state->receive_context,
+ if ((r = cipher_crypt(state->receive_context,
state->p_send.seqnr, cp, sshbuf_ptr(state->input),
block_size, 0, 0)) != 0)
goto out;
@@ -1600,8 +1554,8 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
sshbuf_dump(state->incoming_packet, stderr);
#endif
logit("Bad packet length %u.", state->packlen);
- return ssh_packet_start_discard(ssh, enc, mac,
- state->packlen, PACKET_MAX_SIZE);
+ return ssh_packet_start_discard(ssh, enc, mac, 0,
+ PACKET_MAX_SIZE);
}
if ((r = sshbuf_consume(state->input, block_size)) != 0)
goto out;
@@ -1623,8 +1577,8 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
if (need % block_size != 0) {
logit("padding error: need %d block %d mod %d",
need, block_size, need % block_size);
- return ssh_packet_start_discard(ssh, enc, mac,
- state->packlen, PACKET_MAX_SIZE - block_size);
+ return ssh_packet_start_discard(ssh, enc, mac, 0,
+ PACKET_MAX_SIZE - block_size);
}
/*
* check if the entire packet has been received and
@@ -1635,46 +1589,46 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
* 'maclen' bytes of message authentication code.
*/
if (sshbuf_len(state->input) < aadlen + need + authlen + maclen)
- return 0;
+ return 0; /* packet is incomplete */
#ifdef PACKET_DEBUG
fprintf(stderr, "read_poll enc/full: ");
sshbuf_dump(state->input, stderr);
#endif
- /* EtM: compute mac over encrypted input */
+ /* EtM: check mac over encrypted input */
if (mac && mac->enabled && mac->etm) {
- if ((r = mac_compute(mac, state->p_read.seqnr,
+ if ((r = mac_check(mac, state->p_read.seqnr,
sshbuf_ptr(state->input), aadlen + need,
- macbuf, sizeof(macbuf))) != 0)
+ sshbuf_ptr(state->input) + aadlen + need + authlen,
+ maclen)) != 0) {
+ if (r == SSH_ERR_MAC_INVALID)
+ logit("Corrupted MAC on input.");
goto out;
+ }
}
if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need,
&cp)) != 0)
goto out;
- if ((r = cipher_crypt(&state->receive_context, state->p_read.seqnr, cp,
+ if ((r = cipher_crypt(state->receive_context, state->p_read.seqnr, cp,
sshbuf_ptr(state->input), need, aadlen, authlen)) != 0)
goto out;
if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0)
goto out;
- /*
- * compute MAC over seqnr and packet,
- * increment sequence number for incoming packet
- */
if (mac && mac->enabled) {
- if (!mac->etm)
- if ((r = mac_compute(mac, state->p_read.seqnr,
- sshbuf_ptr(state->incoming_packet),
- sshbuf_len(state->incoming_packet),
- macbuf, sizeof(macbuf))) != 0)
+ /* Not EtM: check MAC over cleartext */
+ if (!mac->etm && (r = mac_check(mac, state->p_read.seqnr,
+ sshbuf_ptr(state->incoming_packet),
+ sshbuf_len(state->incoming_packet),
+ sshbuf_ptr(state->input), maclen)) != 0) {
+ if (r != SSH_ERR_MAC_INVALID)
goto out;
- if (timingsafe_bcmp(macbuf, sshbuf_ptr(state->input),
- mac->mac_len) != 0) {
logit("Corrupted MAC on input.");
- if (need > PACKET_MAX_SIZE)
+ if (need + block_size > PACKET_MAX_SIZE)
return SSH_ERR_INTERNAL_ERROR;
return ssh_packet_start_discard(ssh, enc, mac,
- state->packlen, PACKET_MAX_SIZE - need);
+ sshbuf_len(state->incoming_packet),
+ PACKET_MAX_SIZE - need - block_size);
}
-
+ /* Remove MAC from input buffer */
DBG(debug("MAC #%d ok", state->p_read.seqnr));
if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
goto out;
@@ -1725,6 +1679,8 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
*/
if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
goto out;
+ if (ssh_packet_log_type(*typep))
+ debug3("receive packet: type %u", *typep);
if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN) {
if ((r = sshpkt_disconnect(ssh,
"Invalid ssh2 packet type: %d", *typep)) != 0 ||
@@ -1732,9 +1688,11 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
return r;
return SSH_ERR_PROTOCOL_ERROR;
}
- if (*typep == SSH2_MSG_NEWKEYS)
- r = ssh_set_newkeys(ssh, MODE_IN);
- else if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side)
+ if (state->hook_in != NULL &&
+ (r = state->hook_in(ssh, state->incoming_packet, typep,
+ state->hook_in_ctx)) != 0)
+ return r;
+ if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side)
r = ssh_packet_enable_delayed_compress(ssh);
else
r = 0;
@@ -1744,6 +1702,13 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
#endif
/* reset for next packet */
state->packlen = 0;
+
+ /* do we need to rekey? */
+ if (ssh_packet_need_rekeying(ssh, 0)) {
+ debug3("%s: rekex triggered", __func__);
+ if ((r = kex_start_rekex(ssh)) != 0)
+ return r;
+ }
out:
return r;
}
@@ -1758,74 +1723,48 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
for (;;) {
msg = NULL;
- if (compat20) {
- r = ssh_packet_read_poll2(ssh, typep, seqnr_p);
- if (r != 0)
- return r;
- if (*typep) {
- state->keep_alive_timeouts = 0;
- DBG(debug("received packet type %d", *typep));
- }
- switch (*typep) {
- case SSH2_MSG_IGNORE:
- debug3("Received SSH2_MSG_IGNORE");
- break;
- case SSH2_MSG_DEBUG:
- if ((r = sshpkt_get_u8(ssh, NULL)) != 0 ||
- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
- (r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
- if (msg)
- free(msg);
- return r;
- }
- debug("Remote: %.900s", msg);
- free(msg);
- break;
- case SSH2_MSG_DISCONNECT:
- if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
- return r;
- /* Ignore normal client exit notifications */
- do_log2(ssh->state->server_side &&
- reason == SSH2_DISCONNECT_BY_APPLICATION ?
- SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
- "Received disconnect from %s: %u: %.400s",
- ssh_remote_ipaddr(ssh), reason, msg);
- free(msg);
- return SSH_ERR_DISCONNECTED;
- case SSH2_MSG_UNIMPLEMENTED:
- if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0)
- return r;
- debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
- seqnr);
- break;
- default:
- return 0;
- }
- } else {
- r = ssh_packet_read_poll1(ssh, typep);
- switch (*typep) {
- case SSH_MSG_NONE:
- return SSH_MSG_NONE;
- case SSH_MSG_IGNORE:
- break;
- case SSH_MSG_DEBUG:
- if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
- return r;
- debug("Remote: %.900s", msg);
- free(msg);
- break;
- case SSH_MSG_DISCONNECT:
- if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
- return r;
- error("Received disconnect from %s: %.400s",
- ssh_remote_ipaddr(ssh), msg);
+ r = ssh_packet_read_poll2(ssh, typep, seqnr_p);
+ if (r != 0)
+ return r;
+ if (*typep) {
+ state->keep_alive_timeouts = 0;
+ DBG(debug("received packet type %d", *typep));
+ }
+ switch (*typep) {
+ case SSH2_MSG_IGNORE:
+ debug3("Received SSH2_MSG_IGNORE");
+ break;
+ case SSH2_MSG_DEBUG:
+ if ((r = sshpkt_get_u8(ssh, NULL)) != 0 ||
+ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
+ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
free(msg);
- return SSH_ERR_DISCONNECTED;
- default:
- DBG(debug("received packet type %d", *typep));
- return 0;
+ return r;
}
+ debug("Remote: %.900s", msg);
+ free(msg);
+ break;
+ case SSH2_MSG_DISCONNECT:
+ if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
+ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
+ return r;
+ /* Ignore normal client exit notifications */
+ do_log2(ssh->state->server_side &&
+ reason == SSH2_DISCONNECT_BY_APPLICATION ?
+ SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
+ "Received disconnect from %s port %d:"
+ "%u: %.400s", ssh_remote_ipaddr(ssh),
+ ssh_remote_port(ssh), reason, msg);
+ free(msg);
+ return SSH_ERR_DISCONNECTED;
+ case SSH2_MSG_UNIMPLEMENTED:
+ if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0)
+ return r;
+ debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
+ seqnr);
+ break;
+ default:
+ return 0;
}
}
}
@@ -1877,51 +1816,101 @@ ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...)
va_list args;
int r;
- if (compat20 && (ssh->compat & SSH_BUG_DEBUG))
+ if ((ssh->compat & SSH_BUG_DEBUG))
return;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
- if (compat20) {
- if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 ||
- (r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */
- (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
- (r = sshpkt_put_cstring(ssh, "")) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- } else {
- if ((r = sshpkt_start(ssh, SSH_MSG_DEBUG)) != 0 ||
- (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- }
- if ((r = ssh_packet_write_wait(ssh)) != 0)
+ debug3("sending debug message: %s", buf);
+
+ if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 ||
+ (r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */
+ (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
}
+void
+sshpkt_fmt_connection_id(struct ssh *ssh, char *s, size_t l)
+{
+ snprintf(s, l, "%.200s%s%s port %d",
+ ssh->log_preamble ? ssh->log_preamble : "",
+ ssh->log_preamble ? " " : "",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
+}
+
/*
* Pretty-print connection-terminating errors and exit.
*/
-void
-sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
+static void
+sshpkt_vfatal(struct ssh *ssh, int r, const char *fmt, va_list ap)
{
+ char *tag = NULL, remote_id[512];
+ int oerrno = errno;
+
+ sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
+
switch (r) {
case SSH_ERR_CONN_CLOSED:
- logit("Connection closed by %.200s", ssh_remote_ipaddr(ssh));
- cleanup_exit(255);
+ ssh_packet_clear_keys(ssh);
+ logdie("Connection closed by %s", remote_id);
case SSH_ERR_CONN_TIMEOUT:
- logit("Connection to %.200s timed out while "
- "waiting to write", ssh_remote_ipaddr(ssh));
- cleanup_exit(255);
+ ssh_packet_clear_keys(ssh);
+ logdie("Connection %s %s timed out",
+ ssh->state->server_side ? "from" : "to", remote_id);
+ case SSH_ERR_DISCONNECTED:
+ ssh_packet_clear_keys(ssh);
+ logdie("Disconnected from %s", remote_id);
+ case SSH_ERR_SYSTEM_ERROR:
+ if (errno == ECONNRESET) {
+ ssh_packet_clear_keys(ssh);
+ logdie("Connection reset by %s", remote_id);
+ }
+ /* FALLTHROUGH */
+ case SSH_ERR_NO_CIPHER_ALG_MATCH:
+ case SSH_ERR_NO_MAC_ALG_MATCH:
+ case SSH_ERR_NO_COMPRESS_ALG_MATCH:
+ case SSH_ERR_NO_KEX_ALG_MATCH:
+ case SSH_ERR_NO_HOSTKEY_ALG_MATCH:
+ if (ssh && ssh->kex && ssh->kex->failed_choice) {
+ ssh_packet_clear_keys(ssh);
+ errno = oerrno;
+ logdie("Unable to negotiate with %s: %s. "
+ "Their offer: %s", remote_id, ssh_err(r),
+ ssh->kex->failed_choice);
+ }
+ /* FALLTHROUGH */
default:
- fatal("%s%sConnection to %.200s: %s",
+ if (vasprintf(&tag, fmt, ap) == -1) {
+ ssh_packet_clear_keys(ssh);
+ logdie("%s: could not allocate failure message",
+ __func__);
+ }
+ ssh_packet_clear_keys(ssh);
+ errno = oerrno;
+ logdie("%s%sConnection %s %s: %s",
tag != NULL ? tag : "", tag != NULL ? ": " : "",
- ssh_remote_ipaddr(ssh), ssh_err(r));
+ ssh->state->server_side ? "from" : "to",
+ remote_id, ssh_err(r));
}
}
+void
+sshpkt_fatal(struct ssh *ssh, int r, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ sshpkt_vfatal(ssh, r, fmt, ap);
+ /* NOTREACHED */
+ va_end(ap);
+ logdie("%s: should have exited", __func__);
+}
+
/*
* Logs the error plus constructs and sends a disconnect packet, closes the
* connection, and exits. This function never returns. The error message
@@ -1931,7 +1920,7 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
void
ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
{
- char buf[1024];
+ char buf[1024], remote_id[512];
va_list args;
static int disconnecting = 0;
int r;
@@ -1944,22 +1933,23 @@ ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
* Format the message. Note that the caller must make sure the
* message is of limited size.
*/
+ sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
/* Display the error locally */
- logit("Disconnecting: %.100s", buf);
+ logit("Disconnecting %s: %.100s", remote_id, buf);
/*
* Send the disconnect message to the other side, and wait
* for it to get sent.
*/
if ((r = sshpkt_disconnect(ssh, "%s", buf)) != 0)
- sshpkt_fatal(ssh, __func__, r);
+ sshpkt_fatal(ssh, r, "%s", __func__);
if ((r = ssh_packet_write_wait(ssh)) != 0)
- sshpkt_fatal(ssh, __func__, r);
+ sshpkt_fatal(ssh, r, "%s", __func__);
/* Close the connection. */
ssh_packet_close(ssh);
@@ -1975,19 +1965,18 @@ ssh_packet_write_poll(struct ssh *ssh)
{
struct session_state *state = ssh->state;
int len = sshbuf_len(state->output);
- int cont, r;
+ int r;
if (len > 0) {
- cont = 0;
- len = roaming_write(state->connection_out,
- sshbuf_ptr(state->output), len, &cont);
+ len = write(state->connection_out,
+ sshbuf_ptr(state->output), len);
if (len == -1) {
if (errno == EINTR || errno == EAGAIN ||
errno == EWOULDBLOCK)
return 0;
return SSH_ERR_SYSTEM_ERROR;
}
- if (len == 0 && !cont)
+ if (len == 0)
return SSH_ERR_CONN_CLOSED;
if ((r = sshbuf_consume(state->output, len)) != 0)
return r;
@@ -2007,11 +1996,14 @@ ssh_packet_write_wait(struct ssh *ssh)
struct timeval start, timeout, *timeoutp = NULL;
struct session_state *state = ssh->state;
- setp = (fd_set *)calloc(howmany(state->connection_out + 1,
+ setp = calloc(howmany(state->connection_out + 1,
NFDBITS), sizeof(fd_mask));
if (setp == NULL)
return SSH_ERR_ALLOC_FAIL;
- ssh_packet_write_poll(ssh);
+ if ((r = ssh_packet_write_poll(ssh)) != 0) {
+ free(setp);
+ return r;
+ }
while (ssh_packet_have_data_to_write(ssh)) {
memset(setp, 0, howmany(state->connection_out + 1,
NFDBITS) * sizeof(fd_mask));
@@ -2022,9 +2014,9 @@ ssh_packet_write_wait(struct ssh *ssh)
timeoutp = &timeout;
}
for (;;) {
- if (state->packet_timeout_ms != -1) {
+ if (state->packet_timeout_ms > 0) {
ms_to_timeval(&timeout, ms_remain);
- gettimeofday(&start, NULL);
+ monotime_tv(&start);
}
if ((ret = select(state->connection_out + 1,
NULL, setp, NULL, timeoutp)) >= 0)
@@ -2032,7 +2024,7 @@ ssh_packet_write_wait(struct ssh *ssh)
if (errno != EAGAIN && errno != EINTR &&
errno != EWOULDBLOCK)
break;
- if (state->packet_timeout_ms == -1)
+ if (state->packet_timeout_ms <= 0)
continue;
ms_subtract_diff(&start, &ms_remain);
if (ms_remain <= 0) {
@@ -2076,14 +2068,14 @@ void
ssh_packet_set_tos(struct ssh *ssh, int tos)
{
#ifndef IP_TOS_IS_BROKEN
- if (!ssh_packet_connection_is_on_socket(ssh))
+ if (!ssh_packet_connection_is_on_socket(ssh) || tos == INT_MAX)
return;
switch (ssh_packet_connection_af(ssh)) {
# ifdef IP_TOS
case AF_INET:
debug3("%s: set IP_TOS 0x%02x", __func__, tos);
if (setsockopt(ssh->state->connection_in,
- IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
+ IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1)
error("setsockopt IP_TOS %d: %.100s:",
tos, strerror(errno));
break;
@@ -2092,7 +2084,7 @@ ssh_packet_set_tos(struct ssh *ssh, int tos)
case AF_INET6:
debug3("%s: set IPV6_TCLASS 0x%02x", __func__, tos);
if (setsockopt(ssh->state->connection_in,
- IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0)
+ IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) == -1)
error("setsockopt IPV6_TCLASS %d: %.100s:",
tos, strerror(errno));
break;
@@ -2169,60 +2161,11 @@ ssh_packet_get_maxsize(struct ssh *ssh)
return ssh->state->max_packet_size;
}
-/*
- * 9.2. Ignored Data Message
- *
- * byte SSH_MSG_IGNORE
- * string data
- *
- * All implementations MUST understand (and ignore) this message at any
- * time (after receiving the protocol version). No implementation is
- * required to send them. This message can be used as an additional
- * protection measure against advanced traffic analysis techniques.
- */
void
-ssh_packet_send_ignore(struct ssh *ssh, int nbytes)
+ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t seconds)
{
- u_int32_t rnd = 0;
- int r, i;
-
- if ((r = sshpkt_start(ssh, compat20 ?
- SSH2_MSG_IGNORE : SSH_MSG_IGNORE)) != 0 ||
- (r = sshpkt_put_u32(ssh, nbytes)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- for (i = 0; i < nbytes; i++) {
- if (i % 4 == 0)
- rnd = arc4random();
- if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- rnd >>= 8;
- }
-}
-
-#define MAX_PACKETS (1U<<31)
-int
-ssh_packet_need_rekeying(struct ssh *ssh)
-{
- struct session_state *state = ssh->state;
-
- if (ssh->compat & SSH_BUG_NOREKEY)
- return 0;
- return
- (state->p_send.packets > MAX_PACKETS) ||
- (state->p_read.packets > MAX_PACKETS) ||
- (state->max_blocks_out &&
- (state->p_send.blocks > state->max_blocks_out)) ||
- (state->max_blocks_in &&
- (state->p_read.blocks > state->max_blocks_in)) ||
- (state->rekey_interval != 0 && state->rekey_time +
- state->rekey_interval <= monotime());
-}
-
-void
-ssh_packet_set_rekey_limits(struct ssh *ssh, u_int32_t bytes, time_t seconds)
-{
- debug3("rekey after %lld bytes, %d seconds", (long long)bytes,
- (int)seconds);
+ debug3("rekey after %llu bytes, %u seconds", (unsigned long long)bytes,
+ (unsigned int)seconds);
ssh->state->rekey_limit = bytes;
ssh->state->rekey_interval = seconds;
}
@@ -2241,6 +2184,7 @@ void
ssh_packet_set_server(struct ssh *ssh)
{
ssh->state->server_side = 1;
+ ssh->kex->server = 1; /* XXX unify? */
}
void
@@ -2261,77 +2205,18 @@ ssh_packet_get_output(struct ssh *ssh)
return (void *)ssh->state->output;
}
-/* XXX TODO update roaming to new API (does not work anyway) */
-/*
- * Save the state for the real connection, and use a separate state when
- * resuming a suspended connection.
- */
-void
-ssh_packet_backup_state(struct ssh *ssh,
- struct ssh *backup_state)
-{
- struct ssh *tmp;
-
- close(ssh->state->connection_in);
- ssh->state->connection_in = -1;
- close(ssh->state->connection_out);
- ssh->state->connection_out = -1;
- if (backup_state)
- tmp = backup_state;
- else
- tmp = ssh_alloc_session_state();
- backup_state = ssh;
- ssh = tmp;
-}
-
-/* XXX FIXME FIXME FIXME */
-/*
- * Swap in the old state when resuming a connecion.
- */
-void
-ssh_packet_restore_state(struct ssh *ssh,
- struct ssh *backup_state)
-{
- struct ssh *tmp;
- u_int len;
- int r;
-
- tmp = backup_state;
- backup_state = ssh;
- ssh = tmp;
- ssh->state->connection_in = backup_state->state->connection_in;
- backup_state->state->connection_in = -1;
- ssh->state->connection_out = backup_state->state->connection_out;
- backup_state->state->connection_out = -1;
- len = sshbuf_len(backup_state->state->input);
- if (len > 0) {
- if ((r = sshbuf_putb(ssh->state->input,
- backup_state->state->input)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- sshbuf_reset(backup_state->state->input);
- add_recv_bytes(len);
- }
-}
-
/* Reset after_authentication and reset compression in post-auth privsep */
static int
ssh_packet_set_postauth(struct ssh *ssh)
{
- struct sshcomp *comp;
- int r, mode;
+ int r;
debug("%s: called", __func__);
/* This was set in net child, but is not visible in user child */
ssh->state->after_authentication = 1;
ssh->state->rekeying = 0;
- for (mode = 0; mode < MODE_MAX; mode++) {
- if (ssh->state->newkeys[mode] == NULL)
- continue;
- comp = &ssh->state->newkeys[mode]->comp;
- if (comp && comp->enabled &&
- (r = ssh_packet_init_compression(ssh)) != 0)
- return r;
- }
+ if ((r = ssh_packet_enable_delayed_compress(ssh)) != 0)
+ return r;
return 0;
}
@@ -2346,13 +2231,15 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
if ((r = sshbuf_put_string(m, kex->session_id,
kex->session_id_len)) != 0 ||
(r = sshbuf_put_u32(m, kex->we_need)) != 0 ||
+ (r = sshbuf_put_cstring(m, kex->hostkey_alg)) != 0 ||
(r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 ||
+ (r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 ||
(r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
(r = sshbuf_put_stringb(m, kex->my)) != 0 ||
(r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
- (r = sshbuf_put_u32(m, kex->flags)) != 0 ||
- (r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 ||
- (r = sshbuf_put_cstring(m, kex->server_version_string)) != 0)
+ (r = sshbuf_put_stringb(m, kex->client_version)) != 0 ||
+ (r = sshbuf_put_stringb(m, kex->server_version)) != 0 ||
+ (r = sshbuf_put_u32(m, kex->flags)) != 0)
return r;
return 0;
}
@@ -2374,15 +2261,13 @@ newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode)
enc = &newkey->enc;
mac = &newkey->mac;
comp = &newkey->comp;
- cc = (mode == MODE_OUT) ? &ssh->state->send_context :
- &ssh->state->receive_context;
+ cc = (mode == MODE_OUT) ? ssh->state->send_context :
+ ssh->state->receive_context;
if ((r = cipher_get_keyiv(cc, enc->iv, enc->iv_len)) != 0)
return r;
if ((b = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- /* The cipher struct is constant and shared, you export pointer */
if ((r = sshbuf_put_cstring(b, enc->name)) != 0 ||
- (r = sshbuf_put(b, &enc->cipher, sizeof(enc->cipher))) != 0 ||
(r = sshbuf_put_u32(b, enc->enabled)) != 0 ||
(r = sshbuf_put_u32(b, enc->block_size)) != 0 ||
(r = sshbuf_put_string(b, enc->key, enc->key_len)) != 0 ||
@@ -2395,13 +2280,11 @@ newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode)
goto out;
}
if ((r = sshbuf_put_u32(b, comp->type)) != 0 ||
- (r = sshbuf_put_u32(b, comp->enabled)) != 0 ||
(r = sshbuf_put_cstring(b, comp->name)) != 0)
goto out;
r = sshbuf_put_stringb(m, b);
out:
- if (b != NULL)
- sshbuf_free(b);
+ sshbuf_free(b);
return r;
}
@@ -2410,64 +2293,25 @@ int
ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m)
{
struct session_state *state = ssh->state;
- u_char *p;
- size_t slen, rlen;
- int r, ssh1cipher;
-
- if (!compat20) {
- ssh1cipher = cipher_get_number(state->receive_context.cipher);
- slen = cipher_get_keyiv_len(&state->send_context);
- rlen = cipher_get_keyiv_len(&state->receive_context);
- if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 ||
- (r = sshbuf_put_u32(m, ssh1cipher)) != 0 ||
- (r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 ||
- (r = sshbuf_put_u32(m, slen)) != 0 ||
- (r = sshbuf_reserve(m, slen, &p)) != 0 ||
- (r = cipher_get_keyiv(&state->send_context, p, slen)) != 0 ||
- (r = sshbuf_put_u32(m, rlen)) != 0 ||
- (r = sshbuf_reserve(m, rlen, &p)) != 0 ||
- (r = cipher_get_keyiv(&state->receive_context, p, rlen)) != 0)
- return r;
- } else {
- if ((r = kex_to_blob(m, ssh->kex)) != 0 ||
- (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 ||
- (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 ||
- (r = sshbuf_put_u32(m, state->rekey_limit)) != 0 ||
- (r = sshbuf_put_u32(m, state->rekey_interval)) != 0 ||
- (r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 ||
- (r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 ||
- (r = sshbuf_put_u32(m, state->p_send.packets)) != 0 ||
- (r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 ||
- (r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 ||
- (r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 ||
- (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 ||
- (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0)
- return r;
- }
-
- slen = cipher_get_keycontext(&state->send_context, NULL);
- rlen = cipher_get_keycontext(&state->receive_context, NULL);
- if ((r = sshbuf_put_u32(m, slen)) != 0 ||
- (r = sshbuf_reserve(m, slen, &p)) != 0)
- return r;
- if (cipher_get_keycontext(&state->send_context, p) != (int)slen)
- return SSH_ERR_INTERNAL_ERROR;
- if ((r = sshbuf_put_u32(m, rlen)) != 0 ||
- (r = sshbuf_reserve(m, rlen, &p)) != 0)
- return r;
- if (cipher_get_keycontext(&state->receive_context, p) != (int)rlen)
- return SSH_ERR_INTERNAL_ERROR;
+ int r;
- if ((r = ssh_packet_get_compress_state(m, ssh)) != 0 ||
+ if ((r = kex_to_blob(m, ssh->kex)) != 0 ||
+ (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 ||
+ (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 ||
+ (r = sshbuf_put_u64(m, state->rekey_limit)) != 0 ||
+ (r = sshbuf_put_u32(m, state->rekey_interval)) != 0 ||
+ (r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 ||
+ (r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 ||
+ (r = sshbuf_put_u32(m, state->p_send.packets)) != 0 ||
+ (r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 ||
+ (r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 ||
+ (r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 ||
+ (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 ||
+ (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0 ||
(r = sshbuf_put_stringb(m, state->input)) != 0 ||
(r = sshbuf_put_stringb(m, state->output)) != 0)
return r;
- if (compat20) {
- if ((r = sshbuf_put_u64(m, get_sent_bytes())) != 0 ||
- (r = sshbuf_put_u64(m, get_recv_bytes())) != 0)
- return r;
- }
return 0;
}
@@ -2497,12 +2341,15 @@ newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode)
comp = &newkey->comp;
if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 0 ||
- (r = sshbuf_get(b, &enc->cipher, sizeof(enc->cipher))) != 0 ||
(r = sshbuf_get_u32(b, (u_int *)&enc->enabled)) != 0 ||
(r = sshbuf_get_u32(b, &enc->block_size)) != 0 ||
(r = sshbuf_get_string(b, &enc->key, &keylen)) != 0 ||
(r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0)
goto out;
+ if ((enc->cipher = cipher_by_name(enc->name)) == NULL) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
if (cipher_authlen(enc->cipher) == 0) {
if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0)
goto out;
@@ -2518,14 +2365,8 @@ newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode)
mac->key_len = maclen;
}
if ((r = sshbuf_get_u32(b, &comp->type)) != 0 ||
- (r = sshbuf_get_u32(b, (u_int *)&comp->enabled)) != 0 ||
(r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0)
goto out;
- if (enc->name == NULL ||
- cipher_by_name(enc->name) != enc->cipher) {
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
if (sshbuf_len(b) != 0) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
@@ -2536,10 +2377,8 @@ newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode)
newkey = NULL;
r = 0;
out:
- if (newkey != NULL)
- free(newkey);
- if (b != NULL)
- sshbuf_free(b);
+ free(newkey);
+ sshbuf_free(b);
return r;
}
@@ -2550,37 +2389,30 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
struct kex *kex;
int r;
- if ((kex = calloc(1, sizeof(struct kex))) == NULL ||
- (kex->my = sshbuf_new()) == NULL ||
- (kex->peer = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
+ if ((kex = kex_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 ||
(r = sshbuf_get_u32(m, &kex->we_need)) != 0 ||
+ (r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 ||
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 ||
+ (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 ||
(r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
(r = sshbuf_get_stringb(m, kex->my)) != 0 ||
(r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
- (r = sshbuf_get_u32(m, &kex->flags)) != 0 ||
- (r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 ||
- (r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0)
+ (r = sshbuf_get_stringb(m, kex->client_version)) != 0 ||
+ (r = sshbuf_get_stringb(m, kex->server_version)) != 0 ||
+ (r = sshbuf_get_u32(m, &kex->flags)) != 0)
goto out;
kex->server = 1;
kex->done = 1;
r = 0;
out:
if (r != 0 || kexp == NULL) {
- if (kex != NULL) {
- if (kex->my != NULL)
- sshbuf_free(kex->my);
- if (kex->peer != NULL)
- sshbuf_free(kex->peer);
- free(kex);
- }
+ kex_free(kex);
if (kexp != NULL)
*kexp = NULL;
} else {
+ kex_free(*kexp);
*kexp = kex;
}
return r;
@@ -2594,65 +2426,35 @@ int
ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
{
struct session_state *state = ssh->state;
- const u_char *ssh1key, *ivin, *ivout, *keyin, *keyout, *input, *output;
- size_t ssh1keylen, rlen, slen, ilen, olen;
+ const u_char *input, *output;
+ size_t ilen, olen;
int r;
- u_int ssh1cipher = 0;
- u_int64_t sent_bytes = 0, recv_bytes = 0;
-
- if (!compat20) {
- if ((r = sshbuf_get_u32(m, &state->remote_protocol_flags)) != 0 ||
- (r = sshbuf_get_u32(m, &ssh1cipher)) != 0 ||
- (r = sshbuf_get_string_direct(m, &ssh1key, &ssh1keylen)) != 0 ||
- (r = sshbuf_get_string_direct(m, &ivout, &slen)) != 0 ||
- (r = sshbuf_get_string_direct(m, &ivin, &rlen)) != 0)
- return r;
- if (ssh1cipher > INT_MAX)
- return SSH_ERR_KEY_UNKNOWN_CIPHER;
- ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen,
- (int)ssh1cipher);
- if (cipher_get_keyiv_len(&state->send_context) != (int)slen ||
- cipher_get_keyiv_len(&state->receive_context) != (int)rlen)
- return SSH_ERR_INVALID_FORMAT;
- if ((r = cipher_set_keyiv(&state->send_context, ivout)) != 0 ||
- (r = cipher_set_keyiv(&state->receive_context, ivin)) != 0)
- return r;
- } else {
- if ((r = kex_from_blob(m, &ssh->kex)) != 0 ||
- (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 ||
- (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 ||
- (r = sshbuf_get_u32(m, &state->rekey_limit)) != 0 ||
- (r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 ||
- (r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 ||
- (r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 ||
- (r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 ||
- (r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 ||
- (r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 ||
- (r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 ||
- (r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 ||
- (r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0)
- return r;
- /*
- * We set the time here so that in post-auth privsep slave we
- * count from the completion of the authentication.
- */
- state->rekey_time = monotime();
- /* XXX ssh_set_newkeys overrides p_read.packets? XXX */
- if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 ||
- (r = ssh_set_newkeys(ssh, MODE_OUT)) != 0)
- return r;
- }
- if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 ||
- (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0)
+
+ if ((r = kex_from_blob(m, &ssh->kex)) != 0 ||
+ (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 ||
+ (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 ||
+ (r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 ||
+ (r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 ||
+ (r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 ||
+ (r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 ||
+ (r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 ||
+ (r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 ||
+ (r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 ||
+ (r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 ||
+ (r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 ||
+ (r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0)
+ return r;
+ /*
+ * We set the time here so that in post-auth privsep slave we
+ * count from the completion of the authentication.
+ */
+ state->rekey_time = monotime();
+ /* XXX ssh_set_newkeys overrides p_read.packets? XXX */
+ if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 ||
+ (r = ssh_set_newkeys(ssh, MODE_OUT)) != 0)
return r;
- if (cipher_get_keycontext(&state->send_context, NULL) != (int)slen ||
- cipher_get_keycontext(&state->receive_context, NULL) != (int)rlen)
- return SSH_ERR_INVALID_FORMAT;
- cipher_set_keycontext(&state->send_context, keyout);
- cipher_set_keycontext(&state->receive_context, keyin);
- if ((r = ssh_packet_set_compress_state(ssh, m)) != 0 ||
- (r = ssh_packet_set_postauth(ssh)) != 0)
+ if ((r = ssh_packet_set_postauth(ssh)) != 0)
return r;
sshbuf_reset(state->input);
@@ -2663,12 +2465,6 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
(r = sshbuf_put(state->output, output, olen)) != 0)
return r;
- if (compat20) {
- if ((r = sshbuf_get_u64(m, &sent_bytes)) != 0 ||
- (r = sshbuf_get_u64(m, &recv_bytes)) != 0)
- return r;
- roam_set_bytes(sent_bytes, recv_bytes);
- }
if (sshbuf_len(m))
return SSH_ERR_INVALID_FORMAT;
debug3("%s: done", __func__);
@@ -2727,23 +2523,22 @@ sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v)
return sshbuf_put_stringb(ssh->state->outgoing_packet, v);
}
-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
int
-sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g)
+sshpkt_getb_froms(struct ssh *ssh, struct sshbuf **valp)
{
- return sshbuf_put_ec(ssh->state->outgoing_packet, v, g);
+ return sshbuf_froms(ssh->state->incoming_packet, valp);
}
-#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
-#ifdef WITH_SSH1
+#ifdef WITH_OPENSSL
+#ifdef OPENSSL_HAS_ECC
int
-sshpkt_put_bignum1(struct ssh *ssh, const BIGNUM *v)
+sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g)
{
- return sshbuf_put_bignum1(ssh->state->outgoing_packet, v);
+ return sshbuf_put_ec(ssh->state->outgoing_packet, v, g);
}
-#endif /* WITH_SSH1 */
+#endif /* OPENSSL_HAS_ECC */
+
-#ifdef WITH_OPENSSL
int
sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v)
{
@@ -2790,32 +2585,30 @@ sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp)
}
int
-sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp)
+sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp)
{
- return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp);
+ return sshbuf_peek_string_direct(ssh->state->incoming_packet, valp, lenp);
}
-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
int
-sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g)
+sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp)
{
- return sshbuf_get_ec(ssh->state->incoming_packet, v, g);
+ return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp);
}
-#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
-#ifdef WITH_SSH1
+#ifdef WITH_OPENSSL
+#ifdef OPENSSL_HAS_ECC
int
-sshpkt_get_bignum1(struct ssh *ssh, BIGNUM *v)
+sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g)
{
- return sshbuf_get_bignum1(ssh->state->incoming_packet, v);
+ return sshbuf_get_ec(ssh->state->incoming_packet, v, g);
}
-#endif /* WITH_SSH1 */
+#endif /* OPENSSL_HAS_ECC */
-#ifdef WITH_OPENSSL
int
-sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v)
+sshpkt_get_bignum2(struct ssh *ssh, BIGNUM **valp)
{
- return sshbuf_get_bignum2(ssh->state->incoming_packet, v);
+ return sshbuf_get_bignum2(ssh->state->incoming_packet, valp);
}
#endif /* WITH_OPENSSL */
@@ -2840,15 +2633,74 @@ sshpkt_ptr(struct ssh *ssh, size_t *lenp)
int
sshpkt_start(struct ssh *ssh, u_char type)
{
- u_char buf[9];
- int len;
+ u_char buf[6]; /* u32 packet length, u8 pad len, u8 type */
DBG(debug("packet_start[%d]", type));
- len = compat20 ? 6 : 9;
- memset(buf, 0, len - 1);
- buf[len - 1] = type;
+ memset(buf, 0, sizeof(buf));
+ buf[sizeof(buf) - 1] = type;
sshbuf_reset(ssh->state->outgoing_packet);
- return sshbuf_put(ssh->state->outgoing_packet, buf, len);
+ return sshbuf_put(ssh->state->outgoing_packet, buf, sizeof(buf));
+}
+
+static int
+ssh_packet_send_mux(struct ssh *ssh)
+{
+ struct session_state *state = ssh->state;
+ u_char type, *cp;
+ size_t len;
+ int r;
+
+ if (ssh->kex)
+ return SSH_ERR_INTERNAL_ERROR;
+ len = sshbuf_len(state->outgoing_packet);
+ if (len < 6)
+ return SSH_ERR_INTERNAL_ERROR;
+ cp = sshbuf_mutable_ptr(state->outgoing_packet);
+ type = cp[5];
+ if (ssh_packet_log_type(type))
+ debug3("%s: type %u", __func__, type);
+ /* drop everything, but the connection protocol */
+ if (type >= SSH2_MSG_CONNECTION_MIN &&
+ type <= SSH2_MSG_CONNECTION_MAX) {
+ POKE_U32(cp, len - 4);
+ if ((r = sshbuf_putb(state->output,
+ state->outgoing_packet)) != 0)
+ return r;
+ /* sshbuf_dump(state->output, stderr); */
+ }
+ sshbuf_reset(state->outgoing_packet);
+ return 0;
+}
+
+/*
+ * 9.2. Ignored Data Message
+ *
+ * byte SSH_MSG_IGNORE
+ * string data
+ *
+ * All implementations MUST understand (and ignore) this message at any
+ * time (after receiving the protocol version). No implementation is
+ * required to send them. This message can be used as an additional
+ * protection measure against advanced traffic analysis techniques.
+ */
+int
+sshpkt_msg_ignore(struct ssh *ssh, u_int nbytes)
+{
+ u_int32_t rnd = 0;
+ int r;
+ u_int i;
+
+ if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 ||
+ (r = sshpkt_put_u32(ssh, nbytes)) != 0)
+ return r;
+ for (i = 0; i < nbytes; i++) {
+ if (i % 4 == 0)
+ rnd = arc4random();
+ if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0)
+ return r;
+ rnd >>= 8;
+ }
+ return 0;
}
/* send it */
@@ -2856,10 +2708,9 @@ sshpkt_start(struct ssh *ssh, u_char type)
int
sshpkt_send(struct ssh *ssh)
{
- if (compat20)
- return ssh_packet_send2(ssh);
- else
- return ssh_packet_send1(ssh);
+ if (ssh->state && ssh->state->mux)
+ return ssh_packet_send_mux(ssh);
+ return ssh_packet_send2(ssh);
}
int
@@ -2873,19 +2724,12 @@ sshpkt_disconnect(struct ssh *ssh, const char *fmt,...)
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
- if (compat20) {
- if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
- (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
- (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
- (r = sshpkt_put_cstring(ssh, "")) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- return r;
- } else {
- if ((r = sshpkt_start(ssh, SSH_MSG_DISCONNECT)) != 0 ||
- (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- return r;
- }
+ if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
+ (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ return r;
return 0;
}
diff --git a/packet.h b/packet.h
index 7b06544e..c2544bd9 100644
--- a/packet.h
+++ b/packet.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.h,v 1.66 2015/01/30 01:13:33 djm Exp $ */
+/* $OpenBSD: packet.h,v 1.92 2020/03/06 18:11:10 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -56,9 +56,15 @@ struct ssh {
/* Key exchange */
struct kex *kex;
- /* cached remote ip address and port*/
+ /* cached local and remote ip addresses and ports */
char *remote_ipaddr;
int remote_port;
+ char *local_ipaddr;
+ int local_port;
+ char *rdomain_in;
+
+ /* Optional preamble for log messages (e.g. username) */
+ char *log_preamble;
/* Dispatcher table */
dispatch_fn *dispatch[DISPATCH_MAX];
@@ -72,10 +78,19 @@ struct ssh {
TAILQ_HEAD(, key_entry) private_keys;
TAILQ_HEAD(, key_entry) public_keys;
+ /* Client/Server authentication context */
+ void *authctxt;
+
+ /* Channels context */
+ struct ssh_channels *chanctxt;
+
/* APP data */
void *app_data;
};
+typedef int (ssh_packet_hook_fn)(struct ssh *, struct sshbuf *,
+ u_char *, void *);
+
struct ssh *ssh_alloc_session_state(void);
struct ssh *ssh_packet_set_connection(struct ssh *, int, int);
void ssh_packet_set_timeout(struct ssh *, int, int);
@@ -85,24 +100,31 @@ void ssh_packet_set_nonblocking(struct ssh *);
int ssh_packet_get_connection_in(struct ssh *);
int ssh_packet_get_connection_out(struct ssh *);
void ssh_packet_close(struct ssh *);
-void ssh_packet_set_encryption_key(struct ssh *, const u_char *, u_int, int);
+void ssh_packet_set_input_hook(struct ssh *, ssh_packet_hook_fn *, void *);
+void ssh_packet_clear_keys(struct ssh *);
+void ssh_clear_newkeys(struct ssh *, int);
+
+int ssh_packet_is_rekeying(struct ssh *);
void ssh_packet_set_protocol_flags(struct ssh *, u_int);
u_int ssh_packet_get_protocol_flags(struct ssh *);
-int ssh_packet_start_compression(struct ssh *, int);
void ssh_packet_set_tos(struct ssh *, int);
void ssh_packet_set_interactive(struct ssh *, int, int, int);
int ssh_packet_is_interactive(struct ssh *);
void ssh_packet_set_server(struct ssh *);
void ssh_packet_set_authenticated(struct ssh *);
+void ssh_packet_set_mux(struct ssh *);
+int ssh_packet_get_mux(struct ssh *);
+int ssh_packet_set_log_preamble(struct ssh *, const char *, ...)
+ __attribute__((format(printf, 2, 3)));
+
+int ssh_packet_log_type(u_char);
-int ssh_packet_send1(struct ssh *);
int ssh_packet_send2_wrapped(struct ssh *);
int ssh_packet_send2(struct ssh *);
int ssh_packet_read(struct ssh *);
int ssh_packet_read_expect(struct ssh *, u_int type);
int ssh_packet_read_poll(struct ssh *);
-int ssh_packet_read_poll1(struct ssh *, u_char *);
int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p);
int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len);
int ssh_packet_read_seqnr(struct ssh *, u_char *, u_int32_t *seqnr_p);
@@ -117,11 +139,6 @@ void ssh_packet_send_debug(struct ssh *, const char *fmt, ...) __attribute__
int ssh_set_newkeys(struct ssh *, int mode);
void ssh_packet_get_bytes(struct ssh *, u_int64_t *, u_int64_t *);
-typedef void *(ssh_packet_comp_alloc_func)(void *, u_int, u_int);
-typedef void (ssh_packet_comp_free_func)(void *, void *);
-void ssh_packet_set_compress_hooks(struct ssh *, void *,
- ssh_packet_comp_alloc_func *, ssh_packet_comp_free_func *);
-
int ssh_packet_write_poll(struct ssh *);
int ssh_packet_write_wait(struct ssh *);
int ssh_packet_have_data_to_write(struct ssh *);
@@ -129,10 +146,9 @@ int ssh_packet_not_very_much_data_to_write(struct ssh *);
int ssh_packet_connection_is_on_socket(struct ssh *);
int ssh_packet_remaining(struct ssh *);
-void ssh_packet_send_ignore(struct ssh *, int);
-void tty_make_modes(int, struct termios *);
-void tty_parse_modes(int, int *);
+void ssh_tty_make_modes(struct ssh *, int, struct termios *);
+void ssh_tty_parse_modes(struct ssh *, int);
void ssh_packet_set_alive_timeouts(struct ssh *, int);
int ssh_packet_inc_alive_timeouts(struct ssh *);
@@ -143,15 +159,14 @@ int ssh_packet_get_state(struct ssh *, struct sshbuf *);
int ssh_packet_set_state(struct ssh *, struct sshbuf *);
const char *ssh_remote_ipaddr(struct ssh *);
+int ssh_remote_port(struct ssh *);
+const char *ssh_local_ipaddr(struct ssh *);
+int ssh_local_port(struct ssh *);
+const char *ssh_packet_rdomain_in(struct ssh *);
-int ssh_packet_need_rekeying(struct ssh *);
-void ssh_packet_set_rekey_limits(struct ssh *, u_int32_t, time_t);
+void ssh_packet_set_rekey_limits(struct ssh *, u_int64_t, u_int32_t);
time_t ssh_packet_get_rekey_timeout(struct ssh *);
-/* XXX FIXME */
-void ssh_packet_backup_state(struct ssh *, struct ssh *);
-void ssh_packet_restore_state(struct ssh *, struct ssh *);
-
void *ssh_packet_get_input(struct ssh *);
void *ssh_packet_get_output(struct ssh *);
@@ -161,7 +176,10 @@ int sshpkt_send(struct ssh *ssh);
int sshpkt_disconnect(struct ssh *, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
int sshpkt_add_padding(struct ssh *, u_char);
-void sshpkt_fatal(struct ssh *ssh, const char *tag, int r);
+void sshpkt_fatal(struct ssh *ssh, int r, const char *fmt, ...)
+ __attribute__((format(printf, 3, 4)))
+ __attribute__((noreturn));
+int sshpkt_msg_ignore(struct ssh *, u_int);
int sshpkt_put(struct ssh *ssh, const void *v, size_t len);
int sshpkt_putb(struct ssh *ssh, const struct sshbuf *b);
@@ -172,7 +190,6 @@ int sshpkt_put_string(struct ssh *ssh, const void *v, size_t len);
int sshpkt_put_cstring(struct ssh *ssh, const void *v);
int sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v);
int sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g);
-int sshpkt_put_bignum1(struct ssh *ssh, const BIGNUM *v);
int sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v);
int sshpkt_get(struct ssh *ssh, void *valp, size_t len);
@@ -181,17 +198,15 @@ int sshpkt_get_u32(struct ssh *ssh, u_int32_t *valp);
int sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp);
int sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp);
int sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp);
+int sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp);
int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp);
+int sshpkt_getb_froms(struct ssh *ssh, struct sshbuf **valp);
int sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g);
-int sshpkt_get_bignum1(struct ssh *ssh, BIGNUM *v);
-int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v);
+int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM **valp);
int sshpkt_get_end(struct ssh *ssh);
+void sshpkt_fmt_connection_id(struct ssh *ssh, char *s, size_t l);
const u_char *sshpkt_ptr(struct ssh *, size_t *lenp);
-/* OLD API */
-extern struct ssh *active_state;
-#include "opacket.h"
-
#if !defined(WITH_OPENSSL)
# undef BIGNUM
# undef EC_KEY
diff --git a/pathnames.h b/pathnames.h
index ec89fc66..f7ca5a75 100644
--- a/pathnames.h
+++ b/pathnames.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pathnames.h,v 1.24 2013/12/06 13:39:49 markus Exp $ */
+/* $OpenBSD: pathnames.h,v 1.31 2019/11/12 19:33:08 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -36,14 +36,12 @@
*/
#define _PATH_SERVER_CONFIG_FILE SSHDIR "/sshd_config"
#define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config"
-#define _PATH_HOST_KEY_FILE SSHDIR "/ssh_host_key"
#define _PATH_HOST_DSA_KEY_FILE SSHDIR "/ssh_host_dsa_key"
#define _PATH_HOST_ECDSA_KEY_FILE SSHDIR "/ssh_host_ecdsa_key"
#define _PATH_HOST_ED25519_KEY_FILE SSHDIR "/ssh_host_ed25519_key"
+#define _PATH_HOST_XMSS_KEY_FILE SSHDIR "/ssh_host_xmss_key"
#define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key"
#define _PATH_DH_MODULI SSHDIR "/moduli"
-/* Backwards compatibility */
-#define _PATH_DH_PRIMES SSHDIR "/primes"
#ifndef _PATH_SSH_PROGRAM
#define _PATH_SSH_PROGRAM "/usr/bin/ssh"
@@ -74,11 +72,13 @@
* Name of the default file containing client-side authentication key. This
* file should only be readable by the user him/herself.
*/
-#define _PATH_SSH_CLIENT_IDENTITY _PATH_SSH_USER_DIR "/identity"
#define _PATH_SSH_CLIENT_ID_DSA _PATH_SSH_USER_DIR "/id_dsa"
#define _PATH_SSH_CLIENT_ID_ECDSA _PATH_SSH_USER_DIR "/id_ecdsa"
#define _PATH_SSH_CLIENT_ID_RSA _PATH_SSH_USER_DIR "/id_rsa"
#define _PATH_SSH_CLIENT_ID_ED25519 _PATH_SSH_USER_DIR "/id_ed25519"
+#define _PATH_SSH_CLIENT_ID_XMSS _PATH_SSH_USER_DIR "/id_xmss"
+#define _PATH_SSH_CLIENT_ID_ECDSA_SK _PATH_SSH_USER_DIR "/id_ecdsa_sk"
+#define _PATH_SSH_CLIENT_ID_ED25519_SK _PATH_SSH_USER_DIR "/id_ed25519_sk"
/*
* Configuration file in user's home directory. This file need not be
@@ -134,6 +134,11 @@
#define _PATH_SSH_PKCS11_HELPER "/usr/libexec/ssh-pkcs11-helper"
#endif
+/* Location of ssh-sk-helper to support keys in security keys */
+#ifndef _PATH_SSH_SK_HELPER
+#define _PATH_SSH_SK_HELPER "/usr/libexec/ssh-sk-helper"
+#endif
+
/* xauth for X11 forwarding */
#ifndef _PATH_XAUTH
#define _PATH_XAUTH "/usr/X11R6/bin/xauth"
@@ -168,15 +173,6 @@
#define _PATH_LS "ls"
#endif
-/* path to login program */
-#ifndef LOGIN_PROGRAM
-# ifdef LOGIN_PROGRAM_FALLBACK
-# define LOGIN_PROGRAM LOGIN_PROGRAM_FALLBACK
-# else
-# define LOGIN_PROGRAM "/usr/bin/login"
-# endif
-#endif /* LOGIN_PROGRAM */
-
/* Askpass program define */
#ifndef ASKPASS_PROGRAM
#define ASKPASS_PROGRAM "/usr/lib/ssh/ssh-askpass"
diff --git a/platform-misc.c b/platform-misc.c
new file mode 100644
index 00000000..3f396704
--- /dev/null
+++ b/platform-misc.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2006 Darren Tucker. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include "openbsd-compat/openbsd-compat.h"
+
+/*
+ * return 1 if the specified uid is a uid that may own a system directory
+ * otherwise 0.
+ */
+int
+platform_sys_dir_uid(uid_t uid)
+{
+ if (uid == 0)
+ return 1;
+#ifdef PLATFORM_SYS_DIR_UID
+ if (uid == PLATFORM_SYS_DIR_UID)
+ return 1;
+#endif
+ return 0;
+}
diff --git a/platform-pledge.c b/platform-pledge.c
new file mode 100644
index 00000000..4a6ec15e
--- /dev/null
+++ b/platform-pledge.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015 Joyent, Inc
+ * Author: Alex Wilson <alex.wilson@joyent.com>
+ *
+ * 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 <stdarg.h>
+#include <unistd.h>
+
+#include "platform.h"
+
+#include "openbsd-compat/openbsd-compat.h"
+
+/*
+ * Drop any fine-grained privileges that are not needed for post-startup
+ * operation of ssh-agent
+ *
+ * Should be as close as possible to pledge("stdio cpath unix id proc exec", ...)
+ */
+void
+platform_pledge_agent(void)
+{
+#ifdef USE_SOLARIS_PRIVS
+ /*
+ * Note: Solaris priv dropping is closer to tame() than pledge(), but
+ * we will use what we have.
+ */
+ solaris_drop_privs_root_pinfo_net();
+#endif
+}
+
+/*
+ * Drop any fine-grained privileges that are not needed for post-startup
+ * operation of sftp-server
+ */
+void
+platform_pledge_sftp_server(void)
+{
+#ifdef USE_SOLARIS_PRIVS
+ solaris_drop_privs_pinfo_net_fork_exec();
+#endif
+}
+
+/*
+ * Drop any fine-grained privileges that are not needed for the post-startup
+ * operation of the SSH client mux
+ *
+ * Should be as close as possible to pledge("stdio proc tty", ...)
+ */
+void
+platform_pledge_mux(void)
+{
+#ifdef USE_SOLARIS_PRIVS
+ solaris_drop_privs_root_pinfo_net_exec();
+#endif
+}
diff --git a/platform-tracing.c b/platform-tracing.c
new file mode 100644
index 00000000..4c80a282
--- /dev/null
+++ b/platform-tracing.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016 Darren Tucker. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#if defined(HAVE_SYS_PRCTL_H)
+#include <sys/prctl.h> /* For prctl() and PR_SET_DUMPABLE */
+#endif
+#ifdef HAVE_SYS_PTRACE_H
+#include <sys/ptrace.h>
+#endif
+#ifdef HAVE_PRIV_H
+#include <priv.h> /* For setpflags() and __PROC_PROTECT */
+#endif
+#include <stdarg.h>
+
+#include "log.h"
+
+void
+platform_disable_tracing(int strict)
+{
+#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
+ /* Disable ptrace on Linux without sgid bit */
+ if (prctl(PR_SET_DUMPABLE, 0) != 0 && strict)
+ fatal("unable to make the process undumpable");
+#endif
+#if defined(HAVE_SETPFLAGS) && defined(__PROC_PROTECT)
+ /* On Solaris, we should make this process untraceable */
+ if (setpflags(__PROC_PROTECT, 1) != 0 && strict)
+ fatal("unable to make the process untraceable");
+#endif
+#ifdef PT_DENY_ATTACH
+ /* Mac OS X */
+ if (ptrace(PT_DENY_ATTACH, 0, 0, 0) == -1 && strict)
+ fatal("unable to set PT_DENY_ATTACH");
+#endif
+}
diff --git a/platform.c b/platform.c
index ee313da5..44ba71dc 100644
--- a/platform.c
+++ b/platform.c
@@ -1,5 +1,3 @@
-/* $Id: platform.c,v 1.22 2014/07/18 04:11:26 djm Exp $ */
-
/*
* Copyright (c) 2006 Darren Tucker. All rights reserved.
*
@@ -18,16 +16,14 @@
#include "includes.h"
-#include <sys/types.h>
-
#include <stdarg.h>
+#include <stdio.h>
#include <unistd.h>
#include "log.h"
-#include "buffer.h"
#include "misc.h"
#include "servconf.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-pam.h"
@@ -107,8 +103,12 @@ platform_setusercontext(struct passwd *pw)
#endif
#ifdef USE_SOLARIS_PROJECTS
- /* if solaris projects were detected, set the default now */
- if (getuid() == 0 || geteuid() == 0)
+ /*
+ * If solaris projects were detected, set the default now, unless
+ * we are using PAM in which case it is the responsibility of the
+ * PAM stack.
+ */
+ if (!options.use_pam && (getuid() == 0 || geteuid() == 0))
solaris_set_default_project(pw);
#endif
@@ -197,19 +197,3 @@ platform_krb5_get_principal_name(const char *pw_name)
return NULL;
#endif
}
-
-/*
- * return 1 if the specified uid is a uid that may own a system directory
- * otherwise 0.
- */
-int
-platform_sys_dir_uid(uid_t uid)
-{
- if (uid == 0)
- return 1;
-#ifdef PLATFORM_SYS_DIR_UID
- if (uid == PLATFORM_SYS_DIR_UID)
- return 1;
-#endif
- return 0;
-}
diff --git a/platform.h b/platform.h
index 1c7a45d8..ea4f9c58 100644
--- a/platform.h
+++ b/platform.h
@@ -1,5 +1,3 @@
-/* $Id: platform.h,v 1.9 2013/09/22 09:02:40 dtucker Exp $ */
-
/*
* Copyright (c) 2006 Darren Tucker. All rights reserved.
*
@@ -31,3 +29,9 @@ void platform_setusercontext_post_groups(struct passwd *);
char *platform_get_krb5_client(const char *);
char *platform_krb5_get_principal_name(const char *);
int platform_sys_dir_uid(uid_t);
+void platform_disable_tracing(int);
+
+/* in platform-pledge.c */
+void platform_pledge_agent(void);
+void platform_pledge_sftp_server(void);
+void platform_pledge_mux(void);
diff --git a/config.h b/prebuilt-intermediates/config.h
index f3932ec7..3e8f585f 100644
--- a/config.h
+++ b/prebuilt-intermediates/config.h
@@ -194,7 +194,7 @@
#define HAVE_ATTRIBUTE__NONNULL__ 1
/* OpenBSD's gcc has sentinel */
-/* #undef HAVE_ATTRIBUTE__SENTINEL__ */
+#define HAVE_ATTRIBUTE__SENTINEL__ 1
/* Define to 1 if you have the `aug_get_machine' function. */
/* #undef HAVE_AUG_GET_MACHINE */
@@ -223,6 +223,9 @@
/* Define to 1 if you have the <bstring.h> header file. */
/* #undef HAVE_BSTRING_H */
+/* Define to 1 if you have the `bzero' function. */
+#define HAVE_BZERO 1
+
/* Define to 1 if you have the `clock' function. */
#define HAVE_CLOCK 1
@@ -263,6 +266,10 @@
don't. */
/* #undef HAVE_DECL_AUTHENTICATE */
+/* Define to 1 if you have the declaration of `getpeerid', and to 0 if you
+ don't. */
+#define HAVE_DECL_GETPEEREID 0
+
/* Define to 1 if you have the declaration of `GLOB_NOMATCH', and to 0 if you
don't. */
#define HAVE_DECL_GLOB_NOMATCH 1
@@ -403,6 +410,9 @@
/* Define to 1 if you have the <floatingpoint.h> header file. */
/* #undef HAVE_FLOATINGPOINT_H */
+/* Define to 1 if you have the `flock' function. */
+#define HAVE_FLOCK 1
+
/* Define to 1 if you have the `fmt_scaled' function. */
/* #undef HAVE_FMT_SCALED */
@@ -419,7 +429,7 @@
/* #define HAVE_FSTATVFS 1 */
/* Define to 1 if you have the `futimes' function. */
-/* #define HAVE_FUTIMES 1 */
+#define HAVE_FUTIMES 1
/* Define to 1 if you have the `gai_strerror' function. */
#define HAVE_GAI_STRERROR 1
@@ -445,6 +455,9 @@
/* Define to 1 if you have the `getlastlogxbyname' function. */
/* #undef HAVE_GETLASTLOGXBYNAME */
+/* Define to 1 if you have the `getline' function. */
+#define HAVE_GETLINE 1
+
/* Define to 1 if you have the `getluid' function. */
/* #undef HAVE_GETLUID */
@@ -685,6 +698,9 @@
/* Define if you want to allow MD5 passwords */
/* #undef HAVE_MD5_PASSWORDS */
+/* Define to 1 if you have the `memmem' function. */
+#define HAVE_MEMMEM 1
+
/* Define to 1 if you have the `memmove' function. */
#define HAVE_MEMMOVE 1
@@ -785,6 +801,9 @@
/* Define to 1 if you have the `pututxline' function. */
#define HAVE_PUTUTXLINE 1
+/* Define to 1 if you have the `raise' function. */
+#define HAVE_RAISE 1
+
/* Define to 1 if you have the `readpassphrase' function. */
/* #undef HAVE_READPASSPHRASE */
@@ -980,6 +999,9 @@
/* Define to 1 if you have the `strmode' function. */
/* #undef HAVE_STRMODE */
+/* Define to 1 if you have the `strndup' function. */
+#define HAVE_STRNDUP 1
+
/* Define to 1 if you have the `strnlen' function. */
#define HAVE_STRNLEN 1
@@ -992,6 +1014,9 @@
/* Define to 1 if you have the `strsep' function. */
#define HAVE_STRSEP 1
+/* Define to 1 if you have the `strsignal' function. */
+#define HAVE_STRSIGNAL 1
+
/* Define to 1 if you have the `strtoll' function. */
#define HAVE_STRTOLL 1
@@ -1601,3 +1626,36 @@
#define _PATH_PRIVSEP_CHROOT_DIR SSHDIR "/empty"
#define _PATH_SSH_PROGRAM "/system/bin/sftp"
+
+/* Utilize some of the LibreSSL compatibility layer */
+#define HAVE_DH_GET0_KEY 1
+#define HAVE_DH_GET0_PQG 1
+#define HAVE_DH_SET0_KEY 1
+#define HAVE_DH_SET0_PQG 1
+#undef HAVE_DH_SET_LENGTH
+#define HAVE_DSA_GET0_KEY 1
+#define HAVE_DSA_GET0_PQG 1
+#define HAVE_DSA_SET0_KEY 1
+#define HAVE_DSA_SET0_PQG 1
+#undef HAVE_DSA_SIG_GET0
+#undef HAVE_DSA_SIG_SET0
+#define HAVE_ECDSA_SIG_GET0 1
+#define HAVE_ECDSA_SIG_SET0 1
+#undef HAVE_EVP_CIPHER_CTX_GET_IV
+#undef HAVE_EVP_CIPHER_CTX_SET_IV
+#define HAVE_EVP_MD_CTX_FREE 1
+#define HAVE_EVP_MD_CTX_NEW 1
+#define HAVE_EVP_PKEY_GET0_RSA 1
+#define HAVE_RSA_GET0_CRT_PARAMS 1
+#define HAVE_RSA_GET0_FACTORS 1
+#define HAVE_RSA_GET0_KEY 1
+#define HAVE_RSA_METH_DUP 1
+#define HAVE_RSA_METH_FREE 1
+#define HAVE_RSA_METH_GET_FINISH 1
+#define HAVE_RSA_METH_SET1_NAME 1
+#define HAVE_RSA_METH_SET_FINISH 1
+#define HAVE_RSA_METH_SET_PRIV_DEC 1
+#define HAVE_RSA_METH_SET_PRIV_ENC 1
+#define HAVE_RSA_SET0_CRT_PARAMS 1
+#define HAVE_RSA_SET0_FACTORS 1
+#define HAVE_RSA_SET0_KEY 1
diff --git a/progressmeter.c b/progressmeter.c
index 319b7470..8baf798f 100644
--- a/progressmeter.c
+++ b/progressmeter.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: progressmeter.c,v 1.41 2015/01/14 13:54:13 djm Exp $ */
+/* $OpenBSD: progressmeter.c,v 1.50 2020/01/23 07:10:22 dtucker Exp $ */
/*
* Copyright (c) 2003 Nils Nordman. All rights reserved.
*
@@ -31,6 +31,7 @@
#include <errno.h>
#include <signal.h>
+#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
@@ -39,6 +40,7 @@
#include "progressmeter.h"
#include "atomicio.h"
#include "misc.h"
+#include "utf8.h"
#define DEFAULT_WINSIZE 80
#define MAX_WINSIZE 512
@@ -57,14 +59,11 @@ static void format_rate(char *, int, off_t);
static void sig_winch(int);
static void setscreensize(void);
-/* updates the progressmeter to reflect the current state of the transfer */
-void refresh_progress_meter(void);
-
/* signal handler for updating the progress meter */
-static void update_progress_meter(int);
+static void sig_alarm(int);
-static time_t start; /* start progress */
-static time_t last_update; /* last progress update */
+static double start; /* start progress */
+static double last_update; /* last progress update */
static const char *file; /* name of the file being transferred */
static off_t start_pos; /* initial position of transfer */
static off_t end_pos; /* ending position of transfer */
@@ -74,6 +73,7 @@ static long stalled; /* how long we have been stalled */
static int bytes_per_second; /* current speed in bytes per second */
static int win_size; /* terminal window size */
static volatile sig_atomic_t win_resized; /* for window resizing */
+static volatile sig_atomic_t alarm_fired;
/* units for format_size */
static const char unit[] = " KMGT";
@@ -117,22 +117,29 @@ format_size(char *buf, int size, off_t bytes)
}
void
-refresh_progress_meter(void)
+refresh_progress_meter(int force_update)
{
char buf[MAX_WINSIZE + 1];
- time_t now;
off_t transferred;
- double elapsed;
+ double elapsed, now;
int percent;
off_t bytes_left;
int cur_speed;
int hours, minutes, seconds;
- int i, len;
int file_len;
+ if ((!force_update && !alarm_fired && !win_resized) || !can_output())
+ return;
+ alarm_fired = 0;
+
+ if (win_resized) {
+ setscreensize();
+ win_resized = 0;
+ }
+
transferred = *counter - (cur_pos ? cur_pos : start_pos);
cur_pos = *counter;
- now = monotime();
+ now = monotime_double();
bytes_left = end_pos - cur_pos;
if (bytes_left > 0)
@@ -159,23 +166,18 @@ refresh_progress_meter(void)
/* filename */
buf[0] = '\0';
- file_len = win_size - 35;
+ file_len = win_size - 36;
if (file_len > 0) {
- len = snprintf(buf, file_len + 1, "\r%s", file);
- if (len < 0)
- len = 0;
- if (len >= file_len + 1)
- len = file_len;
- for (i = len; i < file_len; i++)
- buf[i] = ' ';
- buf[file_len] = '\0';
+ buf[0] = '\r';
+ snmprintf(buf+1, sizeof(buf)-1, &file_len, "%-*s",
+ file_len, file);
}
/* percent of transfer done */
- if (end_pos != 0)
- percent = ((float)cur_pos / end_pos) * 100;
- else
+ if (end_pos == 0 || cur_pos == end_pos)
percent = 100;
+ else
+ percent = ((float)cur_pos / end_pos) * 100;
snprintf(buf + strlen(buf), win_size - strlen(buf),
" %3d%% ", percent);
@@ -229,28 +231,16 @@ refresh_progress_meter(void)
/*ARGSUSED*/
static void
-update_progress_meter(int ignore)
+sig_alarm(int ignore)
{
- int save_errno;
-
- save_errno = errno;
-
- if (win_resized) {
- setscreensize();
- win_resized = 0;
- }
- if (can_output())
- refresh_progress_meter();
-
- signal(SIGALRM, update_progress_meter);
+ alarm_fired = 1;
alarm(UPDATE_INTERVAL);
- errno = save_errno;
}
void
start_progress_meter(const char *f, off_t filesize, off_t *ctr)
{
- start = last_update = monotime();
+ start = last_update = monotime_double();
file = f;
start_pos = *ctr;
end_pos = filesize;
@@ -260,11 +250,10 @@ start_progress_meter(const char *f, off_t filesize, off_t *ctr)
bytes_per_second = 0;
setscreensize();
- if (can_output())
- refresh_progress_meter();
+ refresh_progress_meter(1);
- signal(SIGALRM, update_progress_meter);
- signal(SIGWINCH, sig_winch);
+ ssh_signal(SIGALRM, sig_alarm);
+ ssh_signal(SIGWINCH, sig_winch);
alarm(UPDATE_INTERVAL);
}
@@ -278,7 +267,7 @@ stop_progress_meter(void)
/* Ensure we complete the progress */
if (cur_pos != end_pos)
- refresh_progress_meter();
+ refresh_progress_meter(1);
atomicio(vwrite, STDOUT_FILENO, "\n", 1);
}
diff --git a/progressmeter.h b/progressmeter.h
index bf179dca..1703ea75 100644
--- a/progressmeter.h
+++ b/progressmeter.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: progressmeter.h,v 1.3 2015/01/14 13:54:13 djm Exp $ */
+/* $OpenBSD: progressmeter.h,v 1.5 2019/01/24 16:52:17 dtucker Exp $ */
/*
* Copyright (c) 2002 Nils Nordman. All rights reserved.
*
@@ -24,4 +24,5 @@
*/
void start_progress_meter(const char *, off_t, off_t *);
+void refresh_progress_meter(int);
void stop_progress_meter(void);
diff --git a/readconf.c b/readconf.c
index ebbf2195..2afcbaec 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.232 2015/02/16 22:13:32 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.329 2020/04/24 03:33:21 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,10 +35,15 @@
#endif
#include <pwd.h>
#include <signal.h>
-#include <stdarg.h>
#include <stdio.h>
#include <string.h>
+#include <stdarg.h>
#include <unistd.h>
+#ifdef USE_SYSTEM_GLOB
+# include <glob.h>
+#else
+# include "openbsd-compat/glob.h"
+#endif
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
@@ -48,6 +53,7 @@
#include "xmalloc.h"
#include "ssh.h"
+#include "ssherr.h"
#include "compat.h"
#include "cipher.h"
#include "pathnames.h"
@@ -80,7 +86,7 @@
User foo
Host fake.com
- HostName another.host.name.real.org
+ Hostname another.host.name.real.org
User blaah
Port 34289
ForwardX11 no
@@ -88,7 +94,7 @@
Host books.com
RemoteForward 9999 shadows.cs.hut.fi:9999
- Cipher 3des
+ Ciphers 3des-cbc
Host fascist.blob.com
Port 23123
@@ -103,7 +109,7 @@
PublicKeyAuthentication no
Host *.su
- Cipher none
+ Ciphers aes128-ctr
PasswordAuthentication no
Host vpn.fake.com
@@ -115,8 +121,6 @@
ForwardAgent no
ForwardX11 no
PasswordAuthentication yes
- RSAAuthentication yes
- RhostsRSAAuthentication yes
StrictHostKeyChecking yes
TcpKeepAlive no
IdentityFile ~/.ssh/identity
@@ -125,39 +129,51 @@
*/
+static int read_config_file_depth(const char *filename, struct passwd *pw,
+ const char *host, const char *original_host, Options *options,
+ int flags, int *activep, int *want_final_pass, int depth);
+static int process_config_line_depth(Options *options, struct passwd *pw,
+ const char *host, const char *original_host, char *line,
+ const char *filename, int linenum, int *activep, int flags,
+ int *want_final_pass, int depth);
+
/* Keyword tokens. */
typedef enum {
oBadOption,
- oHost, oMatch,
+ oHost, oMatch, oInclude,
oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
oGatewayPorts, oExitOnForwardFailure,
- oPasswordAuthentication, oRSAAuthentication,
+ oPasswordAuthentication,
oChallengeResponseAuthentication, oXAuthLocation,
- oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
- oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
+ oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
+ oCertificateFile, oAddKeysToAgent, oIdentityAgent,
+ oUser, oEscapeChar, oProxyCommand,
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
- oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
- oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
+ oTCPKeepAlive, oNumberOfPasswordPrompts,
+ oLogFacility, oLogLevel, oCiphers, oMacs,
oPubkeyAuthentication,
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
- oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
+ oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
- oSendEnv, oControlPath, oControlMaster, oControlPersist,
+ oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
oHashKnownHosts,
- oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
- oVisualHostKey, oUseRoaming,
+ oTunnel, oTunnelDevice,
+ oLocalCommand, oPermitLocalCommand, oRemoteCommand,
+ oVisualHostKey,
oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
- oIgnoredUnknownOption, oDeprecated, oUnsupported
+ oPubkeyAcceptedKeyTypes, oCASignatureAlgorithms, oProxyJump,
+ oSecurityKeyProvider,
+ oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes;
/* Textual representations of the tokens. */
@@ -166,6 +182,41 @@ static struct {
const char *name;
OpCodes opcode;
} keywords[] = {
+ /* Deprecated options */
+ { "protocol", oIgnore }, /* NB. silently ignored */
+ { "cipher", oDeprecated },
+ { "fallbacktorsh", oDeprecated },
+ { "globalknownhostsfile2", oDeprecated },
+ { "rhostsauthentication", oDeprecated },
+ { "userknownhostsfile2", oDeprecated },
+ { "useroaming", oDeprecated },
+ { "usersh", oDeprecated },
+ { "useprivilegedport", oDeprecated },
+
+ /* Unsupported options */
+ { "afstokenpassing", oUnsupported },
+ { "kerberosauthentication", oUnsupported },
+ { "kerberostgtpassing", oUnsupported },
+ { "rsaauthentication", oUnsupported },
+ { "rhostsrsaauthentication", oUnsupported },
+ { "compressionlevel", oUnsupported },
+
+ /* Sometimes-unsupported options */
+#if defined(GSSAPI)
+ { "gssapiauthentication", oGssAuthentication },
+ { "gssapidelegatecredentials", oGssDelegateCreds },
+# else
+ { "gssapiauthentication", oUnsupported },
+ { "gssapidelegatecredentials", oUnsupported },
+#endif
+#ifdef ENABLE_PKCS11
+ { "pkcs11provider", oPKCS11Provider },
+ { "smartcarddevice", oPKCS11Provider },
+# else
+ { "smartcarddevice", oUnsupported },
+ { "pkcs11provider", oUnsupported },
+#endif
+
{ "forwardagent", oForwardAgent },
{ "forwardx11", oForwardX11 },
{ "forwardx11trusted", oForwardX11Trusted },
@@ -173,42 +224,27 @@ static struct {
{ "exitonforwardfailure", oExitOnForwardFailure },
{ "xauthlocation", oXAuthLocation },
{ "gatewayports", oGatewayPorts },
- { "useprivilegedport", oUsePrivilegedPort },
- { "rhostsauthentication", oDeprecated },
{ "passwordauthentication", oPasswordAuthentication },
{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
{ "kbdinteractivedevices", oKbdInteractiveDevices },
- { "rsaauthentication", oRSAAuthentication },
{ "pubkeyauthentication", oPubkeyAuthentication },
{ "dsaauthentication", oPubkeyAuthentication }, /* alias */
- { "rhostsrsaauthentication", oRhostsRSAAuthentication },
{ "hostbasedauthentication", oHostbasedAuthentication },
{ "challengeresponseauthentication", oChallengeResponseAuthentication },
- { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
+ { "skeyauthentication", oUnsupported },
{ "tisauthentication", oChallengeResponseAuthentication }, /* alias */
- { "kerberosauthentication", oUnsupported },
- { "kerberostgtpassing", oUnsupported },
- { "afstokenpassing", oUnsupported },
-#if defined(GSSAPI)
- { "gssapiauthentication", oGssAuthentication },
- { "gssapidelegatecredentials", oGssDelegateCreds },
-#else
- { "gssapiauthentication", oUnsupported },
- { "gssapidelegatecredentials", oUnsupported },
-#endif
- { "fallbacktorsh", oDeprecated },
- { "usersh", oDeprecated },
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile }, /* obsolete */
{ "identitiesonly", oIdentitiesOnly },
- { "hostname", oHostName },
+ { "certificatefile", oCertificateFile },
+ { "addkeystoagent", oAddKeysToAgent },
+ { "identityagent", oIdentityAgent },
+ { "hostname", oHostname },
{ "hostkeyalias", oHostKeyAlias },
{ "proxycommand", oProxyCommand },
{ "port", oPort },
- { "cipher", oCipher },
{ "ciphers", oCiphers },
{ "macs", oMacs },
- { "protocol", oProtocol },
{ "remoteforward", oRemoteForward },
{ "localforward", oLocalForward },
{ "user", oUser },
@@ -216,30 +252,23 @@ static struct {
{ "match", oMatch },
{ "escapechar", oEscapeChar },
{ "globalknownhostsfile", oGlobalKnownHostsFile },
- { "globalknownhostsfile2", oDeprecated },
{ "userknownhostsfile", oUserKnownHostsFile },
- { "userknownhostsfile2", oDeprecated },
{ "connectionattempts", oConnectionAttempts },
{ "batchmode", oBatchMode },
{ "checkhostip", oCheckHostIP },
{ "stricthostkeychecking", oStrictHostKeyChecking },
{ "compression", oCompression },
- { "compressionlevel", oCompressionLevel },
{ "tcpkeepalive", oTCPKeepAlive },
{ "keepalive", oTCPKeepAlive }, /* obsolete */
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
+ { "syslogfacility", oLogFacility },
{ "loglevel", oLogLevel },
{ "dynamicforward", oDynamicForward },
{ "preferredauthentications", oPreferredAuthentications },
{ "hostkeyalgorithms", oHostKeyAlgorithms },
+ { "casignaturealgorithms", oCASignatureAlgorithms },
{ "bindaddress", oBindAddress },
-#ifdef ENABLE_PKCS11
- { "smartcarddevice", oPKCS11Provider },
- { "pkcs11provider", oPKCS11Provider },
-#else
- { "smartcarddevice", oUnsupported },
- { "pkcs11provider", oUnsupported },
-#endif
+ { "bindinterface", oBindInterface },
{ "clearallforwardings", oClearAllForwardings },
{ "enablesshkeysign", oEnableSSHKeysign },
{ "verifyhostkeydns", oVerifyHostKeyDNS },
@@ -250,16 +279,18 @@ static struct {
{ "serveraliveinterval", oServerAliveInterval },
{ "serveralivecountmax", oServerAliveCountMax },
{ "sendenv", oSendEnv },
+ { "setenv", oSetEnv },
{ "controlpath", oControlPath },
{ "controlmaster", oControlMaster },
{ "controlpersist", oControlPersist },
{ "hashknownhosts", oHashKnownHosts },
+ { "include", oInclude },
{ "tunnel", oTunnel },
{ "tunneldevice", oTunnelDevice },
{ "localcommand", oLocalCommand },
{ "permitlocalcommand", oPermitLocalCommand },
+ { "remotecommand", oRemoteCommand },
{ "visualhostkey", oVisualHostKey },
- { "useroaming", oUseRoaming },
{ "kexalgorithms", oKexAlgorithms },
{ "ipqos", oIPQoS },
{ "requesttty", oRequestTTY },
@@ -275,11 +306,42 @@ static struct {
{ "fingerprinthash", oFingerprintHash },
{ "updatehostkeys", oUpdateHostkeys },
{ "hostbasedkeytypes", oHostbasedKeyTypes },
+ { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes },
{ "ignoreunknown", oIgnoreUnknown },
+ { "proxyjump", oProxyJump },
+ { "securitykeyprovider", oSecurityKeyProvider },
{ NULL, oBadOption }
};
+static char *kex_default_pk_alg_filtered;
+
+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;
+}
+
+char *
+ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
+ const char *user)
+{
+ struct ssh_digest_ctx *md;
+ u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
+
+ if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
+ ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
+ ssh_digest_update(md, host, strlen(host)) < 0 ||
+ ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
+ ssh_digest_update(md, user, strlen(user)) < 0 ||
+ ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
+ fatal("%s: mux digest failed", __func__);
+ ssh_digest_free(md);
+ return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
+}
+
/*
* Adds a local TCP/IP port forward to options. Never returns if there is an
* error.
@@ -289,13 +351,14 @@ void
add_local_forward(Options *options, const struct Forward *newfwd)
{
struct Forward *fwd;
-#ifndef NO_IPPORT_RESERVED_CONCEPT
- extern uid_t original_real_uid;
- if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 &&
- newfwd->listen_path == NULL)
- fatal("Privileged ports can only be forwarded by root.");
-#endif
- options->local_forwards = xrealloc(options->local_forwards,
+ int i;
+
+ /* Don't add duplicates */
+ for (i = 0; i < options->num_local_forwards; i++) {
+ if (forward_equals(newfwd, options->local_forwards + i))
+ return;
+ }
+ options->local_forwards = xreallocarray(options->local_forwards,
options->num_local_forwards + 1,
sizeof(*options->local_forwards));
fwd = &options->local_forwards[options->num_local_forwards++];
@@ -317,8 +380,14 @@ void
add_remote_forward(Options *options, const struct Forward *newfwd)
{
struct Forward *fwd;
+ int i;
- options->remote_forwards = xrealloc(options->remote_forwards,
+ /* Don't add duplicates */
+ for (i = 0; i < options->num_remote_forwards; i++) {
+ if (forward_equals(newfwd, options->remote_forwards + i))
+ return;
+ }
+ options->remote_forwards = xreallocarray(options->remote_forwards,
options->num_remote_forwards + 1,
sizeof(*options->remote_forwards));
fwd = &options->remote_forwards[options->num_remote_forwards++];
@@ -364,6 +433,30 @@ clear_forwardings(Options *options)
}
void
+add_certificate_file(Options *options, const char *path, int userprovided)
+{
+ int i;
+
+ if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
+ fatal("Too many certificate files specified (max %d)",
+ SSH_MAX_CERTIFICATE_FILES);
+
+ /* Avoid registering duplicates */
+ for (i = 0; i < options->num_certificate_files; i++) {
+ if (options->certificate_file_userprovided[i] == userprovided &&
+ strcmp(options->certificate_files[i], path) == 0) {
+ debug2("%s: ignoring duplicate key %s", __func__, path);
+ return;
+ }
+ }
+
+ options->certificate_file_userprovided[options->num_certificate_files] =
+ userprovided;
+ options->certificate_files[options->num_certificate_files++] =
+ xstrdup(path);
+}
+
+void
add_identity_file(Options *options, const char *dir, const char *filename,
int userprovided)
{
@@ -376,8 +469,8 @@ add_identity_file(Options *options, const char *dir, const char *filename,
if (dir == NULL) /* no dir, filename is absolute */
path = xstrdup(filename);
- else
- (void)xasprintf(&path, "%.100s%.100s", dir, filename);
+ else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
+ fatal("Identity file path %s too long", path);
/* Avoid registering duplicates */
for (i = 0; i < options->num_identity_files; i++) {
@@ -414,19 +507,17 @@ default_ssh_port(void)
static int
execute_in_shell(const char *cmd)
{
- char *shell, *command_string;
+ char *shell;
pid_t pid;
int devnull, status;
- extern uid_t original_real_uid;
if ((shell = getenv("SHELL")) == NULL)
shell = _PATH_BSHELL;
- /*
- * Use "exec" to avoid "sh -c" processes on some platforms
- * (e.g. Solaris)
- */
- xasprintf(&command_string, "exec %s", cmd);
+ if (access(shell, X_OK) == -1) {
+ fatal("Shell \"%s\" is not executable: %s",
+ shell, strerror(errno));
+ }
/* Need this to redirect subprocess stdin/out */
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
@@ -438,9 +529,6 @@ execute_in_shell(const char *cmd)
if ((pid = fork()) == 0) {
char *argv[4];
- /* Child. Permanently give up superuser privileges. */
- permanently_drop_suid(original_real_uid);
-
/* Redirect child stdin and stdout. Leave stderr */
if (dup2(devnull, STDIN_FILENO) == -1)
fatal("dup2: %s", strerror(errno));
@@ -452,22 +540,21 @@ execute_in_shell(const char *cmd)
argv[0] = shell;
argv[1] = "-c";
- argv[2] = command_string;
+ argv[2] = xstrdup(cmd);
argv[3] = NULL;
execv(argv[0], argv);
error("Unable to execute '%.100s': %s", cmd, strerror(errno));
/* Die with signal to make this error apparent to parent. */
- signal(SIGTERM, SIG_DFL);
+ ssh_signal(SIGTERM, SIG_DFL);
kill(getpid(), SIGTERM);
_exit(1);
}
/* Parent. */
- if (pid < 0)
+ if (pid == -1)
fatal("%s: fork: %.100s", __func__, strerror(errno));
close(devnull);
- free(command_string);
while (waitpid(pid, &status, 0) == -1) {
if (errno != EINTR && errno != EAGAIN)
@@ -486,14 +573,14 @@ execute_in_shell(const char *cmd)
*/
static int
match_cfg_line(Options *options, char **condition, struct passwd *pw,
- const char *host_arg, const char *original_host, int post_canon,
- const char *filename, int linenum)
+ const char *host_arg, const char *original_host, int final_pass,
+ int *want_final_pass, const char *filename, int linenum)
{
char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
const char *ruser;
int r, port, this_result, result = 1, attributes = 0, negate;
- size_t len;
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
+ char uidstr[32];
/*
* Configuration is likely to be incomplete at this point so we
@@ -501,12 +588,15 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
*/
port = options->port <= 0 ? default_ssh_port() : options->port;
ruser = options->user == NULL ? pw->pw_name : options->user;
- if (options->hostname != NULL) {
+ if (final_pass) {
+ host = xstrdup(options->hostname);
+ } else if (options->hostname != NULL) {
/* NB. Please keep in sync with ssh.c:main() */
host = percent_expand(options->hostname,
"h", host_arg, (char *)NULL);
- } else
+ } else {
host = xstrdup(host_arg);
+ }
debug2("checking match for '%s' host %s originally %s",
cp, host, original_host);
@@ -530,8 +620,16 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
goto out;
}
attributes++;
- if (strcasecmp(attrib, "canonical") == 0) {
- r = !!post_canon; /* force bitmask member to boolean */
+ if (strcasecmp(attrib, "canonical") == 0 ||
+ strcasecmp(attrib, "final") == 0) {
+ /*
+ * If the config requests "Match final" then remember
+ * this so we can perform a second pass later.
+ */
+ if (strcasecmp(attrib, "final") == 0 &&
+ want_final_pass != NULL)
+ *want_final_pass = 1;
+ r = !!final_pass; /* force bitmask member to boolean */
if (r == (negate ? 1 : 0))
this_result = result = 0;
debug3("%.200s line %d: %smatched '%s'",
@@ -545,35 +643,41 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
result = -1;
goto out;
}
- len = strlen(arg);
if (strcasecmp(attrib, "host") == 0) {
criteria = xstrdup(host);
- r = match_hostname(host, arg, len) == 1;
+ r = match_hostname(host, arg) == 1;
if (r == (negate ? 1 : 0))
this_result = result = 0;
} else if (strcasecmp(attrib, "originalhost") == 0) {
criteria = xstrdup(original_host);
- r = match_hostname(original_host, arg, len) == 1;
+ r = match_hostname(original_host, arg) == 1;
if (r == (negate ? 1 : 0))
this_result = result = 0;
} else if (strcasecmp(attrib, "user") == 0) {
criteria = xstrdup(ruser);
- r = match_pattern_list(ruser, arg, len, 0) == 1;
+ r = match_pattern_list(ruser, arg, 0) == 1;
if (r == (negate ? 1 : 0))
this_result = result = 0;
} else if (strcasecmp(attrib, "localuser") == 0) {
criteria = xstrdup(pw->pw_name);
- r = match_pattern_list(pw->pw_name, arg, len, 0) == 1;
+ r = match_pattern_list(pw->pw_name, arg, 0) == 1;
if (r == (negate ? 1 : 0))
this_result = result = 0;
} else if (strcasecmp(attrib, "exec") == 0) {
+ char *conn_hash_hex;
+
if (gethostname(thishost, sizeof(thishost)) == -1)
fatal("gethostname: %s", strerror(errno));
strlcpy(shorthost, thishost, sizeof(shorthost));
shorthost[strcspn(thishost, ".")] = '\0';
snprintf(portstr, sizeof(portstr), "%d", port);
+ snprintf(uidstr, sizeof(uidstr), "%llu",
+ (unsigned long long)pw->pw_uid);
+ conn_hash_hex = ssh_connection_hash(thishost, host,
+ portstr, ruser);
cmd = percent_expand(arg,
+ "C", conn_hash_hex,
"L", shorthost,
"d", pw->pw_dir,
"h", host,
@@ -582,7 +686,9 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
"p", portstr,
"r", ruser,
"u", pw->pw_name,
+ "i", uidstr,
(char *)NULL);
+ free(conn_hash_hex);
if (result != 1) {
/* skip execution if prior predicate failed */
debug3("%.200s line %d: skipped exec "
@@ -625,32 +731,33 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
return result;
}
-/* Check and prepare a domain name: removes trailing '.' and lowercases */
+/* Remove environment variable by pattern */
static void
-valid_domain(char *name, const char *filename, int linenum)
+rm_env(Options *options, const char *arg, const char *filename, int linenum)
{
- size_t i, l = strlen(name);
- u_char c, last = '\0';
-
- if (l == 0)
- fatal("%s line %d: empty hostname suffix", filename, linenum);
- if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0]))
- fatal("%s line %d: hostname suffix \"%.100s\" "
- "starts with invalid character", filename, linenum, name);
- for (i = 0; i < l; i++) {
- c = tolower((u_char)name[i]);
- name[i] = (char)c;
- if (last == '.' && c == '.')
- fatal("%s line %d: hostname suffix \"%.100s\" contains "
- "consecutive separators", filename, linenum, name);
- if (c != '.' && c != '-' && !isalnum(c) &&
- c != '_') /* technically invalid, but common */
- fatal("%s line %d: hostname suffix \"%.100s\" contains "
- "invalid characters", filename, linenum, name);
- last = c;
+ int i, j;
+ char *cp;
+
+ /* Remove an environment variable */
+ for (i = 0; i < options->num_send_env; ) {
+ cp = xstrdup(options->send_env[i]);
+ if (!match_pattern(cp, arg + 1)) {
+ free(cp);
+ i++;
+ continue;
+ }
+ debug3("%s line %d: removing environment %s",
+ filename, linenum, cp);
+ free(cp);
+ free(options->send_env[i]);
+ options->send_env[i] = NULL;
+ for (j = i; j < options->num_send_env - 1; j++) {
+ options->send_env[j] = options->send_env[j + 1];
+ options->send_env[j + 1] = NULL;
+ }
+ options->num_send_env--;
+ /* NB. don't increment i */
}
- if (name[l - 1] == '.')
- name[l - 1] = '\0';
}
/*
@@ -665,8 +772,8 @@ parse_token(const char *cp, const char *filename, int linenum,
for (i = 0; keywords[i].name; i++)
if (strcmp(cp, keywords[i].name) == 0)
return keywords[i].opcode;
- if (ignored_unknown != NULL && match_pattern_list(cp, ignored_unknown,
- strlen(ignored_unknown), 1) == 1)
+ if (ignored_unknown != NULL &&
+ match_pattern_list(cp, ignored_unknown, 1) == 1)
return oIgnoredUnknownOption;
error("%s: line %d: Bad configuration option: %s",
filename, linenum, cp);
@@ -693,6 +800,25 @@ static const struct multistate multistate_yesnoask[] = {
{ "ask", 2 },
{ NULL, -1 }
};
+static const struct multistate multistate_strict_hostkey[] = {
+ { "true", SSH_STRICT_HOSTKEY_YES },
+ { "false", SSH_STRICT_HOSTKEY_OFF },
+ { "yes", SSH_STRICT_HOSTKEY_YES },
+ { "no", SSH_STRICT_HOSTKEY_OFF },
+ { "ask", SSH_STRICT_HOSTKEY_ASK },
+ { "off", SSH_STRICT_HOSTKEY_OFF },
+ { "accept-new", SSH_STRICT_HOSTKEY_NEW },
+ { NULL, -1 }
+};
+static const struct multistate multistate_yesnoaskconfirm[] = {
+ { "true", 1 },
+ { "false", 0 },
+ { "yes", 1 },
+ { "no", 0 },
+ { "ask", 2 },
+ { "confirm", 3 },
+ { NULL, -1 }
+};
static const struct multistate multistate_addressfamily[] = {
{ "inet", AF_INET },
{ "inet6", AF_INET6 },
@@ -735,36 +861,58 @@ static const struct multistate multistate_canonicalizehostname[] = {
{ "always", SSH_CANONICALISE_ALWAYS },
{ NULL, -1 }
};
+static const struct multistate multistate_compression[] = {
+#ifdef WITH_ZLIB
+ { "yes", COMP_ZLIB },
+#endif
+ { "no", COMP_NONE },
+ { NULL, -1 }
+};
/*
* Processes a single option line as used in the configuration files. This
* only sets those values that have not already been set.
*/
-#define WHITESPACE " \t\r\n"
int
process_config_line(Options *options, struct passwd *pw, const char *host,
const char *original_host, char *line, const char *filename,
int linenum, int *activep, int flags)
{
+ return process_config_line_depth(options, pw, host, original_host,
+ line, filename, linenum, activep, flags, NULL, 0);
+}
+
+#define WHITESPACE " \t\r\n"
+static int
+process_config_line_depth(Options *options, struct passwd *pw, const char *host,
+ const char *original_host, char *line, const char *filename,
+ int linenum, int *activep, int flags, int *want_final_pass, int depth)
+{
char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
char **cpptr, fwdarg[256];
u_int i, *uintptr, max_entries = 0;
- int negated, opcode, *intptr, value, value2, cmdline = 0;
+ int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
+ int remotefwd, dynamicfwd;
LogLevel *log_level_ptr;
+ SyslogFacility *log_facility_ptr;
long long val64;
size_t len;
struct Forward fwd;
const struct multistate *multistate_ptr;
struct allowed_cname *cname;
+ glob_t gl;
+ const char *errstr;
if (activep == NULL) { /* We are processing a command line directive */
cmdline = 1;
activep = &cmdline;
}
- /* Strip trailing whitespace */
- for (len = strlen(line) - 1; len > 0; len--) {
- if (strchr(WHITESPACE, line[len]) == NULL)
+ /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
+ if ((len = strlen(line)) == 0)
+ return 0;
+ for (len--; len > 0; len--) {
+ if (strchr(WHITESPACE "\f", line[len]) == NULL)
break;
line[len] = '\0';
}
@@ -788,7 +936,8 @@ process_config_line(Options *options, struct passwd *pw, const char *host,
case oBadOption:
/* don't panic, but count bad options */
return -1;
- /* NOTREACHED */
+ case oIgnore:
+ return 0;
case oIgnoredUnknownOption:
debug("%s line %d: Ignored unknown option \"%s\"",
filename, linenum, keyword);
@@ -811,6 +960,34 @@ parse_time:
case oForwardAgent:
intptr = &options->forward_agent;
+
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing argument.",
+ filename, linenum);
+
+ value = -1;
+ multistate_ptr = multistate_flag;
+ for (i = 0; multistate_ptr[i].key != NULL; i++) {
+ if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
+ value = multistate_ptr[i].value;
+ break;
+ }
+ }
+ if (value != -1) {
+ if (*activep && *intptr == -1)
+ *intptr = value;
+ break;
+ }
+ /* ForwardAgent wasn't 'yes' or 'no', assume a path */
+ if (*activep && *intptr == -1)
+ *intptr = 1;
+
+ charptr = &options->forward_agent_sock_path;
+ goto parse_agent_path;
+
+ case oForwardX11:
+ intptr = &options->forward_x11;
parse_flag:
multistate_ptr = multistate_flag;
parse_multistate:
@@ -832,10 +1009,6 @@ parse_time:
*intptr = value;
break;
- case oForwardX11:
- intptr = &options->forward_x11;
- goto parse_flag;
-
case oForwardX11Trusted:
intptr = &options->forward_x11_trusted;
goto parse_flag;
@@ -852,10 +1025,6 @@ parse_time:
intptr = &options->exit_on_forward_failure;
goto parse_flag;
- case oUsePrivilegedPort:
- intptr = &options->use_privileged_port;
- goto parse_flag;
-
case oPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
@@ -872,14 +1041,6 @@ parse_time:
intptr = &options->pubkey_authentication;
goto parse_flag;
- case oRSAAuthentication:
- intptr = &options->rsa_authentication;
- goto parse_flag;
-
- case oRhostsRSAAuthentication:
- intptr = &options->rhosts_rsa_authentication;
- goto parse_flag;
-
case oHostbasedAuthentication:
intptr = &options->hostbased_authentication;
goto parse_flag;
@@ -911,12 +1072,13 @@ parse_time:
case oStrictHostKeyChecking:
intptr = &options->strict_host_key_checking;
- multistate_ptr = multistate_yesnoask;
+ multistate_ptr = multistate_strict_hostkey;
goto parse_multistate;
case oCompression:
intptr = &options->compression;
- goto parse_flag;
+ multistate_ptr = multistate_compression;
+ goto parse_multistate;
case oTCPKeepAlive:
intptr = &options->tcp_keep_alive;
@@ -930,10 +1092,6 @@ parse_time:
intptr = &options->number_of_password_prompts;
goto parse_int;
- case oCompressionLevel:
- intptr = &options->compression_level;
- goto parse_int;
-
case oRekeyLimit:
arg = strdelim(&s);
if (!arg || *arg == '\0')
@@ -945,16 +1103,12 @@ parse_time:
if (scan_scaled(arg, &val64) == -1)
fatal("%.200s line %d: Bad number '%s': %s",
filename, linenum, arg, strerror(errno));
- /* check for too-large or too-small limits */
- if (val64 > UINT_MAX)
- fatal("%.200s line %d: RekeyLimit too large",
- filename, linenum);
if (val64 != 0 && val64 < 16)
fatal("%.200s line %d: RekeyLimit too small",
filename, linenum);
}
if (*activep && options->rekey_limit == -1)
- options->rekey_limit = (u_int32_t)val64;
+ options->rekey_limit = val64;
if (s != NULL) { /* optional rekey interval present */
if (strcmp(s, "none") == 0) {
(void)strdelim(&s); /* discard */
@@ -979,6 +1133,24 @@ parse_time:
}
break;
+ case oCertificateFile:
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing argument.",
+ filename, linenum);
+ if (*activep) {
+ intptr = &options->num_certificate_files;
+ if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
+ fatal("%.200s line %d: Too many certificate "
+ "files specified (max %d).",
+ filename, linenum,
+ SSH_MAX_CERTIFICATE_FILES);
+ }
+ add_certificate_file(options, arg,
+ flags & SSHCONF_USERCONF);
+ }
+ break;
+
case oXAuthLocation:
charptr=&options->xauth_location;
goto parse_string;
@@ -1003,7 +1175,7 @@ parse_char_array:
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
if ((*uintptr) >= max_entries)
fatal("%s line %d: "
- "too many authorized keys files.",
+ "too many known hosts files.",
filename, linenum);
cpptr[(*uintptr)++] = xstrdup(arg);
}
@@ -1016,7 +1188,7 @@ parse_char_array:
max_entries = SSH_MAX_HOSTS_FILES;
goto parse_char_array;
- case oHostName:
+ case oHostname:
charptr = &options->hostname;
goto parse_string;
@@ -1032,12 +1204,23 @@ parse_char_array:
charptr = &options->bind_address;
goto parse_string;
+ case oBindInterface:
+ charptr = &options->bind_interface;
+ goto parse_string;
+
case oPKCS11Provider:
charptr = &options->pkcs11_provider;
goto parse_string;
+ case oSecurityKeyProvider:
+ charptr = &options->sk_provider;
+ goto parse_string;
+
case 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);
@@ -1046,36 +1229,38 @@ parse_command:
*charptr = xstrdup(s + len);
return 0;
+ case oProxyJump:
+ if (s == NULL) {
+ fatal("%.200s line %d: Missing argument.",
+ filename, linenum);
+ }
+ len = strspn(s, WHITESPACE "=");
+ if (parse_jump(s + len, options, *activep) == -1) {
+ fatal("%.200s line %d: Invalid ProxyJump \"%s\"",
+ filename, linenum, s + len);
+ }
+ return 0;
+
case oPort:
- intptr = &options->port;
-parse_int:
arg = strdelim(&s);
if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (arg[0] < '0' || arg[0] > '9')
- fatal("%.200s line %d: Bad number.", filename, linenum);
-
- /* Octal, decimal, or hex format? */
- value = strtol(arg, &endofnumber, 0);
- if (arg == endofnumber)
- fatal("%.200s line %d: Bad number.", filename, linenum);
- if (*activep && *intptr == -1)
- *intptr = value;
+ fatal("%.200s line %d: Missing argument.",
+ filename, linenum);
+ value = a2port(arg);
+ if (value <= 0)
+ fatal("%.200s line %d: Bad port '%s'.",
+ filename, linenum, arg);
+ if (*activep && options->port == -1)
+ options->port = value;
break;
case oConnectionAttempts:
intptr = &options->connection_attempts;
- goto parse_int;
-
- case oCipher:
- intptr = &options->cipher;
+parse_int:
arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- value = cipher_number(arg);
- if (value == -1)
- fatal("%.200s line %d: Bad cipher '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ if ((errstr = atoi_err(arg, &value)) != NULL)
+ fatal("%s line %d: integer value %s.",
+ filename, linenum, errstr);
if (*activep && *intptr == -1)
*intptr = value;
break;
@@ -1084,7 +1269,8 @@ parse_int:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (!ciphers_valid(arg))
+ if (*arg != '-' &&
+ !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && options->ciphers == NULL)
@@ -1095,8 +1281,9 @@ parse_int:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (!mac_valid(arg))
- fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
+ if (*arg != '-' &&
+ !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
+ fatal("%.200s line %d: Bad SSH2 MAC spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && options->macs == NULL)
options->macs = xstrdup(arg);
@@ -1107,7 +1294,9 @@ parse_int:
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
- if (!kex_names_valid(arg))
+ if (*arg != '-' &&
+ !kex_names_valid(*arg == '+' || *arg == '^' ?
+ arg + 1 : arg))
fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && options->kex_algorithms == NULL)
@@ -1115,28 +1304,24 @@ parse_int:
break;
case oHostKeyAlgorithms:
+ charptr = &options->hostkeyalgorithms;
+parse_keytypes:
arg = strdelim(&s);
if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (!sshkey_names_valid2(arg, 1))
- fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
- if (*activep && options->hostkeyalgorithms == NULL)
- options->hostkeyalgorithms = xstrdup(arg);
+ fatal("%.200s line %d: Missing argument.",
+ filename, linenum);
+ if (*arg != '-' &&
+ !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
+ arg + 1 : arg, 1))
+ fatal("%s line %d: Bad key types '%s'.",
+ filename, linenum, arg ? arg : "<NONE>");
+ if (*activep && *charptr == NULL)
+ *charptr = xstrdup(arg);
break;
- case oProtocol:
- intptr = &options->protocol;
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- value = proto_spec(arg);
- if (value == SSH_PROTO_UNKNOWN)
- fatal("%.200s line %d: Bad protocol spec '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
- if (*activep && *intptr == SSH_PROTO_UNKNOWN)
- *intptr = value;
- break;
+ case oCASignatureAlgorithms:
+ charptr = &options->ca_sign_algorithms;
+ goto parse_keytypes;
case oLogLevel:
log_level_ptr = &options->log_level;
@@ -1149,6 +1334,17 @@ parse_int:
*log_level_ptr = (LogLevel) value;
break;
+ case oLogFacility:
+ log_facility_ptr = &options->log_facility;
+ arg = strdelim(&s);
+ value = log_facility_number(arg);
+ if (value == SYSLOG_FACILITY_NOT_SET)
+ fatal("%.200s line %d: unsupported log facility '%s'",
+ filename, linenum, arg ? arg : "<NONE>");
+ if (*log_facility_ptr == -1)
+ *log_facility_ptr = (SyslogFacility) value;
+ break;
+
case oLocalForward:
case oRemoteForward:
case oDynamicForward:
@@ -1157,31 +1353,36 @@ parse_int:
fatal("%.200s line %d: Missing port argument.",
filename, linenum);
- if (opcode == oLocalForward ||
- opcode == oRemoteForward) {
- arg2 = strdelim(&s);
- if (arg2 == NULL || *arg2 == '\0')
- fatal("%.200s line %d: Missing target argument.",
- filename, linenum);
+ remotefwd = (opcode == oRemoteForward);
+ dynamicfwd = (opcode == oDynamicForward);
- /* construct a string for parse_forward */
- snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
- } else if (opcode == oDynamicForward) {
- strlcpy(fwdarg, arg, sizeof(fwdarg));
+ if (!dynamicfwd) {
+ arg2 = strdelim(&s);
+ if (arg2 == NULL || *arg2 == '\0') {
+ if (remotefwd)
+ dynamicfwd = 1;
+ else
+ fatal("%.200s line %d: Missing target "
+ "argument.", filename, linenum);
+ } else {
+ /* construct a string for parse_forward */
+ snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
+ arg2);
+ }
}
+ if (dynamicfwd)
+ strlcpy(fwdarg, arg, sizeof(fwdarg));
- if (parse_forward(&fwd, fwdarg,
- opcode == oDynamicForward ? 1 : 0,
- opcode == oRemoteForward ? 1 : 0) == 0)
+ if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0)
fatal("%.200s line %d: Bad forwarding specification.",
filename, linenum);
if (*activep) {
- if (opcode == oLocalForward ||
- opcode == oDynamicForward)
- add_local_forward(options, &fwd);
- else if (opcode == oRemoteForward)
+ if (remotefwd) {
add_remote_forward(options, &fwd);
+ } else {
+ add_local_forward(options, &fwd);
+ }
}
break;
@@ -1196,6 +1397,8 @@ parse_int:
*activep = 0;
arg2 = NULL;
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+ if ((flags & SSHCONF_NEVERMATCH) != 0)
+ break;
negated = *arg == '!';
if (negated)
arg++;
@@ -1224,11 +1427,12 @@ parse_int:
fatal("Host directive not supported as a command-line "
"option");
value = match_cfg_line(options, &s, pw, host, original_host,
- flags & SSHCONF_POSTCANON, filename, linenum);
+ flags & SSHCONF_FINAL, want_final_pass,
+ filename, linenum);
if (value < 0)
fatal("%.200s line %d: Bad Match condition", filename,
linenum);
- *activep = value;
+ *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
break;
case oEscapeChar:
@@ -1236,13 +1440,13 @@ parse_int:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (arg[0] == '^' && arg[2] == 0 &&
+ if (strcmp(arg, "none") == 0)
+ value = SSH_ESCAPECHAR_NONE;
+ else if (arg[1] == '\0')
+ value = (u_char) arg[0];
+ else if (arg[0] == '^' && arg[2] == 0 &&
(u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
value = (u_char) arg[1] & 31;
- else if (strlen(arg) == 1)
- value = (u_char) arg[0];
- else if (strcmp(arg, "none") == 0)
- value = SSH_ESCAPECHAR_NONE;
else {
fatal("%.200s line %d: Bad escape character.",
filename, linenum);
@@ -1281,11 +1485,41 @@ parse_int:
filename, linenum);
if (!*activep)
continue;
- if (options->num_send_env >= MAX_SEND_ENV)
- fatal("%s line %d: too many send env.",
+ if (*arg == '-') {
+ /* Removing an env var */
+ rm_env(options, arg, filename, linenum);
+ continue;
+ } else {
+ /* Adding an env var */
+ if (options->num_send_env >= INT_MAX)
+ fatal("%s line %d: too many send env.",
+ filename, linenum);
+ options->send_env = xrecallocarray(
+ options->send_env, options->num_send_env,
+ options->num_send_env + 1,
+ sizeof(*options->send_env));
+ options->send_env[options->num_send_env++] =
+ xstrdup(arg);
+ }
+ }
+ break;
+
+ case oSetEnv:
+ value = options->num_setenv;
+ while ((arg = strdelimw(&s)) != NULL && *arg != '\0') {
+ if (strchr(arg, '=') == NULL)
+ fatal("%s line %d: Invalid SetEnv.",
+ filename, linenum);
+ if (!*activep || value != 0)
+ continue;
+ /* Adding a setenv var */
+ if (options->num_setenv >= INT_MAX)
+ fatal("%s line %d: too many SetEnv.",
filename, linenum);
- options->send_env[options->num_send_env++] =
- xstrdup(arg);
+ options->setenv = xrecallocarray(
+ options->setenv, options->num_setenv,
+ options->num_setenv + 1, sizeof(*options->setenv));
+ options->setenv[options->num_setenv++] = xstrdup(arg);
}
break;
@@ -1352,10 +1586,77 @@ parse_int:
intptr = &options->permit_local_command;
goto parse_flag;
+ case oRemoteCommand:
+ charptr = &options->remote_command;
+ goto parse_command;
+
case oVisualHostKey:
intptr = &options->visual_host_key;
goto parse_flag;
+ case oInclude:
+ if (cmdline)
+ fatal("Include directive not supported as a "
+ "command-line option");
+ value = 0;
+ while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+ /*
+ * Ensure all paths are anchored. User configuration
+ * files may begin with '~/' but system configurations
+ * must not. If the path is relative, then treat it
+ * as living in ~/.ssh for user configurations or
+ * /etc/ssh for system ones.
+ */
+ if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0)
+ fatal("%.200s line %d: bad include path %s.",
+ filename, linenum, arg);
+ if (!path_absolute(arg) && *arg != '~') {
+ xasprintf(&arg2, "%s/%s",
+ (flags & SSHCONF_USERCONF) ?
+ "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
+ } else
+ arg2 = xstrdup(arg);
+ memset(&gl, 0, sizeof(gl));
+ r = glob(arg2, GLOB_TILDE, NULL, &gl);
+ if (r == GLOB_NOMATCH) {
+ debug("%.200s line %d: include %s matched no "
+ "files",filename, linenum, arg2);
+ free(arg2);
+ continue;
+ } else if (r != 0)
+ fatal("%.200s line %d: glob failed for %s.",
+ filename, linenum, arg2);
+ free(arg2);
+ oactive = *activep;
+ for (i = 0; i < gl.gl_pathc; i++) {
+ debug3("%.200s line %d: Including file %s "
+ "depth %d%s", filename, linenum,
+ gl.gl_pathv[i], depth,
+ oactive ? "" : " (parse only)");
+ r = read_config_file_depth(gl.gl_pathv[i],
+ pw, host, original_host, options,
+ flags | SSHCONF_CHECKPERM |
+ (oactive ? 0 : SSHCONF_NEVERMATCH),
+ activep, want_final_pass, depth + 1);
+ if (r != 1 && errno != ENOENT) {
+ fatal("Can't open user config file "
+ "%.100s: %.100s", gl.gl_pathv[i],
+ strerror(errno));
+ }
+ /*
+ * don't let Match in includes clobber the
+ * containing file's Match state.
+ */
+ *activep = oactive;
+ if (r != 1)
+ value = -1;
+ }
+ globfree(&gl);
+ }
+ if (value != 0)
+ return value;
+ break;
+
case oIPQoS:
arg = strdelim(&s);
if ((value = parse_ipqos(arg)) == -1)
@@ -1373,10 +1674,6 @@ parse_int:
}
break;
- case oUseRoaming:
- intptr = &options->use_roaming;
- goto parse_flag;
-
case oRequestTTY:
intptr = &options->request_tty;
multistate_ptr = multistate_requesttty;
@@ -1393,7 +1690,10 @@ parse_int:
case oCanonicalDomains:
value = options->num_canonical_domains != 0;
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- valid_domain(arg, filename, linenum);
+ if (!valid_domain(arg, 1, &errstr)) {
+ fatal("%s line %d: %s", filename, linenum,
+ errstr);
+ }
if (!*activep || value)
continue;
if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
@@ -1485,13 +1785,29 @@ parse_int:
case oHostbasedKeyTypes:
charptr = &options->hostbased_key_types;
+ goto parse_keytypes;
+
+ case oPubkeyAcceptedKeyTypes:
+ charptr = &options->pubkey_key_types;
+ goto parse_keytypes;
+
+ case oAddKeysToAgent:
+ intptr = &options->add_keys_to_agent;
+ multistate_ptr = multistate_yesnoaskconfirm;
+ goto parse_multistate;
+
+ case oIdentityAgent:
+ charptr = &options->identity_agent;
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
- if (!sshkey_names_valid2(arg, 1))
- fatal("%s line %d: Bad key types '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ 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.",
+ filename, linenum, arg);
+ }
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
@@ -1518,22 +1834,37 @@ parse_int:
return 0;
}
-
/*
* Reads the config file and modifies the options accordingly. Options
* should already be initialized before this call. This never returns if
* there is an error. If the file does not exist, this returns 0.
*/
-
int
read_config_file(const char *filename, struct passwd *pw, const char *host,
- const char *original_host, Options *options, int flags)
+ const char *original_host, Options *options, int flags,
+ int *want_final_pass)
+{
+ int active = 1;
+
+ return read_config_file_depth(filename, pw, host, original_host,
+ options, flags, &active, want_final_pass, 0);
+}
+
+#define READCONF_MAX_DEPTH 16
+static int
+read_config_file_depth(const char *filename, struct passwd *pw,
+ const char *host, const char *original_host, Options *options,
+ int flags, int *activep, int *want_final_pass, int depth)
{
FILE *f;
- char line[1024];
- int active, linenum;
+ char *line = NULL;
+ size_t linesize = 0;
+ int linenum;
int bad_options = 0;
+ if (depth < 0 || depth > READCONF_MAX_DEPTH)
+ fatal("Too many recursive configuration includes");
+
if ((f = fopen(filename, "r")) == NULL)
return 0;
@@ -1553,15 +1884,16 @@ read_config_file(const char *filename, struct passwd *pw, const char *host,
* Mark that we are now processing the options. This flag is turned
* on/off by Host specifications.
*/
- active = 1;
linenum = 0;
- while (fgets(line, sizeof(line), f)) {
+ while (getline(&line, &linesize, f) != -1) {
/* Update line number counter. */
linenum++;
- if (process_config_line(options, pw, host, original_host,
- line, filename, linenum, &active, flags) != 0)
+ if (process_config_line_depth(options, pw, host, original_host,
+ line, filename, linenum, activep, flags, want_final_pass,
+ depth) != 0)
bad_options++;
}
+ free(line);
fclose(f);
if (bad_options > 0)
fatal("%s: terminating, %d bad configuration options",
@@ -1588,16 +1920,18 @@ initialize_options(Options * options)
{
memset(options, 'X', sizeof(*options));
options->forward_agent = -1;
+ options->forward_agent_sock_path = NULL;
options->forward_x11 = -1;
options->forward_x11_trusted = -1;
options->forward_x11_timeout = -1;
+ options->stdio_forward_host = NULL;
+ options->stdio_forward_port = 0;
+ options->clear_forwardings = -1;
options->exit_on_forward_failure = -1;
options->xauth_location = NULL;
options->fwd_opts.gateway_ports = -1;
options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
options->fwd_opts.streamlocal_bind_unlink = -1;
- options->use_privileged_port = -1;
- options->rsa_authentication = -1;
options->pubkey_authentication = -1;
options->challenge_response_authentication = -1;
options->gss_authentication = -1;
@@ -1605,29 +1939,31 @@ initialize_options(Options * options)
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->kbd_interactive_devices = NULL;
- options->rhosts_rsa_authentication = -1;
options->hostbased_authentication = -1;
options->batch_mode = -1;
options->check_host_ip = -1;
options->strict_host_key_checking = -1;
options->compression = -1;
options->tcp_keep_alive = -1;
- options->compression_level = -1;
options->port = -1;
options->address_family = -1;
options->connection_attempts = -1;
options->connection_timeout = -1;
options->number_of_password_prompts = -1;
- options->cipher = -1;
options->ciphers = NULL;
options->macs = NULL;
options->kex_algorithms = NULL;
options->hostkeyalgorithms = NULL;
- options->protocol = SSH_PROTO_UNKNOWN;
+ options->ca_sign_algorithms = NULL;
options->num_identity_files = 0;
+ options->num_certificate_files = 0;
options->hostname = NULL;
options->host_key_alias = NULL;
options->proxy_command = NULL;
+ options->jump_user = NULL;
+ options->jump_host = NULL;
+ options->jump_port = -1;
+ options->jump_extra = NULL;
options->user = NULL;
options->escape_char = -1;
options->num_system_hostfiles = 0;
@@ -1636,11 +1972,13 @@ initialize_options(Options * options)
options->num_local_forwards = 0;
options->remote_forwards = NULL;
options->num_remote_forwards = 0;
- options->clear_forwardings = -1;
+ options->log_facility = SYSLOG_FACILITY_NOT_SET;
options->log_level = SYSLOG_LEVEL_NOT_SET;
options->preferred_authentications = NULL;
options->bind_address = NULL;
+ options->bind_interface = NULL;
options->pkcs11_provider = NULL;
+ options->sk_provider = NULL;
options->enable_ssh_keysign = - 1;
options->no_host_authentication_for_localhost = - 1;
options->identities_only = - 1;
@@ -1649,7 +1987,10 @@ initialize_options(Options * options)
options->verify_host_key_dns = -1;
options->server_alive_interval = -1;
options->server_alive_count_max = -1;
+ options->send_env = NULL;
options->num_send_env = 0;
+ options->setenv = NULL;
+ options->num_setenv = 0;
options->control_path = NULL;
options->control_master = -1;
options->control_persist = -1;
@@ -1660,7 +2001,9 @@ initialize_options(Options * options)
options->tun_remote = -1;
options->local_command = NULL;
options->permit_local_command = -1;
- options->use_roaming = 0;
+ options->remote_command = NULL;
+ options->add_keys_to_agent = -1;
+ options->identity_agent = NULL;
options->visual_host_key = -1;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
@@ -1676,6 +2019,7 @@ initialize_options(Options * options)
options->fingerprint_hash = -1;
options->update_hostkeys = -1;
options->hostbased_key_types = NULL;
+ options->pubkey_key_types = NULL;
}
/*
@@ -1700,6 +2044,10 @@ fill_default_options_for_canonicalization(Options *options)
void
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;
+
if (options->forward_agent == -1)
options->forward_agent = 0;
if (options->forward_x11 == -1)
@@ -1708,8 +2056,19 @@ fill_default_options(Options * options)
options->forward_x11_trusted = 0;
if (options->forward_x11_timeout == -1)
options->forward_x11_timeout = 1200;
+ /*
+ * stdio forwarding (-W) changes the default for these but we defer
+ * setting the values so they can be overridden.
+ */
if (options->exit_on_forward_failure == -1)
- options->exit_on_forward_failure = 0;
+ options->exit_on_forward_failure =
+ options->stdio_forward_host != NULL ? 1 : 0;
+ if (options->clear_forwardings == -1)
+ options->clear_forwardings =
+ options->stdio_forward_host != NULL ? 1 : 0;
+ if (options->clear_forwardings == 1)
+ clear_forwardings(options);
+
if (options->xauth_location == NULL)
options->xauth_location = _PATH_XAUTH;
if (options->fwd_opts.gateway_ports == -1)
@@ -1718,10 +2077,6 @@ fill_default_options(Options * options)
options->fwd_opts.streamlocal_bind_mask = 0177;
if (options->fwd_opts.streamlocal_bind_unlink == -1)
options->fwd_opts.streamlocal_bind_unlink = 0;
- if (options->use_privileged_port == -1)
- options->use_privileged_port = 0;
- if (options->rsa_authentication == -1)
- options->rsa_authentication = 1;
if (options->pubkey_authentication == -1)
options->pubkey_authentication = 1;
if (options->challenge_response_authentication == -1)
@@ -1734,8 +2089,6 @@ fill_default_options(Options * options)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
options->kbd_interactive_authentication = 1;
- if (options->rhosts_rsa_authentication == -1)
- options->rhosts_rsa_authentication = 0;
if (options->hostbased_authentication == -1)
options->hostbased_authentication = 0;
if (options->batch_mode == -1)
@@ -1743,13 +2096,11 @@ fill_default_options(Options * options)
if (options->check_host_ip == -1)
options->check_host_ip = 1;
if (options->strict_host_key_checking == -1)
- options->strict_host_key_checking = 2; /* 2 is default */
+ options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
if (options->compression == -1)
options->compression = 0;
if (options->tcp_keep_alive == -1)
options->tcp_keep_alive = 1;
- if (options->compression_level == -1)
- options->compression_level = 6;
if (options->port == -1)
options->port = 0; /* Filled in ssh_connect. */
if (options->address_family == -1)
@@ -1758,32 +2109,22 @@ fill_default_options(Options * options)
options->connection_attempts = 1;
if (options->number_of_password_prompts == -1)
options->number_of_password_prompts = 3;
- /* Selected in ssh_login(). */
- if (options->cipher == -1)
- options->cipher = SSH_CIPHER_NOT_SET;
- /* options->ciphers, default set in myproposals.h */
- /* options->macs, default set in myproposals.h */
- /* options->kex_algorithms, default set in myproposals.h */
/* options->hostkeyalgorithms, default set in myproposals.h */
- if (options->protocol == SSH_PROTO_UNKNOWN)
- options->protocol = SSH_PROTO_2;
+ if (options->add_keys_to_agent == -1)
+ options->add_keys_to_agent = 0;
if (options->num_identity_files == 0) {
- if (options->protocol & SSH_PROTO_1) {
- add_identity_file(options, "~/",
- _PATH_SSH_CLIENT_IDENTITY, 0);
- }
- if (options->protocol & SSH_PROTO_2) {
- add_identity_file(options, "~/",
- _PATH_SSH_CLIENT_ID_RSA, 0);
- add_identity_file(options, "~/",
- _PATH_SSH_CLIENT_ID_DSA, 0);
+ add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
+ add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
#ifdef OPENSSL_HAS_ECC
- add_identity_file(options, "~/",
- _PATH_SSH_CLIENT_ID_ECDSA, 0);
+ add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
+ add_identity_file(options, "~/",
+ _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
#endif
- add_identity_file(options, "~/",
- _PATH_SSH_CLIENT_ID_ED25519, 0);
- }
+ add_identity_file(options, "~/",
+ _PATH_SSH_CLIENT_ID_ED25519, 0);
+ add_identity_file(options, "~/",
+ _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
+ add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
}
if (options->escape_char == -1)
options->escape_char = '~';
@@ -1793,6 +2134,8 @@ fill_default_options(Options * options)
options->system_hostfiles[options->num_system_hostfiles++] =
xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
}
+ if (options->update_hostkeys == -1)
+ 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);
@@ -1801,8 +2144,8 @@ fill_default_options(Options * options)
}
if (options->log_level == SYSLOG_LEVEL_NOT_SET)
options->log_level = SYSLOG_LEVEL_INFO;
- if (options->clear_forwardings == 1)
- clear_forwardings(options);
+ if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
+ options->log_facility = SYSLOG_FACILITY_USER;
if (options->no_host_authentication_for_localhost == - 1)
options->no_host_authentication_for_localhost = 0;
if (options->identities_only == -1)
@@ -1835,13 +2178,12 @@ fill_default_options(Options * options)
options->tun_remote = SSH_TUNID_ANY;
if (options->permit_local_command == -1)
options->permit_local_command = 0;
- options->use_roaming = 0;
if (options->visual_host_key == -1)
options->visual_host_key = 0;
if (options->ip_qos_interactive == -1)
- options->ip_qos_interactive = IPTOS_LOWDELAY;
+ options->ip_qos_interactive = IPTOS_DSCP_AF21;
if (options->ip_qos_bulk == -1)
- options->ip_qos_bulk = IPTOS_THROUGHPUT;
+ options->ip_qos_bulk = IPTOS_DSCP_CS1;
if (options->request_tty == -1)
options->request_tty = REQUEST_TTY_AUTO;
if (options->proxy_use_fdpass == -1)
@@ -1854,10 +2196,49 @@ fill_default_options(Options * options)
options->canonicalize_hostname = SSH_CANONICALISE_NO;
if (options->fingerprint_hash == -1)
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
- if (options->update_hostkeys == -1)
- options->update_hostkeys = 0;
- if (options->hostbased_key_types == NULL)
- options->hostbased_key_types = xstrdup("*");
+#ifdef ENABLE_SK_INTERNAL
+ if (options->sk_provider == NULL)
+ options->sk_provider = xstrdup("internal");
+#else
+ if (options->sk_provider == NULL)
+ options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
+#endif
+
+ /* Expand KEX name lists */
+ all_cipher = cipher_alg_list(',', 0);
+ all_mac = mac_alg_list(',');
+ all_kex = kex_alg_list(',');
+ all_key = sshkey_alg_list(0, 0, 1, ',');
+ all_sig = sshkey_alg_list(0, 1, 1, ',');
+ /* remove unsupported algos from default lists */
+ def_cipher = match_filter_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);
+#define ASSEMBLE(what, defaults, all) \
+ do { \
+ if ((r = kex_assemble_names(&options->what, \
+ defaults, all)) != 0) \
+ fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \
+ } while (0)
+ ASSEMBLE(ciphers, 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(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 { \
@@ -1867,9 +2248,19 @@ fill_default_options(Options * options)
} \
} while(0)
CLEAR_ON_NONE(options->local_command);
+ CLEAR_ON_NONE(options->remote_command);
CLEAR_ON_NONE(options->proxy_command);
CLEAR_ON_NONE(options->control_path);
CLEAR_ON_NONE(options->revoked_host_keys);
+ CLEAR_ON_NONE(options->pkcs11_provider);
+ CLEAR_ON_NONE(options->sk_provider);
+ if (options->jump_host != NULL &&
+ strcmp(options->jump_host, "none") == 0 &&
+ options->jump_port == 0 && options->jump_user == NULL) {
+ free(options->jump_host);
+ options->jump_host = NULL;
+ }
+ /* options->identity_agent distinguishes NULL from 'none' */
/* options->user will be set in the main program if appropriate */
/* options->hostname will be set in the main program if appropriate */
/* options->host_key_alias should not be set by default */
@@ -1926,7 +2317,8 @@ parse_fwd_field(char **p, struct fwdarg *fwd)
switch (*cp) {
case '\\':
memmove(cp, cp + 1, strlen(cp + 1) + 1);
- cp++;
+ if (*cp == '\0')
+ return -1;
break;
case '/':
ispath = 1;
@@ -2084,6 +2476,75 @@ parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remo
return (0);
}
+int
+parse_jump(const char *s, Options *o, int active)
+{
+ char *orig, *sdup, *cp;
+ char *host = NULL, *user = NULL;
+ int ret = -1, port = -1, first;
+
+ active &= o->proxy_command == NULL && o->jump_host == NULL;
+
+ orig = sdup = xstrdup(s);
+ first = active;
+ do {
+ if (strcasecmp(s, "none") == 0)
+ break;
+ if ((cp = strrchr(sdup, ',')) == NULL)
+ cp = sdup; /* last */
+ else
+ *cp++ = '\0';
+
+ if (first) {
+ /* First argument and configuration is active */
+ if (parse_ssh_uri(cp, &user, &host, &port) == -1 ||
+ parse_user_host_port(cp, &user, &host, &port) != 0)
+ goto out;
+ } else {
+ /* Subsequent argument or inactive configuration */
+ if (parse_ssh_uri(cp, NULL, NULL, NULL) == -1 ||
+ parse_user_host_port(cp, NULL, NULL, NULL) != 0)
+ goto out;
+ }
+ first = 0; /* only check syntax for subsequent hosts */
+ } while (cp != sdup);
+ /* success */
+ if (active) {
+ if (strcasecmp(s, "none") == 0) {
+ o->jump_host = xstrdup("none");
+ o->jump_port = 0;
+ } else {
+ o->jump_user = user;
+ o->jump_host = host;
+ o->jump_port = port;
+ o->proxy_command = xstrdup("none");
+ user = host = NULL;
+ if ((cp = strrchr(s, ',')) != NULL && cp != s) {
+ o->jump_extra = xstrdup(s);
+ o->jump_extra[cp - s] = '\0';
+ }
+ }
+ }
+ ret = 0;
+ out:
+ free(orig);
+ free(user);
+ free(host);
+ return ret;
+}
+
+int
+parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
+{
+ char *path;
+ int r;
+
+ r = parse_uri("ssh", uri, userp, hostp, portp, &path);
+ if (r == 0 && path != NULL)
+ r = -1; /* path not allowed */
+ return r;
+}
+
/* XXX the following is a near-vebatim copy from servconf.c; refactor */
static const char *
fmt_multistate_int(int val, const struct multistate *m)
@@ -2106,9 +2567,10 @@ fmt_intarg(OpCodes code, int val)
case oAddressFamily:
return fmt_multistate_int(val, multistate_addressfamily);
case oVerifyHostKeyDNS:
- case oStrictHostKeyChecking:
case oUpdateHostkeys:
return fmt_multistate_int(val, multistate_yesnoask);
+ case oStrictHostKeyChecking:
+ return fmt_multistate_int(val, multistate_strict_hostkey);
case oControlMaster:
return fmt_multistate_int(val, multistate_controlmaster);
case oTunnel:
@@ -2117,19 +2579,10 @@ fmt_intarg(OpCodes code, int val)
return fmt_multistate_int(val, multistate_requesttty);
case oCanonicalizeHostname:
return fmt_multistate_int(val, multistate_canonicalizehostname);
+ case oAddKeysToAgent:
+ return fmt_multistate_int(val, multistate_yesnoaskconfirm);
case oFingerprintHash:
return ssh_digest_alg_name(val);
- case oProtocol:
- switch (val) {
- case SSH_PROTO_1:
- return "1";
- case SSH_PROTO_2:
- return "2";
- case (SSH_PROTO_1|SSH_PROTO_2):
- return "2,1";
- default:
- return "UNKNOWN";
- }
default:
switch (val) {
case 0:
@@ -2202,10 +2655,10 @@ dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
/* oDynamicForward */
for (i = 0; i < count; i++) {
fwd = &fwds[i];
- if (code == oDynamicForward &&
+ if (code == oDynamicForward && fwd->connect_host != NULL &&
strcmp(fwd->connect_host, "socks") != 0)
continue;
- if (code == oLocalForward &&
+ if (code == oLocalForward && fwd->connect_host != NULL &&
strcmp(fwd->connect_host, "socks") == 0)
continue;
printf("%s", lookup_opcode_name(code));
@@ -2234,15 +2687,28 @@ dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
void
dump_client_config(Options *o, const char *host)
{
- int i;
- char vbuf[5];
+ int i, r;
+ char buf[8], *all_key;
+
+ /*
+ * Expand HostKeyAlgorithms name lists. This isn't handled in
+ * fill_default_options() like the other algorithm lists because
+ * the host key algorithms are by default dynamically chosen based
+ * on the host's keys found in known_hosts.
+ */
+ all_key = sshkey_alg_list(0, 0, 1, ',');
+ if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
+ all_key)) != 0)
+ fatal("%s: expand HostKeyAlgorithms: %s", __func__, ssh_err(r));
+ free(all_key);
/* Most interesting options first: user, host, port */
dump_cfg_string(oUser, o->user);
- dump_cfg_string(oHostName, host);
+ dump_cfg_string(oHostname, host);
dump_cfg_int(oPort, o->port);
/* Flag options */
+ dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
dump_cfg_fmtint(oAddressFamily, o->address_family);
dump_cfg_fmtint(oBatchMode, o->batch_mode);
dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
@@ -2252,9 +2718,9 @@ dump_client_config(Options *o, const char *host)
dump_cfg_fmtint(oCompression, o->compression);
dump_cfg_fmtint(oControlMaster, o->control_master);
dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
+ dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
- dump_cfg_fmtint(oForwardAgent, o->forward_agent);
dump_cfg_fmtint(oForwardX11, o->forward_x11);
dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
@@ -2269,24 +2735,19 @@ dump_client_config(Options *o, const char *host)
dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
- dump_cfg_fmtint(oProtocol, o->protocol);
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(oRhostsRSAAuthentication, o->rhosts_rsa_authentication);
- dump_cfg_fmtint(oRSAAuthentication, o->rsa_authentication);
dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
dump_cfg_fmtint(oTunnel, o->tun_open);
- dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port);
dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
/* Integer options */
dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
- dump_cfg_int(oCompressionLevel, o->compression_level);
dump_cfg_int(oConnectionAttempts, o->connection_attempts);
dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
@@ -2295,19 +2756,27 @@ dump_client_config(Options *o, const char *host)
/* String options */
dump_cfg_string(oBindAddress, o->bind_address);
- dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
+ dump_cfg_string(oBindInterface, o->bind_interface);
+ dump_cfg_string(oCiphers, o->ciphers);
dump_cfg_string(oControlPath, o->control_path);
- dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms ? o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
+ dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
dump_cfg_string(oHostKeyAlias, o->host_key_alias);
dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
+ dump_cfg_string(oIdentityAgent, o->identity_agent);
+ dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
- dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
+ dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
+ dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
dump_cfg_string(oLocalCommand, o->local_command);
+ dump_cfg_string(oRemoteCommand, o->remote_command);
dump_cfg_string(oLogLevel, log_level_name(o->log_level));
- dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
+ dump_cfg_string(oMacs, o->macs);
+#ifdef ENABLE_PKCS11
dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
+#endif
+ dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
- dump_cfg_string(oProxyCommand, o->proxy_command);
+ dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types);
dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
dump_cfg_string(oXAuthLocation, o->xauth_location);
@@ -2319,12 +2788,20 @@ dump_client_config(Options *o, const char *host)
/* String array options */
dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
+ dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
+ dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
/* Special cases */
+ /* oForwardAgent */
+ if (o->forward_agent_sock_path == NULL)
+ dump_cfg_fmtint(oForwardAgent, o->forward_agent);
+ else
+ dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
+
/* oConnectTimeout */
if (o->connection_timeout == -1)
printf("connecttimeout none\n");
@@ -2353,10 +2830,6 @@ dump_client_config(Options *o, const char *host)
printf("\n");
}
- /* oCipher */
- if (o->cipher != SSH_CIPHER_NOT_SET)
- printf("Cipher %s\n", cipher_name(o->cipher));
-
/* oControlPersist */
if (o->control_persist == 0 || o->control_persist_timeout == 0)
dump_cfg_fmtint(oControlPersist, o->control_persist);
@@ -2367,8 +2840,8 @@ dump_client_config(Options *o, const char *host)
if (o->escape_char == SSH_ESCAPECHAR_NONE)
printf("escapechar none\n");
else {
- vis(vbuf, o->escape_char, VIS_WHITE, 0);
- printf("escapechar %s\n", vbuf);
+ vis(buf, o->escape_char, VIS_WHITE, 0);
+ printf("escapechar %s\n", buf);
}
/* oIPQoS */
@@ -2376,10 +2849,39 @@ dump_client_config(Options *o, const char *host)
printf("%s\n", iptos2str(o->ip_qos_bulk));
/* oRekeyLimit */
- printf("rekeylimit %lld %d\n",
- (long long)o->rekey_limit, o->rekey_interval);
+ printf("rekeylimit %llu %d\n",
+ (unsigned long long)o->rekey_limit, o->rekey_interval);
/* oStreamLocalBindMask */
printf("streamlocalbindmask 0%o\n",
o->fwd_opts.streamlocal_bind_mask);
+
+ /* oLogFacility */
+ printf("syslogfacility %s\n", log_facility_name(o->log_facility));
+
+ /* oProxyCommand / oProxyJump */
+ if (o->jump_host == NULL)
+ dump_cfg_string(oProxyCommand, o->proxy_command);
+ else {
+ /* Check for numeric addresses */
+ i = strchr(o->jump_host, ':') != NULL ||
+ strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
+ snprintf(buf, sizeof(buf), "%d", o->jump_port);
+ printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
+ /* optional additional jump spec */
+ o->jump_extra == NULL ? "" : o->jump_extra,
+ o->jump_extra == NULL ? "" : ",",
+ /* optional user */
+ o->jump_user == NULL ? "" : o->jump_user,
+ o->jump_user == NULL ? "" : "@",
+ /* opening [ if hostname is numeric */
+ i ? "[" : "",
+ /* mandatory hostname */
+ o->jump_host,
+ /* closing ] if hostname is numeric */
+ i ? "]" : "",
+ /* optional port number */
+ o->jump_port <= 0 ? "" : ":",
+ o->jump_port <= 0 ? "" : buf);
+ }
}
diff --git a/readconf.h b/readconf.h
index 576b9e35..e143a108 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.109 2015/02/16 22:13:32 djm Exp $ */
+/* $OpenBSD: readconf.h,v 1.133 2020/04/03 02:27:12 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -18,7 +18,6 @@
/* Data structure for representing option data. */
-#define MAX_SEND_ENV 256
#define SSH_MAX_HOSTS_FILES 32
#define MAX_CANON_DOMAINS 32
#define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path)
@@ -30,16 +29,13 @@ struct allowed_cname {
typedef struct {
int forward_agent; /* Forward authentication agent. */
+ char *forward_agent_sock_path; /* Optional path of the agent. */
int forward_x11; /* Forward X11 display. */
int forward_x11_timeout; /* Expiration for Cookies */
int forward_x11_trusted; /* Trust Forward X11 display. */
int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */
char *xauth_location; /* Location for xauth program */
struct ForwardOptions fwd_opts; /* forwarding options */
- int use_privileged_port; /* Don't use privileged port if false. */
- int rhosts_rsa_authentication; /* Try rhosts with RSA
- * authentication. */
- int rsa_authentication; /* Try RSA authentication. */
int pubkey_authentication; /* Try ssh2 pubkey authentication. */
int hostbased_authentication; /* ssh2's rhosts_rsa */
int challenge_response_authentication;
@@ -54,11 +50,10 @@ typedef struct {
int check_host_ip; /* Also keep track of keys for IP address */
int strict_host_key_checking; /* Strict host key checking. */
int compression; /* Compress packets in both directions. */
- int compression_level; /* Compression level 1 (fast) to 9
- * (best). */
int tcp_keep_alive; /* Set SO_KEEPALIVE. */
int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */
int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */
+ SyslogFacility log_facility; /* Facility for system logging. */
LogLevel log_level; /* Level for logging. */
int port; /* Port to connect. */
@@ -69,12 +64,11 @@ typedef struct {
* aborting connection attempt */
int number_of_password_prompts; /* Max number of password
* prompts. */
- int cipher; /* Cipher to use. */
char *ciphers; /* SSH2 ciphers in order of preference. */
char *macs; /* SSH2 macs in order of preference. */
char *hostkeyalgorithms; /* SSH2 server key types in order of preference. */
char *kex_algorithms; /* SSH2 kex methods in order of preference. */
- int protocol; /* Protocol in order of preference. */
+ char *ca_sign_algorithms; /* Allowed CA signature algorithms */
char *hostname; /* Real host to connect. */
char *host_key_alias; /* hostname alias for .ssh/known_hosts */
char *proxy_command; /* Proxy command for connecting the host. */
@@ -87,7 +81,9 @@ typedef struct {
char *user_hostfiles[SSH_MAX_HOSTS_FILES];
char *preferred_authentications;
char *bind_address; /* local socket address for connection to sshd */
+ char *bind_interface; /* local interface for bind address */
char *pkcs11_provider; /* PKCS#11 provider */
+ char *sk_provider; /* Security key provider */
int verify_host_key_dns; /* Verify host key using DNS */
int num_identity_files; /* Number of files for RSA/DSA identities. */
@@ -95,6 +91,14 @@ typedef struct {
int identity_file_userprovided[SSH_MAX_IDENTITY_FILES];
struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES];
+ int num_certificate_files; /* Number of extra certificates for ssh. */
+ char *certificate_files[SSH_MAX_CERTIFICATE_FILES];
+ int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES];
+ struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
+
+ int add_keys_to_agent;
+ char *identity_agent; /* Optional path to ssh-agent socket */
+
/* Local TCP/IP forward requests. */
int num_local_forwards;
struct Forward *local_forwards;
@@ -104,6 +108,10 @@ typedef struct {
struct Forward *remote_forwards;
int clear_forwardings;
+ /* stdio forwarding (-W) host and port */
+ char *stdio_forward_host;
+ int stdio_forward_port;
+
int enable_ssh_keysign;
int64_t rekey_limit;
int rekey_interval;
@@ -113,7 +121,9 @@ typedef struct {
int server_alive_count_max;
int num_send_env;
- char *send_env[MAX_SEND_ENV];
+ char **send_env;
+ int num_setenv;
+ char **setenv;
char *control_path;
int control_master;
@@ -128,10 +138,9 @@ typedef struct {
char *local_command;
int permit_local_command;
+ char *remote_command;
int visual_host_key;
- int use_roaming;
-
int request_tty;
int proxy_use_fdpass;
@@ -150,7 +159,13 @@ typedef struct {
int update_hostkeys; /* one of SSH_UPDATE_HOSTKEYS_* */
- char *hostbased_key_types;
+ char *hostbased_key_types;
+ char *pubkey_key_types;
+
+ char *jump_user;
+ char *jump_host;
+ int jump_port;
+ char *jump_extra;
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
} Options;
@@ -172,20 +187,31 @@ typedef struct {
#define SSHCONF_CHECKPERM 1 /* check permissions on config file */
#define SSHCONF_USERCONF 2 /* user provided config file not system */
-#define SSHCONF_POSTCANON 4 /* After hostname canonicalisation */
+#define SSHCONF_FINAL 4 /* Final pass over config, after canon. */
+#define SSHCONF_NEVERMATCH 8 /* Match/Host never matches; internal only */
#define SSH_UPDATE_HOSTKEYS_NO 0
#define SSH_UPDATE_HOSTKEYS_YES 1
#define SSH_UPDATE_HOSTKEYS_ASK 2
+#define SSH_STRICT_HOSTKEY_OFF 0
+#define SSH_STRICT_HOSTKEY_NEW 1
+#define SSH_STRICT_HOSTKEY_YES 2
+#define SSH_STRICT_HOSTKEY_ASK 3
+
+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 *);
void fill_default_options_for_canonicalization(Options *);
int process_config_line(Options *, struct passwd *, const char *,
const char *, char *, const char *, int, int *, int);
int read_config_file(const char *, struct passwd *, const char *,
- const char *, Options *, int);
+ const char *, Options *, int, int *);
int parse_forward(struct Forward *, const char *, int, int);
+int parse_jump(const char *, Options *, int);
+int parse_ssh_uri(const char *, char **, char **, int *);
int default_ssh_port(void);
int option_clear_or_none(const char *);
void dump_client_config(Options *o, const char *host);
@@ -193,5 +219,6 @@ void dump_client_config(Options *o, const char *host);
void add_local_forward(Options *, const struct Forward *);
void add_remote_forward(Options *, const struct Forward *);
void add_identity_file(Options *, const char *, const char *, int);
+void add_certificate_file(Options *, const char *, int);
#endif /* READCONF_H */
diff --git a/readpass.c b/readpass.c
index 869d8642..974d67f0 100644
--- a/readpass.c
+++ b/readpass.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readpass.c,v 1.50 2014/02/02 03:44:31 djm Exp $ */
+/* $OpenBSD: readpass.c,v 1.61 2020/01/23 07:10:22 dtucker Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@@ -48,7 +48,7 @@
#include "uidswap.h"
static char *
-ssh_askpass(char *askpass, const char *msg)
+ssh_askpass(char *askpass, const char *msg, const char *env_hint)
{
pid_t pid, ret;
size_t len;
@@ -58,26 +58,27 @@ ssh_askpass(char *askpass, const char *msg)
void (*osigchld)(int);
if (fflush(stdout) != 0)
- error("ssh_askpass: fflush: %s", strerror(errno));
+ error("%s: fflush: %s", __func__, strerror(errno));
if (askpass == NULL)
fatal("internal error: askpass undefined");
- if (pipe(p) < 0) {
- error("ssh_askpass: pipe: %s", strerror(errno));
+ if (pipe(p) == -1) {
+ error("%s: pipe: %s", __func__, strerror(errno));
return NULL;
}
- osigchld = signal(SIGCHLD, SIG_DFL);
- if ((pid = fork()) < 0) {
- error("ssh_askpass: fork: %s", strerror(errno));
- signal(SIGCHLD, osigchld);
+ osigchld = ssh_signal(SIGCHLD, SIG_DFL);
+ if ((pid = fork()) == -1) {
+ error("%s: fork: %s", __func__, strerror(errno));
+ ssh_signal(SIGCHLD, osigchld);
return NULL;
}
if (pid == 0) {
- permanently_drop_suid(getuid());
close(p[0]);
- if (dup2(p[1], STDOUT_FILENO) < 0)
- fatal("ssh_askpass: dup2: %s", strerror(errno));
- execlp(askpass, askpass, msg, (char *) 0);
- fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno));
+ if (dup2(p[1], STDOUT_FILENO) == -1)
+ fatal("%s: dup2: %s", __func__, 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));
}
close(p[1]);
@@ -94,10 +95,10 @@ ssh_askpass(char *askpass, const char *msg)
buf[len] = '\0';
close(p[0]);
- while ((ret = waitpid(pid, &status, 0)) < 0)
+ while ((ret = waitpid(pid, &status, 0)) == -1)
if (errno != EINTR)
break;
- signal(SIGCHLD, osigchld);
+ ssh_signal(SIGCHLD, osigchld);
if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
explicit_bzero(buf, sizeof(buf));
return NULL;
@@ -109,6 +110,9 @@ ssh_askpass(char *askpass, const char *msg)
return pass;
}
+/* private/internal read_passphrase flags */
+#define RP_ASK_PERMISSION 0x8000 /* pass hint to askpass for confirm UI */
+
/*
* Reads a passphrase from /dev/tty with echo turned off/on. Returns the
* passphrase (allocated with xmalloc). Exits if EOF is encountered. If
@@ -118,8 +122,9 @@ ssh_askpass(char *askpass, const char *msg)
char *
read_passphrase(const char *prompt, int flags)
{
- char *askpass = NULL, *ret, buf[1024];
+ char cr = '\r', *askpass = NULL, *ret, buf[1024];
int rppflags, use_askpass = 0, ttyfd;
+ const char *askpass_hint = NULL;
rppflags = (flags & RP_ECHO) ? RPP_ECHO_ON : RPP_ECHO_OFF;
if (flags & RP_USE_ASKPASS)
@@ -132,9 +137,16 @@ read_passphrase(const char *prompt, int flags)
} else {
rppflags |= RPP_REQUIRE_TTY;
ttyfd = open(_PATH_TTY, O_RDWR);
- if (ttyfd >= 0)
+ if (ttyfd >= 0) {
+ /*
+ * If we're on a tty, ensure that show the prompt at
+ * the beginning of the line. This will hopefully
+ * clobber any password characters the user has
+ * optimistically typed before echo is disabled.
+ */
+ (void)write(ttyfd, &cr, 1);
close(ttyfd);
- else {
+ } else {
debug("read_passphrase: can't open %s: %s", _PATH_TTY,
strerror(errno));
use_askpass = 1;
@@ -149,7 +161,9 @@ read_passphrase(const char *prompt, int flags)
askpass = getenv(SSH_ASKPASS_ENV);
else
askpass = _PATH_SSH_ASKPASS_DEFAULT;
- if ((ret = ssh_askpass(askpass, prompt)) == NULL)
+ if ((flags & RP_ASK_PERMISSION) != 0)
+ askpass_hint = "confirm";
+ if ((ret = ssh_askpass(askpass, prompt, askpass_hint)) == NULL)
if (!(flags & RP_ALLOW_EOF))
return xstrdup("");
return ret;
@@ -177,7 +191,8 @@ ask_permission(const char *fmt, ...)
vsnprintf(prompt, sizeof(prompt), fmt, args);
va_end(args);
- p = read_passphrase(prompt, RP_USE_ASKPASS|RP_ALLOW_EOF);
+ p = read_passphrase(prompt,
+ RP_USE_ASKPASS|RP_ALLOW_EOF|RP_ASK_PERMISSION);
if (p != NULL) {
/*
* Accept empty responses and responses consisting
@@ -191,3 +206,89 @@ ask_permission(const char *fmt, ...)
return (allowed);
}
+
+struct notifier_ctx {
+ pid_t pid;
+ void (*osigchld)(int);
+};
+
+struct notifier_ctx *
+notify_start(int force_askpass, const char *fmt, ...)
+{
+ va_list args;
+ char *prompt = NULL;
+ int devnull;
+ pid_t pid;
+ void (*osigchld)(int);
+ const char *askpass;
+ struct notifier_ctx *ret;
+
+ va_start(args, fmt);
+ xvasprintf(&prompt, fmt, args);
+ va_end(args);
+
+ if (fflush(NULL) != 0)
+ error("%s: fflush: %s", __func__, 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;
+ }
+ 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;
+ }
+ osigchld = ssh_signal(SIGCHLD, SIG_DFL);
+ if ((pid = fork()) == -1) {
+ error("%s: fork: %s", __func__, 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));
+ 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));
+ _exit(1);
+ /* NOTREACHED */
+ }
+ if ((ret = calloc(1, sizeof(*ret))) == NULL) {
+ kill(pid, SIGTERM);
+ fatal("%s: calloc failed", __func__);
+ }
+ ret->pid = pid;
+ ret->osigchld = osigchld;
+ free(prompt);
+ return ret;
+}
+
+void
+notify_complete(struct notifier_ctx *ctx)
+{
+ int ret;
+
+ if (ctx == NULL || ctx->pid <= 0) {
+ free(ctx);
+ return;
+ }
+ kill(ctx->pid, SIGTERM);
+ while ((ret = waitpid(ctx->pid, NULL, 0)) == -1) {
+ if (errno != EINTR)
+ break;
+ }
+ if (ret == -1)
+ fatal("%s: waitpid: %s", __func__, strerror(errno));
+ ssh_signal(SIGCHLD, ctx->osigchld);
+ free(ctx);
+}
diff --git a/regress/Makefile b/regress/Makefile
new file mode 100644
index 00000000..62794d25
--- /dev/null
+++ b/regress/Makefile
@@ -0,0 +1,262 @@
+# $OpenBSD: Makefile,v 1.108 2020/04/20 04:44:47 djm Exp $
+
+tests: prep file-tests t-exec unit
+
+REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12
+
+# File based tests
+file-tests: $(REGRESS_TARGETS)
+
+# Interop tests are not run by default
+interop interop-tests: t-exec-interop
+
+prep:
+ test "x${USE_VALGRIND}" = "x" || mkdir -p $(OBJ)/valgrind-out
+
+clean:
+ for F in $(CLEANFILES); do rm -f $(OBJ)$$F; done
+ rm -rf $(OBJ).putty
+
+distclean: clean
+
+LTESTS= connect \
+ proxy-connect \
+ connect-privsep \
+ connect-uri \
+ proto-version \
+ proto-mismatch \
+ exit-status \
+ envpass \
+ transfer \
+ banner \
+ rekey \
+ dhgex \
+ stderr-data \
+ stderr-after-eof \
+ broken-pipe \
+ try-ciphers \
+ yes-head \
+ login-timeout \
+ agent \
+ agent-getpeereid \
+ agent-timeout \
+ agent-ptrace \
+ keyscan \
+ keygen-change \
+ keygen-convert \
+ keygen-moduli \
+ key-options \
+ scp \
+ scp-uri \
+ sftp \
+ sftp-chroot \
+ sftp-cmds \
+ sftp-badcmds \
+ sftp-batch \
+ sftp-glob \
+ sftp-perm \
+ sftp-uri \
+ reconfigure \
+ dynamic-forward \
+ forwarding \
+ multiplex \
+ reexec \
+ brokenkeys \
+ sshcfgparse \
+ cfgparse \
+ cfgmatch \
+ cfgmatchlisten \
+ percent \
+ addrmatch \
+ localcommand \
+ forcecommand \
+ portnum \
+ keytype \
+ kextype \
+ cert-hostkey \
+ cert-userkey \
+ host-expand \
+ keys-command \
+ forward-control \
+ integrity \
+ krl \
+ multipubkey \
+ limit-keytype \
+ hostkey-agent \
+ keygen-knownhosts \
+ hostkey-rotate \
+ principals-command \
+ cert-file \
+ cfginclude \
+ servcfginclude \
+ allow-deny-users \
+ authinfo \
+ sshsig \
+ keygen-comment
+
+
+INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
+#INTEROP_TESTS+=ssh-com ssh-com-client ssh-com-keygen ssh-com-sftp
+
+EXTRA_TESTS= agent-pkcs11
+#EXTRA_TESTS+= cipher-speed
+
+USERNAME= ${LOGNAME}
+CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \
+ authorized_keys_${USERNAME}.* \
+ authorized_principals_${USERNAME} \
+ banner.in banner.out cert_host_key* cert_user_key* \
+ copy.1 copy.2 data ed25519-agent ed25519-agent* \
+ ed25519-agent.pub ed25519 ed25519.pub empty.in \
+ expect failed-regress.log failed-ssh.log failed-sshd.log \
+ hkr.* host.ecdsa-sha2-nistp256 host.ecdsa-sha2-nistp384 \
+ host.ecdsa-sha2-nistp521 host.ssh-dss host.ssh-ed25519 \
+ host.ssh-rsa host_ca_key* host_krl_* host_revoked_* key.* \
+ key.dsa-* key.ecdsa-* key.ed25519-512 \
+ key.ed25519-512.pub key.rsa-* keys-command-args kh.* \
+ known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \
+ modpipe netcat no_identity_config \
+ pidfile putty.rsa2 ready regress.log remote_pid \
+ revoked-* rsa rsa-agent rsa-agent.pub rsa.pub rsa_ssh2_cr.prv \
+ rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \
+ scp-ssh-wrapper.scp setuid-allowed sftp-server.log \
+ sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \
+ ssh-rsa_oldfmt \
+ ssh_config ssh_config.* ssh_proxy ssh_proxy_bak \
+ ssh_proxy_envpass sshd.log sshd_config sshd_config_minimal \
+ sshd_config.* sshd_proxy sshd_proxy.* sshd_proxy_bak \
+ sshd_proxy_orig t10.out t10.out.pub t12.out t12.out.pub \
+ t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub \
+ t8.out t8.out.pub t9.out t9.out.pub testdata \
+ user_*key* user_ca* user_key*
+
+# Enable all malloc(3) randomisations and checks
+TEST_ENV= "MALLOC_OPTIONS=CFGJRSUX"
+
+TEST_SSH_SSHKEYGEN?=ssh-keygen
+
+CPPFLAGS=-I..
+
+t1:
+ ${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/rsa_ssh2.prv | diff - ${.CURDIR}/rsa_openssh.prv
+ tr '\n' '\r' <${.CURDIR}/rsa_ssh2.prv > ${.OBJDIR}/rsa_ssh2_cr.prv
+ ${TEST_SSH_SSHKEYGEN} -if ${.OBJDIR}/rsa_ssh2_cr.prv | diff - ${.CURDIR}/rsa_openssh.prv
+ awk '{print $$0 "\r"}' ${.CURDIR}/rsa_ssh2.prv > ${.OBJDIR}/rsa_ssh2_crnl.prv
+ ${TEST_SSH_SSHKEYGEN} -if ${.OBJDIR}/rsa_ssh2_crnl.prv | diff - ${.CURDIR}/rsa_openssh.prv
+
+t2:
+ cat ${.CURDIR}/rsa_openssh.prv > $(OBJ)/t2.out
+ chmod 600 $(OBJ)/t2.out
+ ${TEST_SSH_SSHKEYGEN} -yf $(OBJ)/t2.out | diff - ${.CURDIR}/rsa_openssh.pub
+
+t3:
+ ${TEST_SSH_SSHKEYGEN} -ef ${.CURDIR}/rsa_openssh.pub >$(OBJ)/t3.out
+ ${TEST_SSH_SSHKEYGEN} -if $(OBJ)/t3.out | diff - ${.CURDIR}/rsa_openssh.pub
+
+t4:
+ ${TEST_SSH_SSHKEYGEN} -E md5 -lf ${.CURDIR}/rsa_openssh.pub |\
+ awk '{print $$2}' | diff - ${.CURDIR}/t4.ok
+
+t5:
+ ${TEST_SSH_SSHKEYGEN} -Bf ${.CURDIR}/rsa_openssh.pub |\
+ awk '{print $$2}' | diff - ${.CURDIR}/t5.ok
+
+t6:
+ ${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/dsa_ssh2.prv > $(OBJ)/t6.out1
+ ${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/dsa_ssh2.pub > $(OBJ)/t6.out2
+ chmod 600 $(OBJ)/t6.out1
+ ${TEST_SSH_SSHKEYGEN} -yf $(OBJ)/t6.out1 | diff - $(OBJ)/t6.out2
+
+$(OBJ)/t7.out:
+ ${TEST_SSH_SSHKEYGEN} -q -t rsa -N '' -f $@
+
+t7: $(OBJ)/t7.out
+ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t7.out > /dev/null
+ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t7.out > /dev/null
+
+$(OBJ)/t8.out:
+ ${TEST_SSH_SSHKEYGEN} -q -t dsa -N '' -f $@
+
+t8: $(OBJ)/t8.out
+ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t8.out > /dev/null
+ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t8.out > /dev/null
+
+$(OBJ)/t9.out:
+ test "${TEST_SSH_ECC}" != yes || \
+ ${TEST_SSH_SSHKEYGEN} -q -t ecdsa -N '' -f $@
+
+t9: $(OBJ)/t9.out
+ test "${TEST_SSH_ECC}" != yes || \
+ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t9.out > /dev/null
+ test "${TEST_SSH_ECC}" != yes || \
+ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t9.out > /dev/null
+
+
+$(OBJ)/t10.out:
+ ${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -f $@
+
+t10: $(OBJ)/t10.out
+ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t10.out > /dev/null
+ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t10.out > /dev/null
+
+t11:
+ ${TEST_SSH_SSHKEYGEN} -E sha256 -lf ${.CURDIR}/rsa_openssh.pub |\
+ awk '{print $$2}' | diff - ${.CURDIR}/t11.ok
+
+$(OBJ)/t12.out:
+ ${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -C 'test-comment-1234' -f $@
+
+t12: $(OBJ)/t12.out
+ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t12.out.pub | grep test-comment-1234 >/dev/null
+
+t-exec: ${LTESTS:=.sh}
+ @if [ "x$?" = "x" ]; then exit 0; fi; \
+ for TEST in ""$?; do \
+ skip=no; \
+ for t in ""$${SKIP_LTESTS}; do \
+ if [ "x$${t}.sh" = "x$${TEST}" ]; then skip=yes; fi; \
+ done; \
+ if [ "x$${skip}" = "xno" ]; then \
+ echo "run test $${TEST}" ... 1>&2; \
+ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \
+ else \
+ echo skip test $${TEST} 1>&2; \
+ fi; \
+ done
+
+t-exec-interop: ${INTEROP_TESTS:=.sh}
+ @if [ "x$?" = "x" ]; then exit 0; fi; \
+ for TEST in ""$?; do \
+ echo "run test $${TEST}" ... 1>&2; \
+ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \
+ done
+
+t-extra: ${EXTRA_TESTS:=.sh}
+ @if [ "x$?" = "x" ]; then exit 0; fi; \
+ for TEST in ""$?; do \
+ echo "run test $${TEST}" ... 1>&2; \
+ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \
+ done
+
+# Not run by default
+interop: ${INTEROP_TARGETS}
+
+# Unit tests, built by top-level Makefile
+unit:
+ set -e ; if test -z "${SKIP_UNIT}" ; then \
+ V="" ; \
+ test "x${USE_VALGRIND}" = "x" || \
+ V=${.CURDIR}/valgrind-unit.sh ; \
+ $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \
+ $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \
+ -d ${.CURDIR}/unittests/sshkey/testdata ; \
+ $$V ${.OBJDIR}/unittests/bitmap/test_bitmap ; \
+ $$V ${.OBJDIR}/unittests/conversion/test_conversion ; \
+ $$V ${.OBJDIR}/unittests/kex/test_kex ; \
+ $$V ${.OBJDIR}/unittests/hostkeys/test_hostkeys \
+ -d ${.CURDIR}/unittests/hostkeys/testdata ; \
+ $$V ${.OBJDIR}/unittests/match/test_match ; \
+ if test "x${TEST_SSH_UTF8}" = "xyes" ; then \
+ $$V ${.OBJDIR}/unittests/utf8/test_utf8 ; \
+ fi \
+ fi
diff --git a/regress/README.regress b/regress/README.regress
new file mode 100644
index 00000000..ac2e8487
--- /dev/null
+++ b/regress/README.regress
@@ -0,0 +1,161 @@
+Overview.
+
+$ ./configure && make tests
+
+You'll see some progress info. A failure will cause either the make to
+abort or the driver script to report a "FATAL" failure.
+
+The test consists of 2 parts. The first is the file-based tests which is
+driven by the Makefile, and the second is a set of network or proxycommand
+based tests, which are driven by a driver script (test-exec.sh) which is
+called multiple times by the Makefile.
+
+Failures in the first part will cause the Makefile to return an error.
+Failures in the second part will print a "FATAL" message for the failed
+test and continue.
+
+OpenBSD has a system-wide regression test suite. OpenSSH Portable's test
+suite is based on OpenBSD's with modifications.
+
+
+Environment variables.
+
+SKIP_UNIT: Skip unit tests.
+SUDO: path to sudo/doas command, if desired. Note that some systems
+ (notably systems using PAM) require sudo to execute some tests.
+LTESTS: Whitespace separated list of tests (filenames without the .sh
+ extension) to run.
+SKIP_LTESTS: Whitespace separated list of tests to skip.
+OBJ: used by test scripts to access build dir.
+TEST_SHELL: shell used for running the test scripts.
+TEST_SSH_FAIL_FATAL: set to "yes" to make any failure abort the test
+ currently in progress.
+TEST_SSH_PORT: TCP port to be used for the listening tests.
+TEST_SSH_QUIET: set to "yes" to suppress non-fatal output.
+TEST_SSH_SSHD_CONFOPTS: Configuration directives to be added to sshd_config
+ before running each test.
+TEST_SSH_SSH_CONFOPTS: Configuration directives to be added to
+ ssh_config before running each test.
+TEST_SSH_TRACE: set to "yes" for verbose output from tests
+TEST_SSH_x: path to "ssh" command under test, where x is one of
+ SSH, SSHD, SSHAGENT, SSHADD, SSHKEYGEN, SSHKEYSCAN, SFTP or
+ SFTPSERVER
+USE_VALGRIND: Run the tests under valgrind memory checker.
+
+
+Individual tests.
+
+You can run an individual test from the top-level Makefile, eg:
+$ make tests LTESTS=agent-timeout
+
+If you need to manipulate the environment more you can invoke test-exec.sh
+directly if you set up the path to find the binaries under test and the
+test scripts themselves, for example:
+
+$ cd regress
+$ PATH=`pwd`/..:$PATH:. TEST_SHELL=/bin/sh sh test-exec.sh `pwd` \
+ agent-timeout.sh
+ok agent timeout test
+
+
+Files.
+
+test-exec.sh: the main test driver. Sets environment, creates config files
+and keys and runs the specified test.
+
+At the time of writing, the individual tests are:
+connect.sh: simple connect
+proxy-connect.sh: proxy connect
+connect-privsep.sh: proxy connect with privsep
+connect-uri.sh: uri connect
+proto-version.sh: sshd version with different protocol combinations
+proto-mismatch.sh: protocol version mismatch
+exit-status.sh: remote exit status
+envpass.sh: environment passing
+transfer.sh: transfer data
+banner.sh: banner
+rekey.sh: rekey
+stderr-data.sh: stderr data transfer
+stderr-after-eof.sh: stderr data after eof
+broken-pipe.sh: broken pipe test
+try-ciphers.sh: try ciphers
+yes-head.sh: yes pipe head
+login-timeout.sh: connect after login grace timeout
+agent.sh: simple connect via agent
+agent-getpeereid.sh: disallow agent attach from other uid
+agent-timeout.sh: agent timeout test
+agent-ptrace.sh: disallow agent ptrace attach
+keyscan.sh: keyscan
+keygen-change.sh: change passphrase for key
+keygen-convert.sh: convert keys
+keygen-moduli.sh: keygen moduli
+key-options.sh: key options
+scp.sh: scp
+scp-uri.sh: scp-uri
+sftp.sh: basic sftp put/get
+sftp-chroot.sh: sftp in chroot
+sftp-cmds.sh: sftp command
+sftp-badcmds.sh: sftp invalid commands
+sftp-batch.sh: sftp batchfile
+sftp-glob.sh: sftp glob
+sftp-perm.sh: sftp permissions
+sftp-uri.sh: sftp-uri
+ssh-com-client.sh: connect with ssh.com client
+ssh-com-keygen.sh: ssh.com key import
+ssh-com-sftp.sh: basic sftp put/get with ssh.com server
+ssh-com.sh: connect to ssh.com server
+reconfigure.sh: simple connect after reconfigure
+dynamic-forward.sh: dynamic forwarding
+forwarding.sh: local and remote forwarding
+multiplex.sh: connection multiplexing
+reexec.sh: reexec tests
+brokenkeys.sh: broken keys
+sshcfgparse.sh: ssh config parse
+cfgparse.sh: sshd config parse
+cfgmatch.sh: sshd_config match
+cfgmatchlisten.sh: sshd_config matchlisten
+addrmatch.sh: address match
+localcommand.sh: localcommand
+forcecommand.sh: forced command
+portnum.sh: port number parsing
+keytype.sh: login with different key types
+kextype.sh: login with different key exchange algorithms
+cert-hostkey.sh certified host keys
+cert-userkey.sh: certified user keys
+host-expand.sh: expand %h and %n
+keys-command.sh: authorized keys from command
+forward-control.sh: sshd control of local and remote forwarding
+integrity.sh: integrity
+krl.sh: key revocation lists
+multipubkey.sh: multiple pubkey
+limit-keytype.sh: restrict pubkey type
+hostkey-agent.sh: hostkey agent
+keygen-knownhosts.sh: ssh-keygen known_hosts
+hostkey-rotate.sh: hostkey rotate
+principals-command.sh: authorized principals command
+cert-file.sh: ssh with certificates
+cfginclude.sh: config include
+allow-deny-users.sh: AllowUsers/DenyUsers
+authinfo.sh: authinfo
+
+
+Problems?
+
+Run the failing test with shell tracing (-x) turned on:
+$ PATH=`pwd`/..:$PATH:. sh -x test-exec.sh `pwd` agent-timeout.sh
+
+Failed tests can be difficult to diagnose. Suggestions:
+- run the individual test via ./test-exec.sh `pwd` [testname]
+- set LogLevel to VERBOSE in test-exec.sh and enable syslogging of
+ auth.debug (eg to /var/log/authlog).
+
+
+Known Issues.
+
+- Similarly, if you do not have "scp" in your system's $PATH then the
+ multiplex scp tests will fail (since the system's shell startup scripts
+ will determine where the shell started by sshd will look for scp).
+
+- Recent GNU coreutils deprecate "head -[n]": this will cause the yes-head
+ test to fail. The old behaviour can be restored by setting (and
+ exporting) _POSIX2_VERSION=199209 before running the tests.
diff --git a/regress/addrmatch.sh b/regress/addrmatch.sh
new file mode 100644
index 00000000..e7d29c3f
--- /dev/null
+++ b/regress/addrmatch.sh
@@ -0,0 +1,56 @@
+# $OpenBSD: addrmatch.sh,v 1.5 2020/03/13 03:18:45 djm Exp $
+# Placed in the Public Domain.
+
+tid="address match"
+
+mv $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+
+run_trial()
+{
+ user="$1"; addr="$2"; host="$3"; laddr="$4"; lport="$5"
+ expected="$6"; descr="$7"
+
+ verbose "test $descr for $user $addr $host"
+ result=`${SSHD} -f $OBJ/sshd_proxy -T \
+ -C user=${user},addr=${addr},host=${host},laddr=${laddr},lport=${lport} | \
+ awk '/^forcecommand/ {print $2}'`
+ if [ "$result" != "$expected" ]; then
+ fail "failed '$descr' expected $expected got $result"
+ fi
+}
+
+cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+cat >>$OBJ/sshd_proxy <<EOD
+ForceCommand nomatch
+Match Address 192.168.0.0/16,!192.168.30.0/24,10.0.0.0/8,host.example.com
+ ForceCommand match1
+Match Address 1.1.1.1,::1,!::3,2000::/16
+ ForceCommand match2
+Match LocalAddress 127.0.0.1,::1
+ ForceCommand match3
+Match LocalPort 5678
+ ForceCommand match4
+EOD
+
+run_trial user 192.168.0.1 somehost 1.2.3.4 1234 match1 "first entry"
+run_trial user 192.168.30.1 somehost 1.2.3.4 1234 nomatch "negative match"
+run_trial user 19.0.0.1 somehost 1.2.3.4 1234 nomatch "no match"
+run_trial user 10.255.255.254 somehost 1.2.3.4 1234 match1 "list middle"
+run_trial user 192.168.30.1 192.168.0.1 1.2.3.4 1234 nomatch "faked IP in hostname"
+run_trial user 1.1.1.1 somehost.example.com 1.2.3.4 1234 match2 "bare IP4 address"
+run_trial user 19.0.0.1 somehost 127.0.0.1 1234 match3 "localaddress"
+run_trial user 19.0.0.1 somehost 1.2.3.4 5678 match4 "localport"
+
+if test "$TEST_SSH_IPV6" != "no"; then
+run_trial user ::1 somehost.example.com ::2 1234 match2 "bare IP6 address"
+run_trial user ::2 somehost.example.com ::2 1234 nomatch "deny IPv6"
+run_trial user ::3 somehost ::2 1234 nomatch "IP6 negated"
+run_trial user ::4 somehost ::2 1234 nomatch "IP6 no match"
+run_trial user 2000::1 somehost ::2 1234 match2 "IP6 network"
+run_trial user 2001::1 somehost ::2 1234 nomatch "IP6 network"
+run_trial user ::5 somehost ::1 1234 match3 "IP6 localaddress"
+run_trial user ::5 somehost ::2 5678 match4 "IP6 localport"
+fi
+
+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
new file mode 100644
index 00000000..52434081
--- /dev/null
+++ b/regress/agent-getpeereid.sh
@@ -0,0 +1,57 @@
+# $OpenBSD: agent-getpeereid.sh,v 1.11 2019/11/26 23:43:10 djm Exp $
+# Placed in the Public Domain.
+
+tid="disallow agent attach from other uid"
+
+UNPRIV=nobody
+ASOCK=${OBJ}/agent
+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
+fi
+case "x$SUDO" in
+ xsudo) sudo=1;;
+ xdoas) ;;
+ x)
+ echo "need SUDO to switch to uid $UNPRIV"
+ echo SKIPPED
+ exit 0 ;;
+ *)
+ echo "unsupported $SUDO - "doas" and "sudo" are allowed"
+ exit 0 ;;
+esac
+
+trace "start agent"
+eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s -a ${ASOCK}` > /dev/null
+r=$?
+if [ $r -ne 0 ]; then
+ fail "could not start ssh-agent: exit code $r"
+else
+ chmod 644 ${SSH_AUTH_SOCK}
+
+ ${SSHADD} -l > /dev/null 2>&1
+ r=$?
+ if [ $r -ne 1 ]; then
+ fail "ssh-add failed with $r != 1"
+ fi
+ if test -z "$sudo" ; then
+ # doas
+ ${SUDO} -n -u ${UNPRIV} ${SSHADD} -l 2>/dev/null
+ else
+ # sudo
+ < /dev/null ${SUDO} -S -u ${UNPRIV} ${SSHADD} -l 2>/dev/null
+ fi
+ r=$?
+ if [ $r -lt 2 ]; then
+ fail "ssh-add did not fail for ${UNPRIV}: $r < 2"
+ fi
+
+ trace "kill agent"
+ ${SSHAGENT} -k > /dev/null
+fi
+
+rm -f ${OBJ}/agent
diff --git a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh
new file mode 100644
index 00000000..fbbaea51
--- /dev/null
+++ b/regress/agent-pkcs11.sh
@@ -0,0 +1,124 @@
+# $OpenBSD: agent-pkcs11.sh,v 1.7 2019/11/26 23:43:10 djm Exp $
+# Placed in the Public Domain.
+
+tid="pkcs11 agent test"
+
+try_token_libs() {
+ for _lib in "$@" ; do
+ if test -f "$_lib" ; then
+ verbose "Using token library $_lib"
+ TEST_SSH_PKCS11="$_lib"
+ return
+ fi
+ done
+ echo "skipped: Unable to find PKCS#11 token library"
+ exit 0
+}
+
+try_token_libs \
+ /usr/local/lib/softhsm/libsofthsm2.so \
+ /usr/lib64/pkcs11/libsofthsm2.so \
+ /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so
+
+TEST_SSH_PIN=1234
+TEST_SSH_SOPIN=12345678
+if [ "x$TEST_SSH_SSHPKCS11HELPER" != "x" ]; then
+ SSH_PKCS11_HELPER="${TEST_SSH_SSHPKCS11HELPER}"
+ export SSH_PKCS11_HELPER
+fi
+
+test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist"
+
+# setup environment for softhsm2 token
+DIR=$OBJ/SOFTHSM
+rm -rf $DIR
+TOKEN=$DIR/tokendir
+mkdir -p $TOKEN
+SOFTHSM2_CONF=$DIR/softhsm2.conf
+export SOFTHSM2_CONF
+cat > $SOFTHSM2_CONF << EOF
+# SoftHSM v2 configuration file
+directories.tokendir = ${TOKEN}
+objectstore.backend = file
+# ERROR, WARNING, INFO, DEBUG
+log.level = DEBUG
+# If CKF_REMOVABLE_DEVICE flag should be set
+slots.removable = false
+EOF
+out=$(softhsm2-util --init-token --free --label token-slot-0 --pin "$TEST_SSH_PIN" --so-pin "$TEST_SSH_SOPIN")
+slot=$(echo -- $out | sed 's/.* //')
+
+# prevent ssh-agent from calling ssh-askpass
+SSH_ASKPASS=/usr/bin/true
+export SSH_ASKPASS
+unset DISPLAY
+
+# start command w/o tty, so ssh-add accepts pin from stdin
+notty() {
+ perl -e 'use POSIX; POSIX::setsid();
+ if (fork) { wait; exit($? >> 8); } else { exec(@ARGV) }' "$@"
+}
+
+trace "generating keys"
+RSA=${DIR}/RSA
+EC=${DIR}/EC
+openssl genpkey -algorithm rsa > $RSA
+openssl pkcs8 -nocrypt -in $RSA |\
+ softhsm2-util --slot "$slot" --label 01 --id 01 --pin "$TEST_SSH_PIN" --import /dev/stdin
+openssl genpkey \
+ -genparam \
+ -algorithm ec \
+ -pkeyopt ec_paramgen_curve:prime256v1 |\
+ openssl genpkey \
+ -paramfile /dev/stdin > $EC
+openssl pkcs8 -nocrypt -in $EC |\
+ softhsm2-util --slot "$slot" --label 02 --id 02 --pin "$TEST_SSH_PIN" --import /dev/stdin
+
+trace "start agent"
+eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null
+r=$?
+if [ $r -ne 0 ]; then
+ fail "could not start ssh-agent: exit code $r"
+else
+ trace "add pkcs11 key to agent"
+ echo ${TEST_SSH_PIN} | notty ${SSHADD} -s ${TEST_SSH_PKCS11} > /dev/null 2>&1
+ r=$?
+ if [ $r -ne 0 ]; then
+ fail "ssh-add -s failed: exit code $r"
+ fi
+
+ trace "pkcs11 list via agent"
+ ${SSHADD} -l > /dev/null 2>&1
+ r=$?
+ if [ $r -ne 0 ]; then
+ fail "ssh-add -l failed: exit code $r"
+ fi
+
+ for k in $RSA $EC; do
+ trace "testing $k"
+ chmod 600 $k
+ ssh-keygen -y -f $k > $k.pub
+ pub=$(cat $k.pub)
+ ${SSHADD} -L | grep -q "$pub" || fail "key $k missing in ssh-add -L"
+ ${SSHADD} -T $k.pub || fail "ssh-add -T with $k failed"
+
+ # add to authorized keys
+ cat $k.pub > $OBJ/authorized_keys_$USER
+ trace "pkcs11 connect via agent ($k)"
+ ${SSH} -F $OBJ/ssh_proxy somehost exit 5
+ r=$?
+ if [ $r -ne 5 ]; then
+ fail "ssh connect failed (exit code $r)"
+ fi
+ done
+
+ trace "remove pkcs11 keys"
+ echo ${TEST_SSH_PIN} | notty ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1
+ r=$?
+ if [ $r -ne 0 ]; then
+ fail "ssh-add -e failed: exit code $r"
+ fi
+
+ trace "kill agent"
+ ${SSHAGENT} -k > /dev/null
+fi
diff --git a/regress/agent-ptrace.sh b/regress/agent-ptrace.sh
new file mode 100644
index 00000000..9cd68d7e
--- /dev/null
+++ b/regress/agent-ptrace.sh
@@ -0,0 +1,66 @@
+# $OpenBSD: agent-ptrace.sh,v 1.3 2015/09/11 04:55:01 djm Exp $
+# Placed in the Public Domain.
+
+tid="disallow agent ptrace attach"
+
+if have_prog uname ; then
+ case `uname` in
+ AIX|CYGWIN*|OSF1)
+ echo "skipped (not supported on this platform)"
+ exit 0
+ ;;
+ esac
+fi
+
+if [ "x$USER" = "xroot" ]; then
+ echo "Skipped: running as root"
+ exit 0
+fi
+
+if have_prog gdb ; then
+ : ok
+else
+ echo "skipped (gdb not found)"
+ exit 0
+fi
+
+if $OBJ/setuid-allowed ${SSHAGENT} ; then
+ : ok
+else
+ echo "skipped (${SSHAGENT} is mounted on a no-setuid filesystem)"
+ exit 0
+fi
+
+if test -z "$SUDO" ; then
+ echo "skipped (SUDO not set)"
+ exit 0
+else
+ $SUDO chown 0 ${SSHAGENT}
+ $SUDO chgrp 0 ${SSHAGENT}
+ $SUDO chmod 2755 ${SSHAGENT}
+fi
+
+trace "start agent"
+eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null
+r=$?
+if [ $r -ne 0 ]; then
+ fail "could not start ssh-agent: exit code $r"
+else
+ # ls -l ${SSH_AUTH_SOCK}
+ gdb ${SSHAGENT} ${SSH_AGENT_PID} > ${OBJ}/gdb.out 2>&1 << EOF
+ quit
+EOF
+ r=$?
+ if [ $r -ne 0 ]; then
+ fail "gdb failed: exit code $r"
+ fi
+ egrep 'ptrace: Operation not permitted.|procfs:.*Permission denied.|ttrace.*Permission denied.|procfs:.*: Invalid argument.|Unable to access task ' >/dev/null ${OBJ}/gdb.out
+ r=$?
+ rm -f ${OBJ}/gdb.out
+ if [ $r -ne 0 ]; then
+ fail "ptrace succeeded?: exit code $r"
+ fi
+
+ trace "kill agent"
+ ${SSHAGENT} -k > /dev/null
+fi
diff --git a/regress/agent-timeout.sh b/regress/agent-timeout.sh
new file mode 100644
index 00000000..6dec0928
--- /dev/null
+++ b/regress/agent-timeout.sh
@@ -0,0 +1,38 @@
+# $OpenBSD: agent-timeout.sh,v 1.6 2019/11/26 23:43:10 djm Exp $
+# Placed in the Public Domain.
+
+tid="agent timeout test"
+
+SSHAGENT_TIMEOUT=10
+
+trace "start agent"
+eval `${SSHAGENT} -s ${EXTRA_AGENT_ARGS}` > /dev/null
+r=$?
+if [ $r -ne 0 ]; then
+ fail "could not start ssh-agent: exit code $r"
+else
+ trace "add keys with timeout"
+ keys=0
+ for t in ${SSH_KEYTYPES}; do
+ ${SSHADD} -kt ${SSHAGENT_TIMEOUT} $OBJ/$t > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ fail "ssh-add did succeed exit code 0"
+ fi
+ keys=$((${keys} + 1))
+ done
+ n=`${SSHADD} -l 2> /dev/null | wc -l`
+ trace "agent has $n keys"
+ if [ $n -ne $keys ]; then
+ fail "ssh-add -l did not return $keys keys: $n"
+ fi
+ trace "sleeping 2*${SSHAGENT_TIMEOUT} seconds"
+ sleep ${SSHAGENT_TIMEOUT}
+ sleep ${SSHAGENT_TIMEOUT}
+ ${SSHADD} -l 2> /dev/null | grep 'The agent has no identities.' >/dev/null
+ if [ $? -ne 0 ]; then
+ fail "ssh-add -l still returns keys after timeout"
+ fi
+
+ trace "kill agent"
+ ${SSHAGENT} -k > /dev/null
+fi
diff --git a/regress/agent.sh b/regress/agent.sh
new file mode 100644
index 00000000..39403653
--- /dev/null
+++ b/regress/agent.sh
@@ -0,0 +1,164 @@
+# $OpenBSD: agent.sh,v 1.17 2019/12/21 02:33:07 djm Exp $
+# Placed in the Public Domain.
+
+tid="simple agent test"
+
+SSH_AUTH_SOCK=/nonexistent ${SSHADD} -l > /dev/null 2>&1
+if [ $? -ne 2 ]; then
+ fail "ssh-add -l did not fail with exit code 2"
+fi
+
+trace "start agent, args ${EXTRA_AGENT_ARGS} -s"
+eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null
+r=$?
+if [ $r -ne 0 ]; then
+ fatal "could not start ssh-agent: exit code $r"
+fi
+
+eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s | sed 's/SSH_/FW_SSH_/g'` > /dev/null
+r=$?
+if [ $r -ne 0 ]; then
+ fatal "could not start second ssh-agent: exit code $r"
+fi
+
+${SSHADD} -l > /dev/null 2>&1
+if [ $? -ne 1 ]; then
+ fail "ssh-add -l did not fail with exit code 1"
+fi
+
+rm -f $OBJ/user_ca_key $OBJ/user_ca_key.pub
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key \
+ || fatal "ssh-keygen failed"
+
+trace "overwrite authorized keys"
+printf '' > $OBJ/authorized_keys_$USER
+
+for t in ${SSH_KEYTYPES}; do
+ # generate user key for agent
+ rm -f $OBJ/$t-agent $OBJ/$t-agent.pub*
+ ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t-agent ||\
+ fatal "ssh-keygen for $t-agent failed"
+ # Make a certificate for each too.
+ ${SSHKEYGEN} -qs $OBJ/user_ca_key -I "$t cert" \
+ -n estragon $OBJ/$t-agent.pub || fatal "ca sign failed"
+
+ # add to authorized keys
+ cat $OBJ/$t-agent.pub >> $OBJ/authorized_keys_$USER
+ # add private key to agent
+ ${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
+ 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
+done
+
+# Remove explicit identity directives from ssh_proxy
+mv $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
+grep -vi identityfile $OBJ/ssh_proxy_bak > $OBJ/ssh_proxy
+
+${SSHADD} -l > /dev/null 2>&1
+r=$?
+if [ $r -ne 0 ]; then
+ fail "ssh-add -l failed: exit code $r"
+fi
+# the same for full pubkey output
+${SSHADD} -L > /dev/null 2>&1
+r=$?
+if [ $r -ne 0 ]; then
+ fail "ssh-add -L failed: exit code $r"
+fi
+
+trace "simple connect via agent"
+${SSH} -F $OBJ/ssh_proxy somehost exit 52
+r=$?
+if [ $r -ne 52 ]; then
+ fail "ssh connect with failed (exit code $r)"
+fi
+
+for t in ${SSH_KEYTYPES}; do
+ trace "connect via agent using $t key"
+ if [ "$t" = "ssh-dss" ]; then
+ echo "PubkeyAcceptedKeyTypes +ssh-dss" >> $OBJ/ssh_proxy
+ echo "PubkeyAcceptedKeyTypes +ssh-dss" >> $OBJ/sshd_proxy
+ fi
+ ${SSH} -F $OBJ/ssh_proxy -i $OBJ/$t-agent.pub -oIdentitiesOnly=yes \
+ somehost exit 52
+ r=$?
+ if [ $r -ne 52 ]; then
+ fail "ssh connect with failed (exit code $r)"
+ fi
+done
+
+trace "agent forwarding"
+${SSH} -A -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1
+r=$?
+if [ $r -ne 0 ]; then
+ fail "ssh-add -l via agent fwd failed (exit code $r)"
+fi
+${SSH} "-oForwardAgent=$SSH_AUTH_SOCK" -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1
+r=$?
+if [ $r -ne 0 ]; then
+ fail "ssh-add -l via agent path fwd failed (exit code $r)"
+fi
+${SSH} -A -F $OBJ/ssh_proxy somehost \
+ "${SSH} -F $OBJ/ssh_proxy somehost exit 52"
+r=$?
+if [ $r -ne 52 ]; then
+ fail "agent fwd failed (exit code $r)"
+fi
+
+trace "agent forwarding different agent"
+${SSH} "-oForwardAgent=$FW_SSH_AUTH_SOCK" -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1
+r=$?
+if [ $r -ne 0 ]; then
+ fail "ssh-add -l via agent path fwd of different agent failed (exit code $r)"
+fi
+${SSH} '-oForwardAgent=$FW_SSH_AUTH_SOCK' -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1
+r=$?
+if [ $r -ne 0 ]; then
+ fail "ssh-add -l via agent path env fwd of different agent failed (exit code $r)"
+fi
+
+# Remove keys from forwarded agent, ssh-add on remote machine should now fail.
+SSH_AUTH_SOCK=$FW_SSH_AUTH_SOCK ${SSHADD} -D > /dev/null 2>&1
+r=$?
+if [ $r -ne 0 ]; then
+ fail "ssh-add -D failed: exit code $r"
+fi
+${SSH} '-oForwardAgent=$FW_SSH_AUTH_SOCK' -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1
+r=$?
+if [ $r -ne 1 ]; then
+ fail "ssh-add -l with different agent did not fail with exit code 1 (exit code $r)"
+fi
+
+(printf 'cert-authority,principals="estragon" '; cat $OBJ/user_ca_key.pub) \
+ > $OBJ/authorized_keys_$USER
+for t in ${SSH_KEYTYPES}; do
+ if [ "$t" != "ssh-dss" ]; then
+ trace "connect via agent using $t key"
+ ${SSH} -F $OBJ/ssh_proxy -i $OBJ/$t-agent.pub \
+ -oCertificateFile=$OBJ/$t-agent-cert.pub \
+ -oIdentitiesOnly=yes somehost exit 52
+ r=$?
+ if [ $r -ne 52 ]; then
+ fail "ssh connect with failed (exit code $r)"
+ fi
+ fi
+done
+
+trace "delete all agent keys"
+${SSHADD} -D > /dev/null 2>&1
+r=$?
+if [ $r -ne 0 ]; then
+ fail "ssh-add -D failed: exit code $r"
+fi
+
+trace "kill agent"
+${SSHAGENT} -k > /dev/null
+SSH_AGENT_PID=$FW_SSH_AGENT_PID ${SSHAGENT} -k > /dev/null
diff --git a/regress/allow-deny-users.sh b/regress/allow-deny-users.sh
new file mode 100644
index 00000000..5c389512
--- /dev/null
+++ b/regress/allow-deny-users.sh
@@ -0,0 +1,45 @@
+# Public Domain
+# Zev Weiss, 2016
+# $OpenBSD: allow-deny-users.sh,v 1.5 2018/07/13 02:13:50 djm Exp $
+
+tid="AllowUsers/DenyUsers"
+
+me="$LOGNAME"
+if [ "x$me" = "x" ]; then
+ me=`whoami`
+fi
+other="nobody"
+
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
+
+test_auth()
+{
+ deny="$1"
+ allow="$2"
+ should_succeed="$3"
+ 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"
+
+ ${SSH} -F $OBJ/ssh_proxy "$me@somehost" true
+ status=$?
+
+ if (test $status -eq 0 && ! $should_succeed) \
+ || (test $status -ne 0 && $should_succeed); then
+ fail "$failmsg"
+ fi
+}
+
+# DenyUsers AllowUsers should_succeed failure_message
+test_auth "" "" true "user in neither DenyUsers nor AllowUsers denied"
+test_auth "$other $me" "" false "user in DenyUsers allowed"
+test_auth "$me $other" "" false "user in DenyUsers allowed"
+test_auth "" "$other" false "user not in AllowUsers allowed"
+test_auth "" "$other $me" true "user in AllowUsers denied"
+test_auth "" "$me $other" true "user in AllowUsers denied"
+test_auth "$me $other" "$me $other" false "user in both DenyUsers and AllowUsers allowed"
+test_auth "$other $me" "$other $me" false "user in both DenyUsers and AllowUsers allowed"
diff --git a/regress/authinfo.sh b/regress/authinfo.sh
new file mode 100644
index 00000000..693424af
--- /dev/null
+++ b/regress/authinfo.sh
@@ -0,0 +1,17 @@
+# $OpenBSD: authinfo.sh,v 1.3 2018/04/10 00:13:27 djm Exp $
+# Placed in the Public Domain.
+
+tid="authinfo"
+
+# Ensure the environment variable doesn't leak when ExposeAuthInfo=no.
+verbose "ExposeAuthInfo=no"
+env SSH_USER_AUTH=blah ${SSH} -F $OBJ/ssh_proxy x \
+ 'env | grep SSH_USER_AUTH >/dev/null' && fail "SSH_USER_AUTH present"
+
+verbose "ExposeAuthInfo=yes"
+echo ExposeAuthInfo=yes >> $OBJ/sshd_proxy
+${SSH} -F $OBJ/ssh_proxy x \
+ 'grep ^publickey "$SSH_USER_AUTH" /dev/null >/dev/null' ||
+ fail "ssh with ExposeAuthInfo failed"
+
+# XXX test multiple auth and key contents
diff --git a/regress/banner.sh b/regress/banner.sh
new file mode 100644
index 00000000..0d9654fe
--- /dev/null
+++ b/regress/banner.sh
@@ -0,0 +1,44 @@
+# $OpenBSD: banner.sh,v 1.3 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="banner"
+echo "Banner $OBJ/banner.in" >> $OBJ/sshd_proxy
+
+rm -f $OBJ/banner.out $OBJ/banner.in $OBJ/empty.in
+touch $OBJ/empty.in
+
+trace "test missing banner file"
+verbose "test $tid: missing banner file"
+( ${SSH} -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \
+ cmp $OBJ/empty.in $OBJ/banner.out ) || \
+ fail "missing banner file"
+
+for s in 0 10 100 1000 10000 100000 ; do
+ if [ "$s" = "0" ]; then
+ # create empty banner
+ touch $OBJ/banner.in
+ elif [ "$s" = "10" ]; then
+ # create 10-byte banner file
+ echo "abcdefghi" >$OBJ/banner.in
+ else
+ # increase size 10x
+ cp $OBJ/banner.in $OBJ/banner.out
+ for i in 0 1 2 3 4 5 6 7 8 ; do
+ cat $OBJ/banner.out >> $OBJ/banner.in
+ done
+ fi
+
+ trace "test banner size $s"
+ verbose "test $tid: size $s"
+ ( ${SSH} -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \
+ cmp $OBJ/banner.in $OBJ/banner.out ) || \
+ fail "banner size $s mismatch"
+done
+
+trace "test suppress banner (-q)"
+verbose "test $tid: suppress banner (-q)"
+( ${SSH} -q -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \
+ cmp $OBJ/empty.in $OBJ/banner.out ) || \
+ fail "suppress banner (-q)"
+
+rm -f $OBJ/banner.out $OBJ/banner.in $OBJ/empty.in
diff --git a/regress/broken-pipe.sh b/regress/broken-pipe.sh
new file mode 100644
index 00000000..c69276e2
--- /dev/null
+++ b/regress/broken-pipe.sh
@@ -0,0 +1,12 @@
+# $OpenBSD: broken-pipe.sh,v 1.6 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="broken pipe test"
+
+for i in 1 2 3 4; do
+ ${SSH} -F $OBJ/ssh_config_config nexthost echo $i 2> /dev/null | true
+ r=$?
+ if [ $r -ne 0 ]; then
+ fail "broken pipe returns $r"
+ fi
+done
diff --git a/regress/brokenkeys.sh b/regress/brokenkeys.sh
new file mode 100644
index 00000000..9d5a54fa
--- /dev/null
+++ b/regress/brokenkeys.sh
@@ -0,0 +1,23 @@
+# $OpenBSD: brokenkeys.sh,v 1.2 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="broken keys"
+
+KEYS="$OBJ/authorized_keys_${USER}"
+
+start_sshd
+
+mv ${KEYS} ${KEYS}.bak
+
+# Truncated key
+echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEABTM= bad key" > $KEYS
+cat ${KEYS}.bak >> ${KEYS}
+cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+
+${SSH} -F $OBJ/ssh_config somehost true
+if [ $? -ne 0 ]; then
+ fail "ssh connect with failed"
+fi
+
+mv ${KEYS}.bak ${KEYS}
+
diff --git a/regress/cert-file.sh b/regress/cert-file.sh
new file mode 100644
index 00000000..94e672a9
--- /dev/null
+++ b/regress/cert-file.sh
@@ -0,0 +1,166 @@
+# $OpenBSD: cert-file.sh,v 1.8 2019/11/26 23:43:10 djm Exp $
+# Placed in the Public Domain.
+
+tid="ssh with certificates"
+
+rm -f $OBJ/user_ca_key* $OBJ/user_key*
+rm -f $OBJ/cert_user_key*
+
+# Create a CA key
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key1 ||\
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key2 ||\
+ fatal "ssh-keygen failed"
+
+# Make some keys and certificates.
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key1 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key2 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key3 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key4 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key5 || \
+ fatal "ssh-keygen failed"
+
+# Move the certificate to a different address to better control
+# when it is offered.
+${SSHKEYGEN} -q -s $OBJ/user_ca_key1 -I "regress user key for $USER" \
+ -z $$ -n ${USER} $OBJ/user_key1 ||
+ fatal "couldn't sign user_key1 with user_ca_key1"
+mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1_1.pub
+${SSHKEYGEN} -q -s $OBJ/user_ca_key2 -I "regress user key for $USER" \
+ -z $$ -n ${USER} $OBJ/user_key1 ||
+ fatal "couldn't sign user_key1 with user_ca_key2"
+mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1_2.pub
+${SSHKEYGEN} -q -s $OBJ/user_ca_key1 -I "regress user key for $USER" \
+ -z $$ -n ${USER} $OBJ/user_key3 ||
+ fatal "couldn't sign user_key3 with user_ca_key1"
+rm $OBJ/user_key3.pub # to test use of private key w/o public half.
+${SSHKEYGEN} -q -s $OBJ/user_ca_key1 -I "regress user key for $USER" \
+ -z $$ -n ${USER} $OBJ/user_key4 ||
+ fatal "couldn't sign user_key4 with user_ca_key1"
+rm $OBJ/user_key4 $OBJ/user_key4.pub # to test no matching pub/private key case.
+
+trace 'try with identity files'
+opts="-F $OBJ/ssh_proxy -oIdentitiesOnly=yes"
+opts2="$opts -i $OBJ/user_key1 -i $OBJ/user_key2"
+echo "cert-authority $(cat $OBJ/user_ca_key1.pub)" > $OBJ/authorized_keys_$USER
+
+# Make a clean config that doesn't have any pre-added identities.
+cat $OBJ/ssh_proxy | grep -v IdentityFile > $OBJ/no_identity_config
+
+# XXX: verify that certificate used was what we expect. Needs exposure of
+# keys via environment variable or similar.
+
+ # Key with no .pub should work - finding the equivalent *-cert.pub.
+verbose "identity cert with no plain public file"
+${SSH} -F $OBJ/no_identity_config -oIdentitiesOnly=yes \
+ -i $OBJ/user_key3 somehost exit 52
+[ $? -ne 52 ] && fail "ssh failed"
+
+# CertificateFile matching private key with no .pub file should work.
+verbose "CertificateFile with no plain public file"
+${SSH} -F $OBJ/no_identity_config -oIdentitiesOnly=yes \
+ -oCertificateFile=$OBJ/user_key3-cert.pub \
+ -i $OBJ/user_key3 somehost exit 52
+[ $? -ne 52 ] && fail "ssh failed"
+
+# Just keys should fail
+verbose "plain keys"
+${SSH} $opts2 somehost exit 52
+r=$?
+if [ $r -eq 52 ]; then
+ fail "ssh succeeded with no certs"
+fi
+
+# Keys with untrusted cert should fail.
+verbose "untrusted cert"
+opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_2.pub"
+${SSH} $opts3 somehost exit 52
+r=$?
+if [ $r -eq 52 ]; then
+ fail "ssh succeeded with bad cert"
+fi
+
+# Good cert with bad key should fail.
+verbose "good cert, bad key"
+opts3="$opts -i $OBJ/user_key2"
+opts3="$opts3 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
+${SSH} $opts3 somehost exit 52
+r=$?
+if [ $r -eq 52 ]; then
+ fail "ssh succeeded with no matching key"
+fi
+
+# Keys with one trusted cert, should succeed.
+verbose "single trusted"
+opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
+${SSH} $opts3 somehost exit 52
+r=$?
+if [ $r -ne 52 ]; then
+ fail "ssh failed with trusted cert and key"
+fi
+
+# Multiple certs and keys, with one trusted cert, should succeed.
+verbose "multiple trusted"
+opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_2.pub"
+opts3="$opts3 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
+${SSH} $opts3 somehost exit 52
+r=$?
+if [ $r -ne 52 ]; then
+ fail "ssh failed with multiple certs"
+fi
+
+#next, using an agent in combination with the keys
+SSH_AUTH_SOCK=/nonexistent ${SSHADD} -l > /dev/null 2>&1
+if [ $? -ne 2 ]; then
+ fatal "ssh-add -l did not fail with exit code 2"
+fi
+
+trace "start agent"
+eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null
+r=$?
+if [ $r -ne 0 ]; then
+ fatal "could not start ssh-agent: exit code $r"
+fi
+
+# add private keys to agent
+${SSHADD} -k $OBJ/user_key2 > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+ fatal "ssh-add did not succeed with exit code 0"
+fi
+${SSHADD} -k $OBJ/user_key1 > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+ fatal "ssh-add did not succeed with exit code 0"
+fi
+
+# try ssh with the agent and certificates
+opts="-F $OBJ/ssh_proxy"
+# with no certificates, should fail
+${SSH} $opts somehost exit 52
+if [ $? -eq 52 ]; then
+ fail "ssh connect with agent in succeeded with no cert"
+fi
+
+#with an untrusted certificate, should fail
+opts="$opts -oCertificateFile=$OBJ/cert_user_key1_2.pub"
+${SSH} $opts somehost exit 52
+if [ $? -eq 52 ]; then
+ fail "ssh connect with agent in succeeded with bad cert"
+fi
+
+#with an additional trusted certificate, should succeed
+opts="$opts -oCertificateFile=$OBJ/cert_user_key1_1.pub"
+${SSH} $opts somehost exit 52
+if [ $? -ne 52 ]; then
+ fail "ssh connect with agent in failed with good cert"
+fi
+
+trace "kill agent"
+${SSHAGENT} -k > /dev/null
+
+#cleanup
+rm -f $OBJ/user_ca_key* $OBJ/user_key*
+rm -f $OBJ/cert_user_key*
diff --git a/regress/cert-hostkey.sh b/regress/cert-hostkey.sh
new file mode 100644
index 00000000..097bf846
--- /dev/null
+++ b/regress/cert-hostkey.sh
@@ -0,0 +1,325 @@
+# $OpenBSD: cert-hostkey.sh,v 1.23 2020/01/03 03:02:26 djm Exp $
+# Placed in the Public Domain.
+
+tid="certified host keys"
+
+rm -f $OBJ/known_hosts-cert* $OBJ/host_ca_key* $OBJ/host_revoked_*
+rm -f $OBJ/cert_host_key* $OBJ/host_krl_*
+
+# Allow all hostkey/pubkey types, prefer certs for the client
+rsa=0
+types=""
+for i in `$SSH -Q key | maybe_filter_sk`; do
+ if [ -z "$types" ]; then
+ types="$i"
+ continue
+ fi
+ case "$i" in
+ # Special treatment for RSA keys.
+ *rsa*cert*)
+ types="rsa-sha2-256-cert-v01@openssh.com,$i,$types"
+ types="rsa-sha2-512-cert-v01@openssh.com,$types";;
+ *rsa*)
+ rsa=1
+ types="$types,rsa-sha2-512,rsa-sha2-256,$i";;
+ # Prefer certificate to plain keys.
+ *cert*) types="$i,$types";;
+ *) types="$types,$i";;
+ esac
+done
+(
+ echo "HostKeyAlgorithms ${types}"
+ echo "PubkeyAcceptedKeyTypes *"
+) >> $OBJ/ssh_proxy
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+(
+ echo "HostKeyAlgorithms *"
+ echo "PubkeyAcceptedKeyTypes *"
+) >> $OBJ/sshd_proxy_bak
+
+HOSTS='localhost-with-alias,127.0.0.1,::1'
+
+kh_ca() {
+ for k in "$@" ; do
+ printf "@cert-authority $HOSTS "
+ cat $OBJ/$k || fatal "couldn't cat $k"
+ done
+}
+kh_revoke() {
+ for k in "$@" ; do
+ printf "@revoked * "
+ cat $OBJ/$k || fatal "couldn't cat $k"
+ done
+}
+
+# Create a CA key and add it to known hosts. Ed25519 chosen for speed.
+# RSA for testing RSA/SHA2 signatures if supported.
+ktype2=ed25519
+[ "x$rsa" = "x1" ] && ktype2=rsa
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/host_ca_key ||\
+ fail "ssh-keygen of host_ca_key failed"
+${SSHKEYGEN} -q -N '' -t $ktype2 -f $OBJ/host_ca_key2 ||\
+ fail "ssh-keygen of host_ca_key failed"
+
+kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig
+cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
+
+# Plain text revocation files
+touch $OBJ/host_revoked_empty
+touch $OBJ/host_revoked_plain
+touch $OBJ/host_revoked_cert
+cat $OBJ/host_ca_key.pub $OBJ/host_ca_key2.pub > $OBJ/host_revoked_ca
+
+PLAIN_TYPES=`echo "$SSH_KEYTYPES" | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'`
+
+if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then
+ PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512"
+fi
+
+# Prepare certificate, plain key and CA KRLs
+${SSHKEYGEN} -kf $OBJ/host_krl_empty || fatal "KRL init failed"
+${SSHKEYGEN} -kf $OBJ/host_krl_plain || fatal "KRL init failed"
+${SSHKEYGEN} -kf $OBJ/host_krl_cert || fatal "KRL init failed"
+${SSHKEYGEN} -kf $OBJ/host_krl_ca $OBJ/host_ca_key.pub $OBJ/host_ca_key2.pub \
+ || fatal "KRL init failed"
+
+# Generate and sign host keys
+serial=1
+for ktype in $PLAIN_TYPES ; do
+ verbose "$tid: sign host ${ktype} cert"
+ # Generate and sign a host key
+ ${SSHKEYGEN} -q -N '' -t ${ktype} \
+ -f $OBJ/cert_host_key_${ktype} || \
+ fatal "ssh-keygen of cert_host_key_${ktype} failed"
+ ${SSHKEYGEN} -ukf $OBJ/host_krl_plain \
+ $OBJ/cert_host_key_${ktype}.pub || fatal "KRL update failed"
+ cat $OBJ/cert_host_key_${ktype}.pub >> $OBJ/host_revoked_plain
+ case $ktype in
+ rsa-sha2-*) tflag="-t $ktype"; ca="$OBJ/host_ca_key2" ;;
+ *) tflag=""; ca="$OBJ/host_ca_key" ;;
+ esac
+ ${SSHKEYGEN} -h -q -s $ca -z $serial $tflag \
+ -I "regress host key for $USER" \
+ -n $HOSTS $OBJ/cert_host_key_${ktype} ||
+ fatal "couldn't sign cert_host_key_${ktype}"
+ ${SSHKEYGEN} -ukf $OBJ/host_krl_cert \
+ $OBJ/cert_host_key_${ktype}-cert.pub || \
+ fatal "KRL update failed"
+ cat $OBJ/cert_host_key_${ktype}-cert.pub >> $OBJ/host_revoked_cert
+ serial=`expr $serial + 1`
+done
+
+attempt_connect() {
+ _ident="$1"
+ _expect_success="$2"
+ shift; shift
+ verbose "$tid: $_ident expect success $_expect_success"
+ cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
+ ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
+ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
+ "$@" -F $OBJ/ssh_proxy somehost true
+ _r=$?
+ if [ "x$_expect_success" = "xyes" ] ; then
+ if [ $_r -ne 0 ]; then
+ fail "ssh cert connect $_ident failed"
+ fi
+ else
+ if [ $_r -eq 0 ]; then
+ fail "ssh cert connect $_ident succeeded unexpectedly"
+ fi
+ fi
+}
+
+# Basic connect and revocation tests.
+for privsep in yes ; do
+ for ktype in $PLAIN_TYPES ; do
+ verbose "$tid: host ${ktype} cert connect privsep $privsep"
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo HostKey $OBJ/cert_host_key_${ktype}
+ echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
+ echo UsePrivilegeSeparation $privsep
+ ) > $OBJ/sshd_proxy
+
+ # test name expect success
+ attempt_connect "$ktype basic connect" "yes"
+ attempt_connect "$ktype empty KRL" "yes" \
+ -oRevokedHostKeys=$OBJ/host_krl_empty
+ attempt_connect "$ktype KRL w/ plain key revoked" "no" \
+ -oRevokedHostKeys=$OBJ/host_krl_plain
+ attempt_connect "$ktype KRL w/ cert revoked" "no" \
+ -oRevokedHostKeys=$OBJ/host_krl_cert
+ attempt_connect "$ktype KRL w/ CA revoked" "no" \
+ -oRevokedHostKeys=$OBJ/host_krl_ca
+ attempt_connect "$ktype empty plaintext revocation" "yes" \
+ -oRevokedHostKeys=$OBJ/host_revoked_empty
+ attempt_connect "$ktype plain key plaintext revocation" "no" \
+ -oRevokedHostKeys=$OBJ/host_revoked_plain
+ attempt_connect "$ktype cert plaintext revocation" "no" \
+ -oRevokedHostKeys=$OBJ/host_revoked_cert
+ attempt_connect "$ktype CA plaintext revocation" "no" \
+ -oRevokedHostKeys=$OBJ/host_revoked_ca
+ done
+done
+
+# Revoked certificates with key present
+kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig
+for ktype in $PLAIN_TYPES ; do
+ test -f "$OBJ/cert_host_key_${ktype}.pub" || fatal "no pubkey"
+ kh_revoke cert_host_key_${ktype}.pub >> $OBJ/known_hosts-cert.orig
+done
+cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
+for privsep in yes ; do
+ for ktype in $PLAIN_TYPES ; do
+ verbose "$tid: host ${ktype} revoked cert privsep $privsep"
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo HostKey $OBJ/cert_host_key_${ktype}
+ echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
+ echo UsePrivilegeSeparation $privsep
+ ) > $OBJ/sshd_proxy
+
+ cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
+ ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
+ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+ done
+done
+
+# Revoked CA
+kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig
+kh_revoke host_ca_key.pub host_ca_key2.pub >> $OBJ/known_hosts-cert.orig
+cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
+for ktype in $PLAIN_TYPES ; do
+ verbose "$tid: host ${ktype} revoked cert"
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo HostKey $OBJ/cert_host_key_${ktype}
+ echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
+ ) > $OBJ/sshd_proxy
+ cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
+ ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
+ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+done
+
+# Create a CA key and add it to known hosts
+kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig
+cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
+
+test_one() {
+ ident=$1
+ result=$2
+ sign_opts=$3
+
+ for kt in $PLAIN_TYPES; do
+ case $ktype in
+ rsa-sha2-*) tflag="-t $ktype"; ca="$OBJ/host_ca_key2" ;;
+ *) tflag=""; ca="$OBJ/host_ca_key" ;;
+ esac
+ ${SSHKEYGEN} -q -s $ca $tflag -I "regress host key for $USER" \
+ $sign_opts $OBJ/cert_host_key_${kt} ||
+ fatal "couldn't sign cert_host_key_${kt}"
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo HostKey $OBJ/cert_host_key_${kt}
+ echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub
+ ) > $OBJ/sshd_proxy
+
+ cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
+ ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
+ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ rc=$?
+ if [ "x$result" = "xsuccess" ] ; then
+ if [ $rc -ne 0 ]; then
+ fail "ssh cert connect $ident failed unexpectedly"
+ fi
+ else
+ if [ $rc -eq 0 ]; then
+ fail "ssh cert connect $ident succeeded unexpectedly"
+ fi
+ fi
+ done
+}
+
+test_one "user-certificate" failure "-n $HOSTS"
+test_one "empty principals" success "-h"
+test_one "wrong principals" failure "-h -n foo"
+test_one "cert not yet valid" failure "-h -V20300101:20320101"
+test_one "cert expired" failure "-h -V19800101:19900101"
+test_one "cert valid interval" success "-h -V-1w:+2w"
+test_one "cert has constraints" failure "-h -Oforce-command=false"
+
+# Check downgrade of cert to raw key when no CA found
+for ktype in $PLAIN_TYPES ; do
+ rm -f $OBJ/known_hosts-cert $OBJ/cert_host_key*
+ verbose "$tid: host ${ktype} ${v} cert downgrade to raw key"
+ # Generate and sign a host key
+ ${SSHKEYGEN} -q -N '' -t ${ktype} -f $OBJ/cert_host_key_${ktype} || \
+ fail "ssh-keygen of cert_host_key_${ktype} failed"
+ case $ktype in
+ rsa-sha2-*) tflag="-t $ktype"; ca="$OBJ/host_ca_key2" ;;
+ *) tflag=""; ca="$OBJ/host_ca_key" ;;
+ esac
+ ${SSHKEYGEN} -h -q $tflag -s $ca $tflag \
+ -I "regress host key for $USER" \
+ -n $HOSTS $OBJ/cert_host_key_${ktype} ||
+ fatal "couldn't sign cert_host_key_${ktype}"
+ (
+ printf "$HOSTS "
+ cat $OBJ/cert_host_key_${ktype}.pub
+ ) > $OBJ/known_hosts-cert
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo HostKey $OBJ/cert_host_key_${ktype}
+ echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
+ ) > $OBJ/sshd_proxy
+
+ ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
+ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
+ -F $OBJ/ssh_proxy somehost true
+ if [ $? -ne 0 ]; then
+ fail "ssh cert connect failed"
+ fi
+done
+
+# Wrong certificate
+kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig
+cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
+for kt in $PLAIN_TYPES ; do
+ verbose "$tid: host ${kt} connect wrong cert"
+ rm -f $OBJ/cert_host_key*
+ # Self-sign key
+ ${SSHKEYGEN} -q -N '' -t ${kt} -f $OBJ/cert_host_key_${kt} || \
+ fail "ssh-keygen of cert_host_key_${kt} failed"
+ case $kt in
+ rsa-sha2-*) tflag="-t $kt" ;;
+ *) tflag="" ;;
+ esac
+ ${SSHKEYGEN} $tflag -h -q -s $OBJ/cert_host_key_${kt} \
+ -I "regress host key for $USER" \
+ -n $HOSTS $OBJ/cert_host_key_${kt} ||
+ fatal "couldn't sign cert_host_key_${kt}"
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo HostKey $OBJ/cert_host_key_${kt}
+ echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub
+ ) > $OBJ/sshd_proxy
+
+ cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
+ ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
+ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
+ -F $OBJ/ssh_proxy -q somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect $ident succeeded unexpectedly"
+ fi
+done
+
+rm -f $OBJ/known_hosts-cert* $OBJ/host_ca_key* $OBJ/cert_host_key*
diff --git a/regress/cert-userkey.sh b/regress/cert-userkey.sh
new file mode 100644
index 00000000..91596fa7
--- /dev/null
+++ b/regress/cert-userkey.sh
@@ -0,0 +1,404 @@
+# $OpenBSD: cert-userkey.sh,v 1.25 2020/01/03 03:02:26 djm Exp $
+# Placed in the Public Domain.
+
+tid="certified user keys"
+
+rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
+
+PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
+EXTRA_TYPES=""
+rsa=""
+
+if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then
+ rsa=rsa
+ PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512"
+fi
+
+kname() {
+ case $1 in
+ rsa-sha2-*) n="$1" ;;
+ sk-ecdsa-*) n="sk-ecdsa" ;;
+ sk-ssh-ed25519*) n="sk-ssh-ed25519" ;;
+ # subshell because some seds will add a newline
+ *) n=$(echo $1 | sed 's/^dsa/ssh-dss/;s/^rsa/ssh-rsa/;s/^ed/ssh-ed/') ;;
+ esac
+ if [ -z "$rsa" ]; then
+ echo "$n*,ssh-ed25519*"
+ else
+ echo "$n*,ssh-rsa*,ssh-ed25519*"
+ fi
+}
+
+# Create a CA key
+if [ ! -z "$rsa" ]; then
+ catype=rsa
+else
+ catype=ed25519
+fi
+${SSHKEYGEN} -q -N '' -t $catype -f $OBJ/user_ca_key ||\
+ fail "ssh-keygen of user_ca_key failed"
+
+# Generate and sign user keys
+for ktype in $PLAIN_TYPES $EXTRA_TYPES ; do
+ verbose "$tid: sign user ${ktype} cert"
+ ${SSHKEYGEN} -q -N '' -t ${ktype} \
+ -f $OBJ/cert_user_key_${ktype} || \
+ fatal "ssh-keygen of cert_user_key_${ktype} failed"
+ # Generate RSA/SHA2 certs for rsa-sha2* keys.
+ case $ktype in
+ rsa-sha2-*) tflag="-t $ktype" ;;
+ *) tflag="" ;;
+ esac
+ ${SSHKEYGEN} -q -s $OBJ/user_ca_key -z $$ \
+ -I "regress user key for $USER" \
+ -n ${USER},mekmitasdigoat $tflag $OBJ/cert_user_key_${ktype} || \
+ fatal "couldn't sign cert_user_key_${ktype}"
+done
+
+# Test explicitly-specified principals
+for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
+ t=$(kname $ktype)
+ for privsep in yes ; do
+ _prefix="${ktype} privsep $privsep"
+
+ # Setup for AuthorizedPrincipalsFile
+ rm -f $OBJ/authorized_keys_$USER
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo "UsePrivilegeSeparation $privsep"
+ echo "AuthorizedPrincipalsFile " \
+ "$OBJ/authorized_principals_%u"
+ echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
+ echo "PubkeyAcceptedKeyTypes ${t}"
+ ) > $OBJ/sshd_proxy
+ (
+ cat $OBJ/ssh_proxy_bak
+ echo "PubkeyAcceptedKeyTypes ${t}"
+ ) > $OBJ/ssh_proxy
+
+ # Missing authorized_principals
+ verbose "$tid: ${_prefix} missing authorized_principals"
+ rm -f $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+
+ # Empty authorized_principals
+ verbose "$tid: ${_prefix} empty authorized_principals"
+ echo > $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+
+ # Wrong authorized_principals
+ verbose "$tid: ${_prefix} wrong authorized_principals"
+ echo gregorsamsa > $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+
+ # Correct authorized_principals
+ verbose "$tid: ${_prefix} correct authorized_principals"
+ echo mekmitasdigoat > $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ fail "ssh cert connect failed"
+ fi
+
+ # authorized_principals with bad key option
+ verbose "$tid: ${_prefix} authorized_principals bad key opt"
+ echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+
+ # authorized_principals with command=false
+ verbose "$tid: ${_prefix} authorized_principals command=false"
+ echo 'command="false" mekmitasdigoat' > \
+ $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+
+
+ # authorized_principals with command=true
+ verbose "$tid: ${_prefix} authorized_principals command=true"
+ echo 'command="true" mekmitasdigoat' > \
+ $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost false >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ fail "ssh cert connect failed"
+ fi
+
+ # Setup for principals= key option
+ rm -f $OBJ/authorized_principals_$USER
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo "UsePrivilegeSeparation $privsep"
+ echo "PubkeyAcceptedKeyTypes ${t}"
+ ) > $OBJ/sshd_proxy
+ (
+ cat $OBJ/ssh_proxy_bak
+ echo "PubkeyAcceptedKeyTypes ${t}"
+ ) > $OBJ/ssh_proxy
+
+ # Wrong principals list
+ verbose "$tid: ${_prefix} wrong principals key option"
+ (
+ printf 'cert-authority,principals="gregorsamsa" '
+ cat $OBJ/user_ca_key.pub
+ ) > $OBJ/authorized_keys_$USER
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+
+ # Correct principals list
+ verbose "$tid: ${_prefix} correct principals key option"
+ (
+ printf 'cert-authority,principals="mekmitasdigoat" '
+ cat $OBJ/user_ca_key.pub
+ ) > $OBJ/authorized_keys_$USER
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ fail "ssh cert connect failed"
+ fi
+ done
+done
+
+basic_tests() {
+ auth=$1
+ if test "x$auth" = "xauthorized_keys" ; then
+ # Add CA to authorized_keys
+ (
+ printf 'cert-authority '
+ cat $OBJ/user_ca_key.pub
+ ) > $OBJ/authorized_keys_$USER
+ else
+ echo > $OBJ/authorized_keys_$USER
+ extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub"
+ fi
+
+ for ktype in $PLAIN_TYPES ; do
+ t=$(kname $ktype)
+ for privsep in yes ; do
+ _prefix="${ktype} privsep $privsep $auth"
+ # Simple connect
+ verbose "$tid: ${_prefix} connect"
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo "UsePrivilegeSeparation $privsep"
+ echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "$extra_sshd"
+ ) > $OBJ/sshd_proxy
+ (
+ cat $OBJ/ssh_proxy_bak
+ echo "PubkeyAcceptedKeyTypes ${t}"
+ ) > $OBJ/ssh_proxy
+
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true
+ if [ $? -ne 0 ]; then
+ fail "ssh cert connect failed"
+ fi
+
+ # Revoked keys
+ verbose "$tid: ${_prefix} revoked key"
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo "UsePrivilegeSeparation $privsep"
+ echo "RevokedKeys $OBJ/cert_user_key_revoked"
+ echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "$extra_sshd"
+ ) > $OBJ/sshd_proxy
+ cp $OBJ/cert_user_key_${ktype}.pub \
+ $OBJ/cert_user_key_revoked
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpecedly"
+ fi
+ verbose "$tid: ${_prefix} revoked via KRL"
+ rm $OBJ/cert_user_key_revoked
+ ${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked \
+ $OBJ/cert_user_key_${ktype}.pub
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpecedly"
+ fi
+ verbose "$tid: ${_prefix} empty KRL"
+ ${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ fail "ssh cert connect failed"
+ fi
+ done
+
+ # Revoked CA
+ verbose "$tid: ${ktype} $auth revoked CA key"
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo "RevokedKeys $OBJ/user_ca_key.pub"
+ echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "$extra_sshd"
+ ) > $OBJ/sshd_proxy
+ ${SSH} -i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
+ somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpecedly"
+ fi
+ done
+
+ verbose "$tid: $auth CA does not authenticate"
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "$extra_sshd"
+ ) > $OBJ/sshd_proxy
+ verbose "$tid: ensure CA key does not authenticate user"
+ ${SSH} -i $OBJ/user_ca_key \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect with CA key succeeded unexpectedly"
+ fi
+}
+
+basic_tests authorized_keys
+basic_tests TrustedUserCAKeys
+
+test_one() {
+ ident=$1
+ result=$2
+ sign_opts=$3
+ auth_choice=$4
+ auth_opt=$5
+
+ if test "x$auth_choice" = "x" ; then
+ auth_choice="authorized_keys TrustedUserCAKeys"
+ fi
+
+ for auth in $auth_choice ; do
+ for ktype in $rsa ed25519 ; do
+ cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
+ if test "x$auth" = "xauthorized_keys" ; then
+ # Add CA to authorized_keys
+ (
+ printf "cert-authority${auth_opt} "
+ cat $OBJ/user_ca_key.pub
+ ) > $OBJ/authorized_keys_$USER
+ else
+ echo > $OBJ/authorized_keys_$USER
+ echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \
+ >> $OBJ/sshd_proxy
+ echo "PubkeyAcceptedKeyTypes ${t}*" \
+ >> $OBJ/sshd_proxy
+ if test "x$auth_opt" != "x" ; then
+ echo $auth_opt >> $OBJ/sshd_proxy
+ fi
+ fi
+
+ verbose "$tid: $ident auth $auth expect $result $ktype"
+ ${SSHKEYGEN} -q -s $OBJ/user_ca_key \
+ -I "regress user key for $USER" \
+ $sign_opts $OBJ/cert_user_key_${ktype} ||
+ fail "couldn't sign cert_user_key_${ktype}"
+
+ ${SSH} -i $OBJ/cert_user_key_${ktype} \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ rc=$?
+ if [ "x$result" = "xsuccess" ] ; then
+ if [ $rc -ne 0 ]; then
+ fail "$ident failed unexpectedly"
+ fi
+ else
+ if [ $rc -eq 0 ]; then
+ fail "$ident succeeded unexpectedly"
+ fi
+ fi
+ done
+ done
+}
+
+test_one "correct principal" success "-n ${USER}"
+test_one "host-certificate" failure "-n ${USER} -h"
+test_one "wrong principals" failure "-n foo"
+test_one "cert not yet valid" failure "-n ${USER} -V20300101:20320101"
+test_one "cert expired" failure "-n ${USER} -V19800101:19900101"
+test_one "cert valid interval" success "-n ${USER} -V-1w:+2w"
+test_one "wrong source-address" failure "-n ${USER} -Osource-address=10.0.0.0/8"
+test_one "force-command" failure "-n ${USER} -Oforce-command=false"
+
+# Behaviour is different here: TrustedUserCAKeys doesn't allow empty principals
+test_one "empty principals" success "" authorized_keys
+test_one "empty principals" failure "" TrustedUserCAKeys
+
+# Check explicitly-specified principals: an empty principals list in the cert
+# should always be refused.
+
+# AuthorizedPrincipalsFile
+rm -f $OBJ/authorized_keys_$USER
+echo mekmitasdigoat > $OBJ/authorized_principals_$USER
+test_one "AuthorizedPrincipalsFile principals" success "-n mekmitasdigoat" \
+ TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
+test_one "AuthorizedPrincipalsFile no principals" failure "" \
+ TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
+
+# principals= key option
+rm -f $OBJ/authorized_principals_$USER
+test_one "principals key option principals" success "-n mekmitasdigoat" \
+ authorized_keys ',principals="mekmitasdigoat"'
+test_one "principals key option no principals" failure "" \
+ authorized_keys ',principals="mekmitasdigoat"'
+
+# command= options vs. force-command in key
+test_one "force-command match true" success \
+ "-n ${USER} -Oforce-command=true" \
+ authorized_keys ',command="true"'
+test_one "force-command match true" failure \
+ "-n ${USER} -Oforce-command=false" \
+ authorized_keys ',command="false"'
+test_one "force-command mismatch 1" failure \
+ "-n ${USER} -Oforce-command=false" \
+ authorized_keys ',command="true"'
+test_one "force-command mismatch 2" failure \
+ "-n ${USER} -Oforce-command=true" \
+ authorized_keys ',command="false"'
+
+# Wrong certificate
+cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
+for ktype in $PLAIN_TYPES ; do
+ t=$(kname $ktype)
+ # Self-sign
+ ${SSHKEYGEN} -q -s $OBJ/cert_user_key_${ktype} -I \
+ "regress user key for $USER" \
+ -n $USER $OBJ/cert_user_key_${ktype} ||
+ fatal "couldn't sign cert_user_key_${ktype}"
+ verbose "$tid: user ${ktype} connect wrong cert"
+ ${SSH} -i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
+ somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect $ident succeeded unexpectedly"
+ fi
+done
+
+rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
+rm -f $OBJ/authorized_principals_$USER
+
diff --git a/regress/cfginclude.sh b/regress/cfginclude.sh
new file mode 100644
index 00000000..2fc39ce4
--- /dev/null
+++ b/regress/cfginclude.sh
@@ -0,0 +1,293 @@
+# $OpenBSD: cfginclude.sh,v 1.2 2016/05/03 15:30:46 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="config include"
+
+# to appease StrictModes
+umask 022
+
+cat > $OBJ/ssh_config.i << _EOF
+Match host a
+ Hostname aa
+
+Match host b
+ Hostname bb
+ Include $OBJ/ssh_config.i.*
+
+Match host c
+ Include $OBJ/ssh_config.i.*
+ Hostname cc
+
+Match host m
+ Include $OBJ/ssh_config.i.*
+
+Host d
+ Hostname dd
+
+Host e
+ Hostname ee
+ Include $OBJ/ssh_config.i.*
+
+Host f
+ Include $OBJ/ssh_config.i.*
+ Hostname ff
+
+Host n
+ Include $OBJ/ssh_config.i.*
+_EOF
+
+cat > $OBJ/ssh_config.i.0 << _EOF
+Match host xxxxxx
+_EOF
+
+cat > $OBJ/ssh_config.i.1 << _EOF
+Match host a
+ Hostname aaa
+
+Match host b
+ Hostname bbb
+
+Match host c
+ Hostname ccc
+
+Host d
+ Hostname ddd
+
+Host e
+ Hostname eee
+
+Host f
+ Hostname fff
+_EOF
+
+cat > $OBJ/ssh_config.i.2 << _EOF
+Match host a
+ Hostname aaaa
+
+Match host b
+ Hostname bbbb
+
+Match host c
+ Hostname cccc
+
+Host d
+ Hostname dddd
+
+Host e
+ Hostname eeee
+
+Host f
+ Hostname ffff
+
+Match all
+ Hostname xxxx
+_EOF
+
+trial() {
+ _host="$1"
+ _exp="$2"
+ ${REAL_SSH} -F $OBJ/ssh_config.i -G "$_host" > $OBJ/ssh_config.out ||
+ fatal "ssh config parse failed"
+ _got=`grep -i '^hostname ' $OBJ/ssh_config.out | awk '{print $2}'`
+ if test "x$_exp" != "x$_got" ; then
+ fail "host $_host include fail: expected $_exp got $_got"
+ fi
+}
+
+trial a aa
+trial b bb
+trial c ccc
+trial d dd
+trial e ee
+trial f fff
+trial m xxxx
+trial n xxxx
+trial x x
+
+# Prepare an included config with an error.
+
+cat > $OBJ/ssh_config.i.3 << _EOF
+Hostname xxxx
+ Junk
+_EOF
+
+${REAL_SSH} -F $OBJ/ssh_config.i -G a 2>/dev/null && \
+ fail "ssh include allowed invalid config"
+
+${REAL_SSH} -F $OBJ/ssh_config.i -G x 2>/dev/null && \
+ fail "ssh include allowed invalid config"
+
+rm -f $OBJ/ssh_config.i.*
+
+# Ensure that a missing include is not fatal.
+cat > $OBJ/ssh_config.i << _EOF
+Include $OBJ/ssh_config.i.*
+Hostname aa
+_EOF
+
+trial a aa
+
+# Ensure that Match/Host in an included config does not affect parent.
+cat > $OBJ/ssh_config.i.x << _EOF
+Match host x
+_EOF
+
+trial a aa
+
+cat > $OBJ/ssh_config.i.x << _EOF
+Host x
+_EOF
+
+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 $
+# Placed in the Public Domain.
+
+tid="config include"
+
+cat > $OBJ/ssh_config.i << _EOF
+Match host a
+ Hostname aa
+
+Match host b
+ Hostname bb
+ Include $OBJ/ssh_config.i.*
+
+Match host c
+ Include $OBJ/ssh_config.i.*
+ Hostname cc
+
+Match host m
+ Include $OBJ/ssh_config.i.*
+
+Host d
+ Hostname dd
+
+Host e
+ Hostname ee
+ Include $OBJ/ssh_config.i.*
+
+Host f
+ Include $OBJ/ssh_config.i.*
+ Hostname ff
+
+Host n
+ Include $OBJ/ssh_config.i.*
+_EOF
+
+cat > $OBJ/ssh_config.i.0 << _EOF
+Match host xxxxxx
+_EOF
+
+cat > $OBJ/ssh_config.i.1 << _EOF
+Match host a
+ Hostname aaa
+
+Match host b
+ Hostname bbb
+
+Match host c
+ Hostname ccc
+
+Host d
+ Hostname ddd
+
+Host e
+ Hostname eee
+
+Host f
+ Hostname fff
+_EOF
+
+cat > $OBJ/ssh_config.i.2 << _EOF
+Match host a
+ Hostname aaaa
+
+Match host b
+ Hostname bbbb
+
+Match host c
+ Hostname cccc
+
+Host d
+ Hostname dddd
+
+Host e
+ Hostname eeee
+
+Host f
+ Hostname ffff
+
+Match all
+ Hostname xxxx
+_EOF
+
+trial() {
+ _host="$1"
+ _exp="$2"
+ ${REAL_SSH} -F $OBJ/ssh_config.i -G "$_host" > $OBJ/ssh_config.out ||
+ fatal "ssh config parse failed"
+ _got=`grep -i '^hostname ' $OBJ/ssh_config.out | awk '{print $2}'`
+ if test "x$_exp" != "x$_got" ; then
+ fail "host $_host include fail: expected $_exp got $_got"
+ fi
+}
+
+trial a aa
+trial b bb
+trial c ccc
+trial d dd
+trial e ee
+trial f fff
+trial m xxxx
+trial n xxxx
+trial x x
+
+# Prepare an included config with an error.
+
+cat > $OBJ/ssh_config.i.3 << _EOF
+Hostname xxxx
+ Junk
+_EOF
+
+${REAL_SSH} -F $OBJ/ssh_config.i -G a 2>/dev/null && \
+ fail "ssh include allowed invalid config"
+
+${REAL_SSH} -F $OBJ/ssh_config.i -G x 2>/dev/null && \
+ fail "ssh include allowed invalid config"
+
+rm -f $OBJ/ssh_config.i.*
+
+# Ensure that a missing include is not fatal.
+cat > $OBJ/ssh_config.i << _EOF
+Include $OBJ/ssh_config.i.*
+Hostname aa
+_EOF
+
+trial a aa
+
+# Ensure that Match/Host in an included config does not affect parent.
+cat > $OBJ/ssh_config.i.x << _EOF
+Match host x
+_EOF
+
+trial a aa
+
+cat > $OBJ/ssh_config.i.x << _EOF
+Host x
+_EOF
+
+trial a aa
+
+# Ensure that recursive includes are bounded.
+cat > $OBJ/ssh_config.i << _EOF
+Include $OBJ/ssh_config.i
+_EOF
+
+${REAL_SSH} -F $OBJ/ssh_config.i -G a 2>/dev/null && \
+ fail "ssh include allowed infinite recursion?" # or hang...
+
+# cleanup
+rm -f $OBJ/ssh_config.i $OBJ/ssh_config.i.* $OBJ/ssh_config.out
diff --git a/regress/cfgmatch.sh b/regress/cfgmatch.sh
new file mode 100644
index 00000000..6620c84e
--- /dev/null
+++ b/regress/cfgmatch.sh
@@ -0,0 +1,158 @@
+# $OpenBSD: cfgmatch.sh,v 1.12 2019/04/18 18:57:16 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="sshd_config match"
+
+pidfile=$OBJ/remote_pid
+fwdport=3301
+fwd="-L $fwdport:127.0.0.1:$PORT"
+
+echo "ExitOnForwardFailure=yes" >> $OBJ/ssh_config
+echo "ExitOnForwardFailure=yes" >> $OBJ/ssh_proxy
+
+start_client()
+{
+ rm -f $pidfile
+ ${SSH} -q $fwd "$@" somehost \
+ exec sh -c \'"echo \$\$ > $pidfile; exec sleep 100"\' \
+ >>$TEST_REGRESS_LOGFILE 2>&1 &
+ client_pid=$!
+ # Wait for remote end
+ n=0
+ while test ! -f $pidfile ; do
+ sleep 1
+ n=`expr $n + 1`
+ if test $n -gt 60; then
+ kill $client_pid
+ fatal "timeout waiting for background ssh"
+ fi
+ done
+}
+
+stop_client()
+{
+ pid=`cat $pidfile`
+ if [ ! -z "$pid" ]; then
+ kill $pid
+ fi
+ wait
+}
+
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+echo "PermitOpen 127.0.0.1:1" >>$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 "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 "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 || \
+ fail "config w/match fails config test"
+
+start_sshd
+
+# Test Match + PermitOpen in sshd_config. This should be permitted
+trace "match permitopen localhost"
+start_client -F $OBJ/ssh_config
+${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
+ fail "match permitopen permit"
+stop_client
+
+# Same but from different source. This should not be permitted
+trace "match permitopen proxy"
+start_client -F $OBJ/ssh_proxy
+${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true && \
+ fail "match permitopen deny"
+stop_client
+
+# Retry previous with key option, should also be denied.
+cp /dev/null $OBJ/authorized_keys_$USER
+for t in ${SSH_KEYTYPES}; do
+ printf 'permitopen="127.0.0.1:'$PORT'" ' >> $OBJ/authorized_keys_$USER
+ cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+done
+trace "match permitopen proxy w/key opts"
+start_client -F $OBJ/ssh_proxy
+${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true && \
+ fail "match permitopen deny w/key opt"
+stop_client
+
+# Test both sshd_config and key options permitting the same dst/port pair.
+# Should be permitted.
+trace "match permitopen localhost"
+start_client -F $OBJ/ssh_config
+${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
+ fail "match permitopen permit"
+stop_client
+
+cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+echo "PermitOpen 127.0.0.1:1 127.0.0.1:$PORT 127.0.0.2:2" >>$OBJ/sshd_proxy
+echo "Match User $USER" >>$OBJ/sshd_proxy
+echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy
+
+# Test that a Match overrides a PermitOpen in the global section
+trace "match permitopen proxy w/key opts"
+start_client -F $OBJ/ssh_proxy
+${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true && \
+ fail "match override permitopen"
+stop_client
+
+cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+echo "PermitOpen 127.0.0.1:1 127.0.0.1:$PORT 127.0.0.2:2" >>$OBJ/sshd_proxy
+echo "Match User NoSuchUser" >>$OBJ/sshd_proxy
+echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy
+
+# Test that a rule that doesn't match doesn't override, plus test a
+# PermitOpen entry that's not at the start of the list
+trace "nomatch permitopen proxy w/key opts"
+start_client -F $OBJ/ssh_proxy
+${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
+ fail "nomatch override permitopen"
+stop_client
+
+# Test parsing of available Match criteria (with the exception of Group which
+# requires knowledge of actual group memberships user running the test).
+params="user:user:u1 host:host:h1 address:addr:1.2.3.4 \
+ localaddress:laddr:5.6.7.8 rdomain:rdomain:rdom1"
+cp $OBJ/sshd_proxy_bak $OBJ/sshd_config
+echo 'Banner /nomatch' >>$OBJ/sshd_config
+for i in $params; do
+ config=`echo $i | cut -f1 -d:`
+ criteria=`echo $i | cut -f2 -d:`
+ value=`echo $i | cut -f3 -d:`
+ cat >>$OBJ/sshd_config <<EOD
+ Match $config $value
+ Banner /$value
+EOD
+done
+
+${SUDO} ${SSHD} -f $OBJ/sshd_config -T >/dev/null || \
+ fail "validate config for w/out spec"
+
+# Test matching each criteria.
+for i in $params; do
+ testcriteria=`echo $i | cut -f2 -d:`
+ expected=/`echo $i | cut -f3 -d:`
+ spec=""
+ for j in $params; do
+ config=`echo $j | cut -f1 -d:`
+ criteria=`echo $j | cut -f2 -d:`
+ value=`echo $j | cut -f3 -d:`
+ if [ "$criteria" = "$testcriteria" ]; then
+ spec="$criteria=$value,$spec"
+ else
+ spec="$criteria=1$value,$spec"
+ fi
+ done
+ trace "test spec $spec"
+ result=`${SUDO} ${SSHD} -f $OBJ/sshd_config -T -C "$spec" | \
+ awk '$1=="banner"{print $2}'`
+ if [ "$result" != "$expected" ]; then
+ fail "match $config expected $expected got $result"
+ fi
+done
diff --git a/regress/cfgmatchlisten.sh b/regress/cfgmatchlisten.sh
new file mode 100644
index 00000000..a4fd66b3
--- /dev/null
+++ b/regress/cfgmatchlisten.sh
@@ -0,0 +1,202 @@
+# $OpenBSD: cfgmatchlisten.sh,v 1.3 2018/07/02 14:13:30 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="sshd_config matchlisten"
+
+pidfile=$OBJ/remote_pid
+fwdport=3301
+fwdspec="localhost:${fwdport}"
+fwd="-R $fwdport:127.0.0.1:$PORT"
+
+echo "ExitOnForwardFailure=yes" >> $OBJ/ssh_config
+echo "ExitOnForwardFailure=yes" >> $OBJ/ssh_proxy
+
+start_client()
+{
+ rm -f $pidfile
+ ${SSH} -vvv $fwd "$@" somehost true >>$TEST_REGRESS_LOGFILE 2>&1
+ r=$?
+ if [ $r -ne 0 ]; then
+ return $r
+ fi
+ ${SSH} -vvv $fwd "$@" somehost \
+ exec sh -c \'"echo \$\$ > $pidfile; exec sleep 100"\' \
+ >>$TEST_REGRESS_LOGFILE 2>&1 &
+ client_pid=$!
+ # Wait for remote end
+ n=0
+ while test ! -f $pidfile ; do
+ sleep 1
+ n=`expr $n + 1`
+ if test $n -gt 60; then
+ kill $client_pid
+ fatal "timeout waiting for background ssh"
+ fi
+ done
+ return $r
+}
+
+expect_client_ok()
+{
+ start_client "$@" ||
+ fail "client did not start"
+}
+
+expect_client_fail()
+{
+ local failmsg="$1"
+ shift
+ start_client "$@" &&
+ fail $failmsg
+}
+
+stop_client()
+{
+ pid=`cat $pidfile`
+ if [ ! -z "$pid" ]; then
+ kill $pid
+ fi
+ wait
+}
+
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+echo "PermitListen 127.0.0.1:1" >>$OBJ/sshd_config
+echo "Match Address 127.0.0.1" >>$OBJ/sshd_config
+echo "PermitListen 127.0.0.1:2 127.0.0.1:3 $fwdspec" >>$OBJ/sshd_config
+
+grep -v AuthorizedKeysFile $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
+echo "AuthorizedKeysFile /dev/null" >>$OBJ/sshd_proxy
+echo "PermitListen 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 "PermitListen 127.0.0.1:2 127.0.0.1:3 $fwdspec" >>$OBJ/sshd_proxy
+
+start_sshd
+
+#set -x
+
+# Test Match + PermitListen in sshd_config. This should be permitted
+trace "match permitlisten localhost"
+expect_client_ok -F $OBJ/ssh_config
+${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
+ fail "match permitlisten permit"
+stop_client
+
+# Same but from different source. This should not be permitted
+trace "match permitlisten proxy"
+expect_client_fail "match permitlisten deny" \
+ -F $OBJ/ssh_proxy
+
+# Retry previous with key option, should also be denied.
+cp /dev/null $OBJ/authorized_keys_$USER
+for t in ${SSH_KEYTYPES}; do
+ printf 'permitlisten="'$fwdspec'" ' >> $OBJ/authorized_keys_$USER
+ cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+done
+trace "match permitlisten proxy w/key opts"
+expect_client_fail "match permitlisten deny w/key opt"\
+ -F $OBJ/ssh_proxy
+
+# Test both sshd_config and key options permitting the same dst/port pair.
+# Should be permitted.
+trace "match permitlisten localhost"
+expect_client_ok -F $OBJ/ssh_config
+${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
+ fail "match permitlisten permit"
+stop_client
+
+# Test that a bare port number is accepted in PermitListen
+cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+echo "PermitListen 127.0.0.1:1 $fwdport 127.0.0.2:2" >>$OBJ/sshd_proxy
+trace "match permitlisten bare"
+expect_client_ok -F $OBJ/ssh_config
+${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
+ fail "match permitlisten bare"
+stop_client
+
+# Test that an incorrect bare port number is denied as expected
+cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+echo "PermitListen 1 2 99" >>$OBJ/sshd_proxy
+trace "match permitlisten bare"
+expect_client_fail -F $OBJ/ssh_config
+
+cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+echo "PermitListen 127.0.0.1:1 $fwdspec 127.0.0.2:2" >>$OBJ/sshd_proxy
+echo "Match User $USER" >>$OBJ/sshd_proxy
+echo "PermitListen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy
+
+# Test that a Match overrides a PermitListen in the global section
+trace "match permitlisten proxy w/key opts"
+expect_client_fail "match override permitlisten" \
+ -F $OBJ/ssh_proxy
+
+cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+echo "PermitListen 127.0.0.1:1 $fwdspec 127.0.0.2:2" >>$OBJ/sshd_proxy
+echo "Match User NoSuchUser" >>$OBJ/sshd_proxy
+echo "PermitListen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy
+
+# Test that a rule that doesn't match doesn't override, plus test a
+# PermitListen entry that's not at the start of the list
+trace "nomatch permitlisten proxy w/key opts"
+expect_client_ok -F $OBJ/ssh_proxy
+${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
+ fail "nomatch override permitlisten"
+stop_client
+
+# bind to 127.0.0.1 instead of default localhost
+fwdspec2="127.0.0.1:${fwdport}"
+fwd="-R ${fwdspec2}:127.0.0.1:$PORT"
+
+# first try w/ old fwdspec both in server config and key opts
+cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+echo "PermitListen 127.0.0.1:1 $fwdspec 127.0.0.2:2" >>$OBJ/sshd_proxy
+cp /dev/null $OBJ/authorized_keys_$USER
+for t in ${SSH_KEYTYPES}; do
+ printf 'permitlisten="'$fwdspec'" ' >> $OBJ/authorized_keys_$USER
+ cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+done
+trace "nomatch permitlisten 127.0.0.1 server config and userkey"
+expect_client_fail "nomatch 127.0.0.1 server config and userkey" \
+ -F $OBJ/ssh_config
+
+# correct server config, denied by key opts
+cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+echo "PermitListen 127.0.0.1:1 ${fwdspec2} 127.0.0.2:2" >>$OBJ/sshd_proxy
+trace "nomatch permitlisten 127.0.0.1 w/key opts"
+expect_client_fail "nomatch 127.0.0.1 w/key opts" \
+ -F $OBJ/ssh_config
+
+# fix key opts
+cp /dev/null $OBJ/authorized_keys_$USER
+for t in ${SSH_KEYTYPES}; do
+ printf 'permitlisten="'$fwdspec2'" ' >> $OBJ/authorized_keys_$USER
+ cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+done
+trace "match permitlisten 127.0.0.1 server config w/key opts"
+expect_client_ok -F $OBJ/ssh_proxy
+${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
+ fail "match 127.0.0.1 server config w/key opts"
+stop_client
+
+# key opts with bare port number
+cp /dev/null $OBJ/authorized_keys_$USER
+for t in ${SSH_KEYTYPES}; do
+ printf 'permitlisten="'$fwdport'" ' >> $OBJ/authorized_keys_$USER
+ cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+done
+trace "match permitlisten 127.0.0.1 server config w/key opts (bare)"
+expect_client_ok -F $OBJ/ssh_proxy
+${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
+ fail "match 127.0.0.1 server config w/key opts (bare)"
+stop_client
+
+# key opts with incorrect bare port number
+cp /dev/null $OBJ/authorized_keys_$USER
+for t in ${SSH_KEYTYPES}; do
+ printf 'permitlisten="99" ' >> $OBJ/authorized_keys_$USER
+ cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+done
+trace "match permitlisten 127.0.0.1 server config w/key opts (wrong bare)"
+expect_client_fail "nomatch 127.0.0.1 w/key opts (wrong bare)" \
+ -F $OBJ/ssh_config
diff --git a/regress/cfgparse.sh b/regress/cfgparse.sh
new file mode 100644
index 00000000..a9e5c6b0
--- /dev/null
+++ b/regress/cfgparse.sh
@@ -0,0 +1,75 @@
+# $OpenBSD: cfgparse.sh,v 1.7 2018/05/11 03:51:06 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="sshd config parse"
+
+# This is a reasonable proxy for IPv6 support.
+if ! config_defined HAVE_STRUCT_IN6_ADDR ; then
+ SKIP_IPV6=yes
+fi
+
+# We need to use the keys generated for the regression test because sshd -T
+# will fail if we're not running with SUDO (no permissions for real keys) or
+# if we are running tests on a system that has never had sshd installed
+# because the keys won't exist.
+
+grep "HostKey " $OBJ/sshd_config > $OBJ/sshd_config_minimal
+SSHD_KEYS="`cat $OBJ/sshd_config_minimal`"
+
+verbose "reparse minimal config"
+($SUDO ${SSHD} -T -f $OBJ/sshd_config_minimal >$OBJ/sshd_config.1 &&
+ $SUDO ${SSHD} -T -f $OBJ/sshd_config.1 >$OBJ/sshd_config.2 &&
+ diff $OBJ/sshd_config.1 $OBJ/sshd_config.2) || fail "reparse minimal config"
+
+verbose "reparse regress config"
+($SUDO ${SSHD} -T -f $OBJ/sshd_config >$OBJ/sshd_config.1 &&
+ $SUDO ${SSHD} -T -f $OBJ/sshd_config.1 >$OBJ/sshd_config.2 &&
+ diff $OBJ/sshd_config.1 $OBJ/sshd_config.2) || fail "reparse regress config"
+
+verbose "listenaddress order"
+# expected output
+cat > $OBJ/sshd_config.0 <<EOD
+listenaddress 1.2.3.4:1234
+listenaddress 1.2.3.4:5678
+EOD
+[ X${SKIP_IPV6} = Xyes ] || cat >> $OBJ/sshd_config.0 <<EOD
+listenaddress [::1]:1234
+listenaddress [::1]:5678
+EOD
+
+# test input sets. should all result in the output above.
+# test 1: addressfamily and port first
+cat > $OBJ/sshd_config.1 <<EOD
+${SSHD_KEYS}
+addressfamily any
+port 1234
+port 5678
+listenaddress 1.2.3.4
+EOD
+[ X${SKIP_IPV6} = Xyes ] || cat >> $OBJ/sshd_config.1 <<EOD
+listenaddress ::1
+EOD
+
+($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \
+ grep 'listenaddress ' >$OBJ/sshd_config.2 &&
+ diff $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \
+ fail "listenaddress order 1"
+# test 2: listenaddress first
+cat > $OBJ/sshd_config.1 <<EOD
+${SSHD_KEYS}
+listenaddress 1.2.3.4
+port 1234
+port 5678
+addressfamily any
+EOD
+[ X${SKIP_IPV6} = Xyes ] || cat >> $OBJ/sshd_config.1 <<EOD
+listenaddress ::1
+EOD
+
+($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \
+ grep 'listenaddress ' >$OBJ/sshd_config.2 &&
+ diff $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \
+ fail "listenaddress order 2"
+
+# cleanup
+rm -f $OBJ/sshd_config.[012]
diff --git a/regress/check-perm.c b/regress/check-perm.c
new file mode 100644
index 00000000..dac307d2
--- /dev/null
+++ b/regress/check-perm.c
@@ -0,0 +1,205 @@
+/*
+ * Placed in the public domain
+ */
+
+/* $OpenBSD: modpipe.c,v 1.6 2013/11/21 03:16:47 djm Exp $ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pwd.h>
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+
+static void
+fatal(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ fputc('\n', stderr);
+ va_end(args);
+ exit(1);
+}
+/* Based on session.c. NB. keep tests in sync */
+static void
+safely_chroot(const char *path, uid_t uid)
+{
+ const char *cp;
+ char component[PATH_MAX];
+ struct stat st;
+
+ if (*path != '/')
+ fatal("chroot path does not begin at root");
+ if (strlen(path) >= sizeof(component))
+ fatal("chroot path too long");
+
+ /*
+ * Descend the path, checking that each component is a
+ * root-owned directory with strict permissions.
+ */
+ for (cp = path; cp != NULL;) {
+ if ((cp = strchr(cp, '/')) == NULL)
+ strlcpy(component, path, sizeof(component));
+ else {
+ cp++;
+ memcpy(component, path, cp - path);
+ component[cp - path] = '\0';
+ }
+
+ /* debug3("%s: checking '%s'", __func__, component); */
+
+ if (stat(component, &st) != 0)
+ fatal("%s: stat(\"%s\"): %s", __func__,
+ component, strerror(errno));
+ if (st.st_uid != 0 || (st.st_mode & 022) != 0)
+ fatal("bad ownership or modes for chroot "
+ "directory %s\"%s\"",
+ cp == NULL ? "" : "component ", component);
+ if (!S_ISDIR(st.st_mode))
+ fatal("chroot path %s\"%s\" is not a directory",
+ cp == NULL ? "" : "component ", component);
+
+ }
+
+ if (chdir(path) == -1)
+ fatal("Unable to chdir to chroot path \"%s\": "
+ "%s", path, strerror(errno));
+}
+
+/* from platform.c */
+int
+platform_sys_dir_uid(uid_t uid)
+{
+ if (uid == 0)
+ return 1;
+#ifdef PLATFORM_SYS_DIR_UID
+ if (uid == PLATFORM_SYS_DIR_UID)
+ return 1;
+#endif
+ return 0;
+}
+
+/* from auth.c */
+int
+auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
+ uid_t uid, char *err, size_t errlen)
+{
+ char buf[PATH_MAX], homedir[PATH_MAX];
+ char *cp;
+ int comparehome = 0;
+ struct stat st;
+
+ if (realpath(name, buf) == NULL) {
+ snprintf(err, errlen, "realpath %s failed: %s", name,
+ strerror(errno));
+ return -1;
+ }
+ if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
+ comparehome = 1;
+
+ if (!S_ISREG(stp->st_mode)) {
+ snprintf(err, errlen, "%s is not a regular file", buf);
+ return -1;
+ }
+ if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
+ (stp->st_mode & 022) != 0) {
+ snprintf(err, errlen, "bad ownership or modes for file %s",
+ buf);
+ return -1;
+ }
+
+ /* for each component of the canonical path, walking upwards */
+ for (;;) {
+ if ((cp = dirname(buf)) == NULL) {
+ snprintf(err, errlen, "dirname() failed");
+ return -1;
+ }
+ strlcpy(buf, cp, sizeof(buf));
+
+ if (stat(buf, &st) < 0 ||
+ (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
+ (st.st_mode & 022) != 0) {
+ snprintf(err, errlen,
+ "bad ownership or modes for directory %s", buf);
+ return -1;
+ }
+
+ /* If are past the homedir then we can stop */
+ if (comparehome && strcmp(homedir, buf) == 0)
+ break;
+
+ /*
+ * dirname should always complete with a "/" path,
+ * but we can be paranoid and check for "." too
+ */
+ if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
+ break;
+ }
+ return 0;
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "check-perm -m [chroot | keys-command] [path]\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ const char *path = ".";
+ char errmsg[256];
+ int ch, mode = -1;
+ extern char *optarg;
+ extern int optind;
+ struct stat st;
+
+ while ((ch = getopt(argc, argv, "hm:")) != -1) {
+ switch (ch) {
+ case 'm':
+ if (strcasecmp(optarg, "chroot") == 0)
+ mode = 1;
+ else if (strcasecmp(optarg, "keys-command") == 0)
+ mode = 2;
+ else {
+ fprintf(stderr, "Invalid -m option\n"),
+ usage();
+ }
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 1)
+ usage();
+ else if (argc == 1)
+ path = argv[0];
+
+ if (mode == 1)
+ safely_chroot(path, getuid());
+ else if (mode == 2) {
+ if (stat(path, &st) < 0)
+ fatal("Could not stat %s: %s", path, strerror(errno));
+ if (auth_secure_path(path, &st, NULL, 0,
+ errmsg, sizeof(errmsg)) != 0)
+ fatal("Unsafe %s: %s", path, errmsg);
+ } else {
+ fprintf(stderr, "Invalid mode\n");
+ usage();
+ }
+ return 0;
+}
diff --git a/regress/cipher-speed.sh b/regress/cipher-speed.sh
new file mode 100644
index 00000000..5da95b3a
--- /dev/null
+++ b/regress/cipher-speed.sh
@@ -0,0 +1,32 @@
+# $OpenBSD: cipher-speed.sh,v 1.14 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="cipher speed"
+
+getbytes ()
+{
+ sed -n -e '/transferred/s/.*secs (\(.* bytes.sec\).*/\1/p' \
+ -e '/copied/s/.*s, \(.* MB.s\).*/\1/p'
+}
+
+tries="1 2"
+
+for c in `${SSH} -Q cipher`; do n=0; for m in `${SSH} -Q mac`; do
+ trace "cipher $c mac $m"
+ for x in $tries; do
+ printf "%-60s" "$c/$m:"
+ ( ${SSH} -o 'compression no' \
+ -F $OBJ/ssh_proxy -m $m -c $c somehost \
+ exec sh -c \'"dd of=/dev/null obs=32k"\' \
+ < ${DATA} ) 2>&1 | getbytes
+
+ if [ $? -ne 0 ]; then
+ fail "ssh failed with mac $m cipher $c"
+ fi
+ done
+ # No point trying all MACs for AEAD ciphers since they are ignored.
+ if ${SSH} -Q cipher-auth | grep "^${c}\$" >/dev/null 2>&1 ; then
+ break
+ fi
+ n=`expr $n + 1`
+done; done
diff --git a/regress/conch-ciphers.sh b/regress/conch-ciphers.sh
new file mode 100644
index 00000000..6678813a
--- /dev/null
+++ b/regress/conch-ciphers.sh
@@ -0,0 +1,28 @@
+# $OpenBSD: conch-ciphers.sh,v 1.4 2019/07/05 04:12:46 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="conch ciphers"
+
+if test "x$REGRESS_INTEROP_CONCH" != "xyes" ; then
+ echo "conch interop tests not enabled"
+ exit 0
+fi
+
+start_sshd
+
+for c in aes256-ctr aes256-cbc aes192-ctr aes192-cbc aes128-ctr aes128-cbc \
+ cast128-cbc blowfish 3des-cbc ; do
+ verbose "$tid: cipher $c"
+ rm -f ${COPY}
+ # XXX the 2nd "cat" seems to be needed because of buggy FD handling
+ # in conch
+ ${CONCH} --identity $OBJ/ssh-rsa --port $PORT --user $USER -e none \
+ --known-hosts $OBJ/known_hosts --notty --noagent --nox11 -n \
+ 127.0.0.1 "cat ${DATA}" 2>/dev/null | cat > ${COPY}
+ if [ $? -ne 0 ]; then
+ fail "ssh cat $DATA failed"
+ fi
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
+done
+rm -f ${COPY}
+
diff --git a/regress/connect-privsep.sh b/regress/connect-privsep.sh
new file mode 100644
index 00000000..b6abb65e
--- /dev/null
+++ b/regress/connect-privsep.sh
@@ -0,0 +1,35 @@
+# $OpenBSD: connect-privsep.sh,v 1.9 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="proxy connect with privsep"
+
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
+echo 'UsePrivilegeSeparation yes' >> $OBJ/sshd_proxy
+
+${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true
+if [ $? -ne 0 ]; then
+ fail "ssh privsep+proxyconnect failed"
+fi
+
+cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
+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"
+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
+ mopts="C F G J R S U X < >"
+else
+ mopts=`echo $TEST_MALLOC_OPTIONS | sed 's/./& /g'`
+fi
+for m in '' $mopts ; do
+ env MALLOC_OPTIONS="$m" ${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true
+ if [ $? -ne 0 ]; then
+ fail "ssh privsep/sandbox+proxyconnect mopt '$m' failed"
+ fi
+done
diff --git a/regress/connect-uri.sh b/regress/connect-uri.sh
new file mode 100644
index 00000000..f13f15e6
--- /dev/null
+++ b/regress/connect-uri.sh
@@ -0,0 +1,29 @@
+# $OpenBSD: connect-uri.sh,v 1.1 2017/10/24 19:33:32 millert Exp $
+# Placed in the Public Domain.
+
+tid="uri connect"
+
+# Remove Port and User from ssh_config, we want to rely on the URI
+cp $OBJ/ssh_config $OBJ/ssh_config.orig
+egrep -v '^ +(Port|User) +.*$' $OBJ/ssh_config.orig > $OBJ/ssh_config
+
+start_sshd
+
+verbose "$tid: no trailing slash"
+${SSH} -F $OBJ/ssh_config "ssh://${USER}@somehost:${PORT}" true
+if [ $? -ne 0 ]; then
+ fail "ssh connection failed"
+fi
+
+verbose "$tid: trailing slash"
+${SSH} -F $OBJ/ssh_config "ssh://${USER}@somehost:${PORT}/" true
+if [ $? -ne 0 ]; then
+ fail "ssh connection failed"
+fi
+
+verbose "$tid: with path name"
+${SSH} -F $OBJ/ssh_config "ssh://${USER}@somehost:${PORT}/${DATA}" true \
+ > /dev/null 2>&1
+if [ $? -eq 0 ]; then
+ fail "ssh connection succeeded, expected failure"
+fi
diff --git a/regress/connect.sh b/regress/connect.sh
new file mode 100644
index 00000000..46f12b7b
--- /dev/null
+++ b/regress/connect.sh
@@ -0,0 +1,18 @@
+# $OpenBSD: connect.sh,v 1.8 2020/01/25 02:57:53 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="simple connect"
+
+start_sshd
+
+trace "direct connect"
+${SSH} -F $OBJ/ssh_config somehost true
+if [ $? -ne 0 ]; then
+ fail "ssh direct connect failed"
+fi
+
+trace "proxy connect"
+${SSH} -F $OBJ/ssh_config -o "proxycommand $NC %h %p" somehost true
+if [ $? -ne 0 ]; then
+ fail "ssh proxycommand connect failed"
+fi
diff --git a/regress/dhgex.sh b/regress/dhgex.sh
new file mode 100644
index 00000000..ae64a9fb
--- /dev/null
+++ b/regress/dhgex.sh
@@ -0,0 +1,61 @@
+# $OpenBSD: dhgex.sh,v 1.6 2019/10/06 11:49:50 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="dhgex"
+
+LOG=${TEST_SSH_LOGFILE}
+rm -f ${LOG}
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+
+kexs=`${SSH} -Q kex | grep diffie-hellman-group-exchange`
+
+ssh_test_dhgex()
+{
+ bits="$1"; shift
+ cipher="$1"; shift
+ kex="$1"; shift
+
+ cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+ echo "KexAlgorithms=$kex" >> $OBJ/sshd_proxy
+ echo "Ciphers=$cipher" >> $OBJ/sshd_proxy
+ rm -f ${LOG}
+ opts="-oKexAlgorithms=$kex -oCiphers=$cipher"
+ min=2048
+ max=8192
+ groupsz="$min<$bits<$max"
+ verbose "$tid bits $bits $kex $cipher"
+ ${SSH} ${opts} $@ -vvv -F ${OBJ}/ssh_proxy somehost true
+ if [ $? -ne 0 ]; then
+ fail "ssh failed ($@)"
+ fi
+ # check what we request
+ grep "SSH2_MSG_KEX_DH_GEX_REQUEST($groupsz) sent" ${LOG} >/dev/null
+ if [ $? != 0 ]; then
+ got=`egrep "SSH2_MSG_KEX_DH_GEX_REQUEST(.*) sent" ${LOG}`
+ fail "$tid unexpected GEX sizes, expected $groupsz, got $got"
+ fi
+ # check what we got.
+ gotbits="`awk 'BEGIN{FS="/"}/bits set:/{print $2}' ${LOG} |
+ head -1 | tr -d '\r\n'`"
+ trace "expected '$bits' got '$gotbits'"
+ if [ -z "$gotbits" ] || [ "$gotbits" -lt "$bits" ]; then
+ fatal "$tid expected $bits bit group, got $gotbits"
+ fi
+}
+
+check()
+{
+ bits="$1"; shift
+
+ for c in $@; do
+ for k in $kexs; do
+ ssh_test_dhgex $bits $c $k
+ done
+ done
+}
+
+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
diff --git a/regress/dsa_ssh2.prv b/regress/dsa_ssh2.prv
new file mode 100644
index 00000000..c93b4037
--- /dev/null
+++ b/regress/dsa_ssh2.prv
@@ -0,0 +1,14 @@
+---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----
+Subject: ssh-keygen test
+Comment: "1024-bit dsa, Tue Jan 08 2002 22:00:23 +0100"
+P2/56wAAAgIAAAAmZGwtbW9kcHtzaWdue2RzYS1uaXN0LXNoYTF9LGRoe3BsYWlufX0AAA
+AEbm9uZQAAAcQAAAHAAAAAAAAABACwUfm3AxZTut3icBmwCcD48nY64HzuELlQ+vEqjIcR
+Lo49es/DQTeLNQ+kdKRCfouosGNv0WqxRtF0tUsWdXxS37oHGa4QPugBdHRd7YlZGZv8kg
+x7FsoepY7v7E683/97dv2zxL3AGagTEzWr7fl0yPexAaZoDvtQrrjX44BLmwAABACWQkvv
+MxnD8eFkS1konFfMJ1CkuRfTN34CBZ6dY7VTSGemy4QwtFdMKmoufD0eKgy3p5WOeWCYKt
+F4FhjHKZk/aaxFjjIbtkrnlvXg64QI11dSZyBN6/ViQkHPSkUDF+A6AAEhrNbQbAFSvao1
+kTvNtPCtL0AkUIduEMzGQfLCTAAAAKDeC043YVo9Zo0zAEeIA4uZh4LBCQAAA/9aj7Y5ik
+ehygJ4qTDSlVypsPuV+n59tMS0e2pfrSG87yf5r94AKBmJeho5OO6wYaXCxsVB7AFbSUD6
+75AK8mHF4v1/+7SWKk5f8xlMCMSPZ9K0+j/W1d/q2qkhnnDZolOHDomLA+U00i5ya/jnTV
+zyDPWLFpWK8u3xGBPAYX324gAAAKDHFvooRnaXdZbeWGTTqmgHB1GU9A==
+---- END SSH2 ENCRYPTED PRIVATE KEY ----
diff --git a/regress/dsa_ssh2.pub b/regress/dsa_ssh2.pub
new file mode 100644
index 00000000..215d73ba
--- /dev/null
+++ b/regress/dsa_ssh2.pub
@@ -0,0 +1,13 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+Subject: ssh-keygen test
+Comment: "1024-bit dsa, Tue Jan 08 2002 22:00:23 +0100"
+AAAAB3NzaC1kc3MAAACBALBR+bcDFlO63eJwGbAJwPjydjrgfO4QuVD68SqMhxEujj16z8
+NBN4s1D6R0pEJ+i6iwY2/RarFG0XS1SxZ1fFLfugcZrhA+6AF0dF3tiVkZm/ySDHsWyh6l
+ju/sTrzf/3t2/bPEvcAZqBMTNavt+XTI97EBpmgO+1CuuNfjgEubAAAAFQDeC043YVo9Zo
+0zAEeIA4uZh4LBCQAAAIEAlkJL7zMZw/HhZEtZKJxXzCdQpLkX0zd+AgWenWO1U0hnpsuE
+MLRXTCpqLnw9HioMt6eVjnlgmCrReBYYxymZP2msRY4yG7ZK55b14OuECNdXUmcgTev1Yk
+JBz0pFAxfgOgABIazW0GwBUr2qNZE7zbTwrS9AJFCHbhDMxkHywkwAAACAWo+2OYpHocoC
+eKkw0pVcqbD7lfp+fbTEtHtqX60hvO8n+a/eACgZiXoaOTjusGGlwsbFQewBW0lA+u+QCv
+JhxeL9f/u0lipOX/MZTAjEj2fStPo/1tXf6tqpIZ5w2aJThw6JiwPlNNIucmv4501c8gz1
+ixaVivLt8RgTwGF99uI=
+---- END SSH2 PUBLIC KEY ----
diff --git a/regress/dynamic-forward.sh b/regress/dynamic-forward.sh
new file mode 100644
index 00000000..84f8ee19
--- /dev/null
+++ b/regress/dynamic-forward.sh
@@ -0,0 +1,61 @@
+# $OpenBSD: dynamic-forward.sh,v 1.13 2017/09/21 19:18:12 markus Exp $
+# Placed in the Public Domain.
+
+tid="dynamic forwarding"
+
+FWDPORT=`expr $PORT + 1`
+
+if have_prog nc && nc -h 2>&1 | grep "proxy address" >/dev/null; then
+ proxycmd="nc -x 127.0.0.1:$FWDPORT -X"
+elif have_prog connect; then
+ proxycmd="connect -S 127.0.0.1:$FWDPORT -"
+else
+ echo "skipped (no suitable ProxyCommand found)"
+ exit 0
+fi
+trace "will use ProxyCommand $proxycmd"
+
+start_sshd
+
+for d in D R; do
+ n=0
+ error="1"
+ trace "start dynamic forwarding, fork to background"
+
+ while [ "$error" -ne 0 -a "$n" -lt 3 ]; do
+ n=`expr $n + 1`
+ ${SSH} -F $OBJ/ssh_config -f -$d $FWDPORT -q \
+ -oExitOnForwardFailure=yes somehost exec sh -c \
+ \'"echo \$\$ > $OBJ/remote_pid; exec sleep 444"\'
+ error=$?
+ if [ "$error" -ne 0 ]; then
+ trace "forward failed attempt $n err $error"
+ sleep $n
+ fi
+ done
+ if [ "$error" -ne 0 ]; then
+ fatal "failed to start dynamic forwarding"
+ fi
+
+ for s in 4 5; do
+ for h in 127.0.0.1 localhost; do
+ trace "testing ssh socks version $s host $h (-$d)"
+ ${SSH} -F $OBJ/ssh_config \
+ -o "ProxyCommand ${proxycmd}${s} $h $PORT" \
+ somehost cat ${DATA} > ${COPY}
+ test -f ${COPY} || fail "failed copy ${DATA}"
+ cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
+ done
+ done
+
+ if [ -f $OBJ/remote_pid ]; then
+ remote=`cat $OBJ/remote_pid`
+ trace "terminate remote shell, pid $remote"
+ if [ $remote -gt 1 ]; then
+ kill -HUP $remote
+ fi
+ else
+ fail "no pid file: $OBJ/remote_pid"
+ fi
+
+done
diff --git a/regress/envpass.sh b/regress/envpass.sh
new file mode 100644
index 00000000..af7eafe3
--- /dev/null
+++ b/regress/envpass.sh
@@ -0,0 +1,60 @@
+# $OpenBSD: envpass.sh,v 1.4 2005/03/04 08:48:46 djm Exp $
+# Placed in the Public Domain.
+
+tid="environment passing"
+
+# NB accepted env vars are in test-exec.sh (_XXX_TEST_* and _XXX_TEST)
+
+# Prepare a custom config to test for a configuration parsing bug fixed in 4.0
+cat << EOF > $OBJ/ssh_proxy_envpass
+Host test-sendenv-confparse-bug
+ SendEnv *
+EOF
+cat $OBJ/ssh_proxy >> $OBJ/ssh_proxy_envpass
+
+trace "pass env, don't accept"
+verbose "test $tid: pass env, don't accept"
+_TEST_ENV=blah ${SSH} -oSendEnv="*" -F $OBJ/ssh_proxy_envpass otherhost \
+ sh << 'EOF'
+ test -z "$_TEST_ENV"
+EOF
+r=$?
+if [ $r -ne 0 ]; then
+ fail "environment found"
+fi
+
+trace "don't pass env, accept"
+verbose "test $tid: don't pass env, accept"
+_XXX_TEST_A=1 _XXX_TEST_B=2 ${SSH} -F $OBJ/ssh_proxy_envpass otherhost \
+ sh << 'EOF'
+ test -z "$_XXX_TEST_A" && test -z "$_XXX_TEST_B"
+EOF
+r=$?
+if [ $r -ne 0 ]; then
+ fail "environment found"
+fi
+
+trace "pass single env, accept single env"
+verbose "test $tid: pass single env, accept single env"
+_XXX_TEST=blah ${SSH} -oSendEnv="_XXX_TEST" -F $OBJ/ssh_proxy_envpass \
+ otherhost sh << 'EOF'
+ test X"$_XXX_TEST" = X"blah"
+EOF
+r=$?
+if [ $r -ne 0 ]; then
+ fail "environment not found"
+fi
+
+trace "pass multiple env, accept multiple env"
+verbose "test $tid: pass multiple env, accept multiple env"
+_XXX_TEST_A=1 _XXX_TEST_B=2 ${SSH} -oSendEnv="_XXX_TEST_*" \
+ -F $OBJ/ssh_proxy_envpass otherhost \
+ sh << 'EOF'
+ test X"$_XXX_TEST_A" = X"1" -a X"$_XXX_TEST_B" = X"2"
+EOF
+r=$?
+if [ $r -ne 0 ]; then
+ fail "environment not found"
+fi
+
+rm -f $OBJ/ssh_proxy_envpass
diff --git a/regress/exit-status.sh b/regress/exit-status.sh
new file mode 100644
index 00000000..aadf99fb
--- /dev/null
+++ b/regress/exit-status.sh
@@ -0,0 +1,22 @@
+# $OpenBSD: exit-status.sh,v 1.8 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="remote exit status"
+
+for s in 0 1 4 5 44; do
+ trace "status $s"
+ verbose "test $tid: status $s"
+ ${SSH} -F $OBJ/ssh_proxy otherhost exit $s
+ r=$?
+ if [ $r -ne $s ]; then
+ fail "exit code mismatch for: $r != $s"
+ fi
+
+ # same with early close of stdout/err
+ ${SSH} -F $OBJ/ssh_proxy -n otherhost exec \
+ sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\'
+ r=$?
+ if [ $r -ne $s ]; then
+ fail "exit code (with sleep) mismatch for: $r != $s"
+ fi
+done
diff --git a/regress/forcecommand.sh b/regress/forcecommand.sh
new file mode 100644
index 00000000..e059f1fd
--- /dev/null
+++ b/regress/forcecommand.sh
@@ -0,0 +1,35 @@
+# $OpenBSD: forcecommand.sh,v 1.4 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="forced command"
+
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+
+cp /dev/null $OBJ/authorized_keys_$USER
+for t in ${SSH_KEYTYPES}; do
+ printf 'command="true" ' >>$OBJ/authorized_keys_$USER
+ cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+done
+
+trace "forced command in key option"
+${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command in key"
+
+cp /dev/null $OBJ/authorized_keys_$USER
+for t in ${SSH_KEYTYPES}; do
+ printf 'command="false" ' >> $OBJ/authorized_keys_$USER
+ cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+done
+
+cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+echo "ForceCommand true" >> $OBJ/sshd_proxy
+
+trace "forced command in sshd_config overrides key option"
+${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command in key"
+
+cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+echo "ForceCommand false" >> $OBJ/sshd_proxy
+echo "Match User $USER" >> $OBJ/sshd_proxy
+echo " ForceCommand true" >> $OBJ/sshd_proxy
+
+trace "forced command with match"
+${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command in key"
diff --git a/regress/forward-control.sh b/regress/forward-control.sh
new file mode 100644
index 00000000..3b1f69a7
--- /dev/null
+++ b/regress/forward-control.sh
@@ -0,0 +1,235 @@
+# $OpenBSD: forward-control.sh,v 1.7 2018/06/07 14:29:43 djm Exp $
+# Placed in the Public Domain.
+
+tid="sshd control of local and remote forwarding"
+
+LFWD_PORT=3320
+RFWD_PORT=3321
+CTL=$OBJ/ctl-sock
+READY=$OBJ/ready
+
+wait_for_file_to_appear() {
+ _path=$1
+ _n=0
+ while test ! -f $_path ; do
+ test $_n -eq 1 && trace "waiting for $_path to appear"
+ _n=`expr $_n + 1`
+ test $_n -ge 20 && return 1
+ sleep 1
+ done
+ return 0
+}
+
+wait_for_process_to_exit() {
+ _pid=$1
+ _n=0
+ while kill -0 $_pid 2>/dev/null ; do
+ test $_n -eq 1 && trace "waiting for $_pid to exit"
+ _n=`expr $_n + 1`
+ test $_n -ge 20 && return 1
+ sleep 1
+ done
+ return 0
+}
+
+# usage: check_lfwd Y|N message
+check_lfwd() {
+ _expected=$1
+ _message=$2
+ rm -f $READY
+ ${SSH} -F $OBJ/ssh_proxy \
+ -L$LFWD_PORT:127.0.0.1:$PORT \
+ -o ExitOnForwardFailure=yes \
+ -n host exec sh -c \'"sleep 60 & echo \$! > $READY ; wait "\' \
+ >/dev/null 2>&1 &
+ _sshpid=$!
+ 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
+ _result=$?
+ kill $_sshpid `cat $READY` 2>/dev/null
+ wait_for_process_to_exit $_sshpid
+ if test "x$_expected" = "xY" -a $_result -ne 0 ; then
+ fail "check_lfwd failed (expecting success): $_message"
+ elif test "x$_expected" = "xN" -a $_result -eq 0 ; then
+ fail "check_lfwd succeeded (expecting failure): $_message"
+ elif test "x$_expected" != "xY" -a "x$_expected" != "xN" ; then
+ fatal "check_lfwd invalid argument \"$_expected\""
+ else
+ verbose "check_lfwd done (expecting $_expected): $_message"
+ fi
+}
+
+# usage: check_rfwd Y|N message
+check_rfwd() {
+ _expected=$1
+ _message=$2
+ rm -f $READY
+ ${SSH} -F $OBJ/ssh_proxy \
+ -R127.0.0.1:$RFWD_PORT:127.0.0.1:$PORT \
+ -o ExitOnForwardFailure=yes \
+ -n host exec sh -c \'"sleep 60 & echo \$! > $READY ; wait "\' \
+ >/dev/null 2>&1 &
+ _sshpid=$!
+ wait_for_file_to_appear $READY
+ _result=$?
+ if test $_result -eq 0 ; then
+ ${SSH} -F $OBJ/ssh_config -p $RFWD_PORT \
+ -oConnectionAttempts=4 host true >/dev/null 2>&1
+ _result=$?
+ kill $_sshpid `cat $READY` 2>/dev/null
+ wait_for_process_to_exit $_sshpid
+ fi
+ if test "x$_expected" = "xY" -a $_result -ne 0 ; then
+ fail "check_rfwd failed (expecting success): $_message"
+ elif test "x$_expected" = "xN" -a $_result -eq 0 ; then
+ fail "check_rfwd succeeded (expecting failure): $_message"
+ elif test "x$_expected" != "xY" -a "x$_expected" != "xN" ; then
+ fatal "check_rfwd invalid argument \"$_expected\""
+ else
+ verbose "check_rfwd done (expecting $_expected): $_message"
+ fi
+}
+
+start_sshd
+cp ${OBJ}/sshd_proxy ${OBJ}/sshd_proxy.bak
+cp ${OBJ}/authorized_keys_${USER} ${OBJ}/authorized_keys_${USER}.bak
+
+# Sanity check: ensure the default config allows forwarding
+check_lfwd Y "default configuration"
+check_rfwd Y "default configuration"
+
+# Usage: lperm_tests yes|local|remote|no Y|N Y|N Y|N Y|N Y|N Y|N
+lperm_tests() {
+ _tcpfwd=$1
+ _plain_lfwd=$2
+ _plain_rfwd=$3
+ _nopermit_lfwd=$4
+ _nopermit_rfwd=$5
+ _permit_lfwd=$6
+ _permit_rfwd=$7
+ _badfwd1=127.0.0.1:22
+ _badfwd2=127.0.0.2:22
+ _goodfwd=127.0.0.1:${PORT}
+ cp ${OBJ}/authorized_keys_${USER}.bak ${OBJ}/authorized_keys_${USER}
+ _prefix="AllowTcpForwarding=$_tcpfwd"
+
+ # No PermitOpen
+ ( cat ${OBJ}/sshd_proxy.bak ;
+ echo "AllowTcpForwarding $_tcpfwd" ) \
+ > ${OBJ}/sshd_proxy
+ check_lfwd $_plain_lfwd "$_prefix"
+ check_rfwd $_plain_rfwd "$_prefix"
+
+ # PermitOpen via sshd_config that doesn't match
+ ( cat ${OBJ}/sshd_proxy.bak ;
+ echo "AllowTcpForwarding $_tcpfwd" ;
+ echo "PermitOpen $_badfwd1 $_badfwd2" ) \
+ > ${OBJ}/sshd_proxy
+ check_lfwd $_nopermit_lfwd "$_prefix, !PermitOpen"
+ check_rfwd $_nopermit_rfwd "$_prefix, !PermitOpen"
+ # PermitOpen via sshd_config that does match
+ ( cat ${OBJ}/sshd_proxy.bak ;
+ echo "AllowTcpForwarding $_tcpfwd" ;
+ echo "PermitOpen $_badfwd1 $_goodfwd $_badfwd2" ) \
+ > ${OBJ}/sshd_proxy
+ check_lfwd $_plain_lfwd "$_prefix, PermitOpen"
+ check_rfwd $_plain_rfwd "$_prefix, PermitOpen"
+
+ # permitopen keys option.
+ # NB. permitopen via authorized_keys should have same
+ # success/fail as via sshd_config
+ # permitopen via authorized_keys that doesn't match
+ sed "s/^/permitopen=\"$_badfwd1\",permitopen=\"$_badfwd2\" /" \
+ < ${OBJ}/authorized_keys_${USER}.bak \
+ > ${OBJ}/authorized_keys_${USER} || fatal "sed 1 fail"
+ ( cat ${OBJ}/sshd_proxy.bak ;
+ echo "AllowTcpForwarding $_tcpfwd" ) \
+ > ${OBJ}/sshd_proxy
+ check_lfwd $_nopermit_lfwd "$_prefix, !permitopen"
+ check_rfwd $_nopermit_rfwd "$_prefix, !permitopen"
+ # permitopen via authorized_keys that does match
+ sed "s/^/permitopen=\"$_badfwd1\",permitopen=\"$_goodfwd\" /" \
+ < ${OBJ}/authorized_keys_${USER}.bak \
+ > ${OBJ}/authorized_keys_${USER} || fatal "sed 2 fail"
+ ( cat ${OBJ}/sshd_proxy.bak ;
+ echo "AllowTcpForwarding $_tcpfwd" ) \
+ > ${OBJ}/sshd_proxy
+ check_lfwd $_permit_lfwd "$_prefix, permitopen"
+ check_rfwd $_permit_rfwd "$_prefix, permitopen"
+
+ # Check port-forwarding flags in authorized_keys.
+ # These two should refuse all.
+ sed "s/^/no-port-forwarding /" \
+ < ${OBJ}/authorized_keys_${USER}.bak \
+ > ${OBJ}/authorized_keys_${USER} || fatal "sed 3 fail"
+ ( cat ${OBJ}/sshd_proxy.bak ;
+ echo "AllowTcpForwarding $_tcpfwd" ) \
+ > ${OBJ}/sshd_proxy
+ check_lfwd N "$_prefix, no-port-forwarding"
+ check_rfwd N "$_prefix, no-port-forwarding"
+ sed "s/^/restrict /" \
+ < ${OBJ}/authorized_keys_${USER}.bak \
+ > ${OBJ}/authorized_keys_${USER} || fatal "sed 4 fail"
+ ( cat ${OBJ}/sshd_proxy.bak ;
+ echo "AllowTcpForwarding $_tcpfwd" ) \
+ > ${OBJ}/sshd_proxy
+ check_lfwd N "$_prefix, restrict"
+ check_rfwd N "$_prefix, restrict"
+ # This should pass the same cases as _nopermit*
+ sed "s/^/restrict,port-forwarding /" \
+ < ${OBJ}/authorized_keys_${USER}.bak \
+ > ${OBJ}/authorized_keys_${USER} || fatal "sed 5 fail"
+ ( cat ${OBJ}/sshd_proxy.bak ;
+ echo "AllowTcpForwarding $_tcpfwd" ) \
+ > ${OBJ}/sshd_proxy
+ check_lfwd $_plain_lfwd "$_prefix, restrict,port-forwarding"
+ check_rfwd $_plain_rfwd "$_prefix, restrict,port-forwarding"
+}
+
+# permit-open none mismatch match
+# AllowTcpForwarding local remote local remote local remote
+lperm_tests yes Y Y N Y Y Y
+lperm_tests local Y N N N Y N
+lperm_tests remote N Y N Y N Y
+lperm_tests no N N N N N N
+
+# Usage: rperm_tests yes|local|remote|no Y|N Y|N Y|N Y|N Y|N Y|N
+rperm_tests() {
+ _tcpfwd=$1
+ _plain_lfwd=$2
+ _plain_rfwd=$3
+ _nopermit_lfwd=$4
+ _nopermit_rfwd=$5
+ _permit_lfwd=$6
+ _permit_rfwd=$7
+ _badfwd1=127.0.0.1:22
+ _badfwd2=127.0.0.2:${RFWD_PORT}
+ _goodfwd=127.0.0.1:${RFWD_PORT}
+ cp ${OBJ}/authorized_keys_${USER}.bak ${OBJ}/authorized_keys_${USER}
+ _prefix="AllowTcpForwarding=$_tcpfwd"
+
+ # PermitListen via sshd_config that doesn't match
+ ( cat ${OBJ}/sshd_proxy.bak ;
+ echo "AllowTcpForwarding $_tcpfwd" ;
+ echo "PermitListen $_badfwd1 $_badfwd2" ) \
+ > ${OBJ}/sshd_proxy
+ check_lfwd $_nopermit_lfwd "$_prefix, !PermitListen"
+ check_rfwd $_nopermit_rfwd "$_prefix, !PermitListen"
+ # PermitListen via sshd_config that does match
+ ( cat ${OBJ}/sshd_proxy.bak ;
+ echo "AllowTcpForwarding $_tcpfwd" ;
+ echo "PermitListen $_badfwd1 $_goodfwd $_badfwd2" ) \
+ > ${OBJ}/sshd_proxy
+ check_lfwd $_plain_lfwd "$_prefix, PermitListen"
+ check_rfwd $_plain_rfwd "$_prefix, PermitListen"
+}
+
+# permit-remote-open none mismatch match
+# AllowTcpForwarding local remote local remote local remote
+rperm_tests yes Y Y Y N Y Y
+rperm_tests local Y N Y N Y N
+rperm_tests remote N Y N N N Y
+rperm_tests no N N N N N N
+
diff --git a/regress/forwarding.sh b/regress/forwarding.sh
new file mode 100644
index 00000000..cd634f2f
--- /dev/null
+++ b/regress/forwarding.sh
@@ -0,0 +1,136 @@
+# $OpenBSD: forwarding.sh,v 1.23 2019/07/20 09:50:58 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="local and remote forwarding"
+
+DATA=/bin/ls${EXEEXT}
+
+start_sshd
+
+base=33
+last=$PORT
+fwd=""
+make_tmpdir
+CTL=${SSH_REGRESS_TMP}/ctl-sock
+
+for j in 0 1 2; do
+ for i in 0 1 2; do
+ a=$base$j$i
+ b=`expr $a + 50`
+ c=$last
+ # fwd chain: $a -> $b -> $c
+ fwd="$fwd -L$a:127.0.0.1:$b -R$b:127.0.0.1:$c"
+ last=$a
+ done
+done
+
+trace "start forwarding, fork to background"
+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' \
+ somehost cat ${DATA} > ${COPY}
+test -s ${COPY} || fail "failed copy of ${DATA}"
+cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
+
+${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost 2>/dev/null
+
+for d in L R; do
+ trace "exit on -$d forward failure"
+
+ # this one should succeed
+ ${SSH} -F $OBJ/ssh_config \
+ -$d ${base}01:127.0.0.1:$PORT \
+ -$d ${base}02:127.0.0.1:$PORT \
+ -$d ${base}03:127.0.0.1:$PORT \
+ -$d ${base}04:127.0.0.1:$PORT \
+ -oExitOnForwardFailure=yes somehost true
+ if [ $? != 0 ]; then
+ fatal "connection failed, should not"
+ else
+ # this one should fail
+ ${SSH} -q -F $OBJ/ssh_config \
+ -$d ${base}01:127.0.0.1:$PORT \
+ -$d ${base}02:127.0.0.1:$PORT \
+ -$d ${base}03:127.0.0.1:$PORT \
+ -$d ${base}01:localhost:$PORT \
+ -$d ${base}04:127.0.0.1:$PORT \
+ -oExitOnForwardFailure=yes somehost true
+ r=$?
+ if [ $r != 255 ]; then
+ fail "connection not termintated, but should ($r)"
+ fi
+ fi
+done
+
+trace "simple clear forwarding"
+${SSH} -F $OBJ/ssh_config -oClearAllForwardings=yes somehost true
+
+trace "clear local forward"
+rm -f $CTL
+${SSH} -S $CTL -N -M -f -F $OBJ/ssh_config -L ${base}01:127.0.0.1:$PORT \
+ -oClearAllForwardings=yes somehost
+if [ $? != 0 ]; then
+ fail "connection failed with cleared local forwarding"
+else
+ # this one should fail
+ ${SSH} -F $OBJ/ssh_config -p ${base}01 somehost true \
+ >>$TEST_REGRESS_LOGFILE 2>&1 && \
+ fail "local forwarding not cleared"
+fi
+${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost 2>/dev/null
+
+trace "clear remote forward"
+rm -f $CTL
+${SSH} -S $CTL -N -M -f -F $OBJ/ssh_config -R ${base}01:127.0.0.1:$PORT \
+ -oClearAllForwardings=yes somehost
+if [ $? != 0 ]; then
+ fail "connection failed with cleared remote forwarding"
+else
+ # this one should fail
+ ${SSH} -F $OBJ/ssh_config -p ${base}01 somehost true \
+ >>$TEST_REGRESS_LOGFILE 2>&1 && \
+ fail "remote forwarding not cleared"
+fi
+${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost 2>/dev/null
+
+trace "stdio forwarding"
+cmd="${SSH} -F $OBJ/ssh_config"
+$cmd -o "ProxyCommand $cmd -q -W localhost:$PORT somehost" somehost true
+if [ $? != 0 ]; then
+ fail "stdio forwarding"
+fi
+
+echo "LocalForward ${base}01 127.0.0.1:$PORT" >> $OBJ/ssh_config
+echo "RemoteForward ${base}02 127.0.0.1:${base}01" >> $OBJ/ssh_config
+
+trace "config file: start forwarding, fork to background"
+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' \
+ somehost cat ${DATA} > ${COPY}
+test -s ${COPY} || fail "failed copy of ${DATA}"
+cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
+
+${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost 2>/dev/null
+
+trace "transfer over chained unix domain socket forwards and check result"
+rm -f $OBJ/unix-[123].fwd
+rm -f $CTL $CTL.[123]
+${SSH} -S $CTL -N -M -f -F $OBJ/ssh_config -R${base}01:[$OBJ/unix-1.fwd] somehost
+${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' \
+ somehost cat ${DATA} > ${COPY}
+test -s ${COPY} || fail "failed copy ${DATA}"
+cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
+
+${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost 2>/dev/null
+${SSH} -F $OBJ/ssh_config -S $CTL.1 -O exit somehost 2>/dev/null
+${SSH} -F $OBJ/ssh_config -S $CTL.2 -O exit somehost 2>/dev/null
+${SSH} -F $OBJ/ssh_config -S $CTL.3 -O exit somehost 2>/dev/null
+
diff --git a/regress/host-expand.sh b/regress/host-expand.sh
new file mode 100644
index 00000000..9444f7fb
--- /dev/null
+++ b/regress/host-expand.sh
@@ -0,0 +1,16 @@
+# $OpenBSD: host-expand.sh,v 1.5 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="expand %h and %n"
+
+echo 'PermitLocalCommand yes' >> $OBJ/ssh_proxy
+printf 'LocalCommand printf "%%%%s\\n" "%%n" "%%h"\n' >> $OBJ/ssh_proxy
+
+cat >$OBJ/expect <<EOE
+somehost
+127.0.0.1
+EOE
+
+${SSH} -F $OBJ/ssh_proxy somehost true >$OBJ/actual
+diff $OBJ/expect $OBJ/actual || fail "$tid"
+
diff --git a/regress/hostkey-agent.sh b/regress/hostkey-agent.sh
new file mode 100644
index 00000000..d6736e24
--- /dev/null
+++ b/regress/hostkey-agent.sh
@@ -0,0 +1,53 @@
+# $OpenBSD: hostkey-agent.sh,v 1.11 2019/12/16 02:39:05 djm Exp $
+# Placed in the Public Domain.
+
+tid="hostkey agent"
+
+rm -f $OBJ/agent-key.* $OBJ/ssh_proxy.orig $OBJ/known_hosts.orig
+
+trace "start agent"
+eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null
+r=$?
+[ $r -ne 0 ] && fatal "could not start ssh-agent: exit code $r"
+
+grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig
+echo "HostKeyAgent $SSH_AUTH_SOCK" >> $OBJ/sshd_proxy.orig
+
+trace "load hostkeys"
+for k in $SSH_KEYTYPES ; do
+ ${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k"
+ (
+ printf 'localhost-with-alias,127.0.0.1,::1 '
+ cat $OBJ/agent-key.$k.pub
+ ) >> $OBJ/known_hosts.orig
+ ${SSHADD} $OBJ/agent-key.$k >/dev/null 2>&1 || \
+ fatal "couldn't load key $OBJ/agent-key.$k"
+ echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy.orig
+ # Remove private key so the server can't use it.
+ rm $OBJ/agent-key.$k || fatal "couldn't rm $OBJ/agent-key.$k"
+done
+cp $OBJ/known_hosts.orig $OBJ/known_hosts
+
+unset SSH_AUTH_SOCK
+
+for ps in yes; do
+ for k in $SSH_KEYTYPES ; do
+ verbose "key type $k privsep=$ps"
+ cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
+ echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy
+ echo "HostKeyAlgorithms $k" >> $OBJ/sshd_proxy
+ opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy"
+ cp $OBJ/known_hosts.orig $OBJ/known_hosts
+ SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'`
+ if [ $? -ne 0 ]; then
+ fail "privsep=$ps failed"
+ fi
+ if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then
+ fail "bad SSH_CONNECTION key type $k privsep=$ps"
+ fi
+ done
+done
+
+trace "kill agent"
+${SSHAGENT} -k > /dev/null
+
diff --git a/regress/hostkey-rotate.sh b/regress/hostkey-rotate.sh
new file mode 100644
index 00000000..c3e100c3
--- /dev/null
+++ b/regress/hostkey-rotate.sh
@@ -0,0 +1,121 @@
+# $OpenBSD: hostkey-rotate.sh,v 1.8 2019/11/26 23:43:10 djm Exp $
+# Placed in the Public Domain.
+
+tid="hostkey rotate"
+
+rm -f $OBJ/hkr.* $OBJ/ssh_proxy.orig
+
+grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig
+echo "UpdateHostkeys=yes" >> $OBJ/ssh_proxy
+rm $OBJ/known_hosts
+
+# The "primary" key type is ed25519 since it's supported even when built
+# without OpenSSL. The secondary is RSA if it's supported.
+primary="ssh-ed25519"
+secondary="$primary"
+
+trace "prepare hostkeys"
+nkeys=0
+all_algs=""
+for k in $SSH_HOSTKEY_TYPES; do
+ ${SSHKEYGEN} -qt $k -f $OBJ/hkr.$k -N '' || fatal "ssh-keygen $k"
+ echo "Hostkey $OBJ/hkr.${k}" >> $OBJ/sshd_proxy.orig
+ nkeys=`expr $nkeys + 1`
+ test "x$all_algs" = "x" || all_algs="${all_algs},"
+ all_algs="${all_algs}$k"
+ case "$k" in
+ ssh-rsa) secondary="ssh-rsa" ;;
+ esac
+done
+
+dossh() {
+ # All ssh should succeed in this test
+ ${SSH} -F $OBJ/ssh_proxy "$@" x true || fail "ssh $@ failed"
+}
+
+expect_nkeys() {
+ _expected=$1
+ _message=$2
+ _n=`wc -l $OBJ/known_hosts | awk '{ print $1 }'` || fatal "wc failed"
+ [ "x$_n" = "x$_expected" ] || fail "$_message (got $_n wanted $_expected)"
+}
+
+check_key_present() {
+ _type=$1
+ _kfile=$2
+ test "x$_kfile" = "x" && _kfile="$OBJ/hkr.${_type}.pub"
+ _kpub=`awk "/$_type /"' { print $2 }' < $_kfile` || \
+ fatal "awk failed"
+ fgrep "$_kpub" $OBJ/known_hosts > /dev/null
+}
+
+cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
+
+# Connect to sshd with StrictHostkeyChecking=no
+verbose "learn hostkey with StrictHostKeyChecking=no"
+>$OBJ/known_hosts
+dossh -oHostKeyAlgorithms=$primary -oStrictHostKeyChecking=no
+# Verify no additional keys learned
+expect_nkeys 1 "unstrict connect keys"
+check_key_present $primary || fail "unstrict didn't learn key"
+
+# Connect to sshd as usual
+verbose "learn additional hostkeys"
+dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$all_algs
+# Check that other keys learned
+expect_nkeys $nkeys "learn hostkeys"
+for k in $SSH_HOSTKEY_TYPES; do
+ check_key_present $k || fail "didn't learn keytype $k"
+done
+
+# Check each key type
+for k in $SSH_HOSTKEY_TYPES; do
+ verbose "learn additional hostkeys, type=$k"
+ dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$k,$all_algs
+ expect_nkeys $nkeys "learn hostkeys $k"
+ check_key_present $k || fail "didn't learn $k correctly"
+done
+
+# Change one hostkey (non primary) and relearn
+if [ "$primary" != "$secondary" ]; then
+ verbose "learn changed non-primary hostkey type=${secondary}"
+ mv $OBJ/hkr.${secondary}.pub $OBJ/hkr.${secondary}.pub.old
+ rm -f $OBJ/hkr.${secondary}
+ ${SSHKEYGEN} -qt ${secondary} -f $OBJ/hkr.${secondary} -N '' || \
+ fatal "ssh-keygen $secondary"
+ dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$all_algs
+ # Check that the key was replaced
+ expect_nkeys $nkeys "learn hostkeys"
+ check_key_present ${secondary} $OBJ/hkr.${secondary}.pub.old && \
+ fail "old key present"
+ check_key_present ${secondary} || fail "didn't learn changed key"
+fi
+
+# Add new hostkey (primary type) to sshd and connect
+verbose "learn new primary hostkey"
+${SSHKEYGEN} -qt ${primary} -f $OBJ/hkr.${primary}-new -N '' || fatal "ssh-keygen ed25519"
+( cat $OBJ/sshd_proxy.orig ; echo HostKey $OBJ/hkr.${primary}-new ) \
+ > $OBJ/sshd_proxy
+# Check new hostkey added
+dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=${primary},$all_algs
+expect_nkeys `expr $nkeys + 1` "learn hostkeys"
+check_key_present ${primary} || fail "current key missing"
+check_key_present ${primary} $OBJ/hkr.${primary}-new.pub || fail "new key missing"
+
+# Remove old hostkey (primary type) from sshd
+verbose "rotate primary hostkey"
+cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
+mv $OBJ/hkr.${primary}.pub $OBJ/hkr.${primary}.pub.old
+mv $OBJ/hkr.${primary}-new.pub $OBJ/hkr.${primary}.pub
+mv $OBJ/hkr.${primary}-new $OBJ/hkr.${primary}
+# Check old hostkey removed
+dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=${primary},$all_algs
+expect_nkeys $nkeys "learn hostkeys"
+check_key_present ${primary} $OBJ/hkr.${primary}.pub.old && fail "old key present"
+check_key_present ${primary} || fail "didn't learn changed key"
+
+# Connect again, forcing rotated key
+verbose "check rotate primary hostkey"
+dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=${primary}
+expect_nkeys 1 "learn hostkeys"
+check_key_present ${primary} || fail "didn't learn changed key"
diff --git a/regress/integrity.sh b/regress/integrity.sh
new file mode 100644
index 00000000..bc030cb7
--- /dev/null
+++ b/regress/integrity.sh
@@ -0,0 +1,76 @@
+# $OpenBSD: integrity.sh,v 1.24 2020/01/21 08:06:27 djm Exp $
+# Placed in the Public Domain.
+
+tid="integrity"
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+
+# start at byte 2900 (i.e. after kex) and corrupt at different offsets
+tries=10
+startoffset=2900
+macs=`${SSH} -Q mac`
+# The following are not MACs, but ciphers with integrated integrity. They are
+# handled specially below.
+macs="$macs `${SSH} -Q cipher-auth`"
+
+# avoid DH group exchange as the extra traffic makes it harder to get the
+# offset into the stream right.
+#echo "KexAlgorithms -diffie-hellman-group*" \
+# >> $OBJ/ssh_proxy
+
+# sshd-command for proxy (see test-exec.sh)
+cmd="$SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy"
+
+for m in $macs; do
+ trace "test $tid: mac $m"
+ elen=0
+ epad=0
+ emac=0
+ etmo=0
+ ecnt=0
+ skip=0
+ for off in `jot $tries $startoffset`; do
+ skip=`expr $skip - 1`
+ if [ $skip -gt 0 ]; then
+ # avoid modifying the high bytes of the length
+ continue
+ fi
+ cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+ # modify output from sshd at offset $off
+ pxy="proxycommand=$cmd | $OBJ/modpipe -wm xor:$off:1"
+ if ${SSH} -Q cipher-auth | grep "^${m}\$" >/dev/null 2>&1 ; then
+ echo "Ciphers=$m" >> $OBJ/sshd_proxy
+ macopt="-c $m"
+ else
+ echo "Ciphers=aes128-ctr" >> $OBJ/sshd_proxy
+ echo "MACs=$m" >> $OBJ/sshd_proxy
+ macopt="-m $m -c aes128-ctr"
+ fi
+ verbose "test $tid: $m @$off"
+ ${SSH} $macopt -F $OBJ/ssh_proxy -o "$pxy" \
+ -oServerAliveInterval=1 -oServerAliveCountMax=30 \
+ 999.999.999.999 'printf "%4096s" " "' >/dev/null
+ if [ $? -eq 0 ]; then
+ fail "ssh -m $m succeeds with bit-flip at $off"
+ fi
+ ecnt=`expr $ecnt + 1`
+ out=$(egrep -v "^debug" $TEST_SSH_LOGFILE | tail -2 | \
+ tr -s '\r\n' '.')
+ case "$out" in
+ Bad?packet*) elen=`expr $elen + 1`; skip=3;;
+ Corrupted?MAC* | *message?authentication?code?incorrect*)
+ emac=`expr $emac + 1`; skip=0;;
+ padding*) epad=`expr $epad + 1`; skip=0;;
+ *Timeout,?server*)
+ etmo=`expr $etmo + 1`; skip=0;;
+ *) fail "unexpected error mac $m at $off: $out";;
+ esac
+ done
+ verbose "test $tid: $ecnt errors: mac $emac padding $epad length $elen timeout $etmo"
+ if [ $emac -eq 0 ]; then
+ fail "$m: no mac errors"
+ fi
+ expect=`expr $ecnt - $epad - $elen - $etmo`
+ if [ $emac -ne $expect ]; then
+ fail "$m: expected $expect mac errors, got $emac"
+ fi
+done
diff --git a/regress/kextype.sh b/regress/kextype.sh
new file mode 100644
index 00000000..e2718990
--- /dev/null
+++ b/regress/kextype.sh
@@ -0,0 +1,25 @@
+# $OpenBSD: kextype.sh,v 1.6 2015/03/24 20:19:15 markus Exp $
+# Placed in the Public Domain.
+
+tid="login with different key exchange algorithms"
+
+TIME=/usr/bin/time
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
+
+# Make server accept all key exchanges.
+ALLKEX=`${SSH} -Q kex`
+KEXOPT=`echo $ALLKEX | tr ' ' ,`
+echo "KexAlgorithms=$KEXOPT" >> $OBJ/sshd_proxy
+
+tries="1 2 3 4"
+for k in `${SSH} -Q kex`; do
+ verbose "kex $k"
+ for i in $tries; do
+ ${SSH} -F $OBJ/ssh_proxy -o KexAlgorithms=$k x true
+ if [ $? -ne 0 ]; then
+ fail "ssh kex $k"
+ fi
+ done
+done
+
diff --git a/regress/key-options.sh b/regress/key-options.sh
new file mode 100644
index 00000000..097f46eb
--- /dev/null
+++ b/regress/key-options.sh
@@ -0,0 +1,124 @@
+# $OpenBSD: key-options.sh,v 1.9 2018/07/03 13:53:26 djm Exp $
+# Placed in the Public Domain.
+
+tid="key options"
+
+origkeys="$OBJ/authkeys_orig"
+authkeys="$OBJ/authorized_keys_${USER}"
+cp $authkeys $origkeys
+
+# Allocating ptys can require privileges on some platforms.
+skip_pty=""
+if ! config_defined HAVE_OPENPTY && [ "x$SUDO" == "x" ]; then
+ skip_pty="no openpty(3) and SUDO not set"
+fi
+
+# Test command= forced command
+for c in 'command="echo bar"' 'no-pty,command="echo bar"'; do
+ sed "s/.*/$c &/" $origkeys >$authkeys
+ verbose "key option $c"
+ r=`${SSH} -q -F $OBJ/ssh_proxy somehost echo foo`
+ if [ "$r" = "foo" ]; then
+ fail "key option forced command not restricted"
+ fi
+ if [ "$r" != "bar" ]; then
+ fail "key option forced command not executed"
+ fi
+done
+
+# Test no-pty
+expect_pty_succeed() {
+ which=$1
+ opts=$2
+ rm -f $OBJ/data
+ sed "s/.*/$opts &/" $origkeys >$authkeys
+ verbose "key option pty $which"
+ [ "x$skip_pty" != "x" ] && verbose "skipped because $skip_pty" && return
+ ${SSH} -ttq -F $OBJ/ssh_proxy somehost "tty > $OBJ/data; exit 0"
+ if [ $? -ne 0 ] ; then
+ fail "key option failed $which"
+ else
+ r=`cat $OBJ/data`
+ case "$r" in
+ /dev/*) ;;
+ *) fail "key option failed $which (pty $r)" ;;
+ esac
+ fi
+}
+expect_pty_fail() {
+ which=$1
+ opts=$2
+ rm -f $OBJ/data
+ sed "s/.*/$opts &/" $origkeys >$authkeys
+ verbose "key option pty $which"
+ [ "x$skip_pty" != "x" ] && verbose "skipped because $skip_pty" && return
+ ${SSH} -ttq -F $OBJ/ssh_proxy somehost "tty > $OBJ/data; exit 0"
+ if [ $? -eq 0 ]; then
+ r=`cat $OBJ/data`
+ if [ -e "$r" ]; then
+ fail "key option failed $which (pty $r)"
+ fi
+ case "$r" in
+ /dev/*) fail "key option failed $which (pty $r)" ;;
+ *) ;;
+ esac
+ fi
+}
+# First ensure that we can allocate a pty by default.
+expect_pty_succeed "default" ""
+expect_pty_fail "no-pty" "no-pty"
+expect_pty_fail "restrict" "restrict"
+expect_pty_succeed "restrict,pty" "restrict,pty"
+
+# Test environment=
+# XXX this can fail if ~/.ssh/environment exists for the user running the test
+echo 'PermitUserEnvironment yes' >> $OBJ/sshd_proxy
+sed 's/.*/environment="FOO=bar" &/' $origkeys >$authkeys
+verbose "key option environment"
+r=`${SSH} -q -F $OBJ/ssh_proxy somehost 'echo $FOO'`
+if [ "$r" != "bar" ]; then
+ fail "key option environment not set"
+fi
+
+# Test from= restriction
+start_sshd
+for f in 127.0.0.1 '127.0.0.0\/8'; do
+ cat $origkeys >$authkeys
+ ${SSH} -q -F $OBJ/ssh_proxy somehost true
+ if [ $? -ne 0 ]; then
+ fail "key option failed without restriction"
+ fi
+
+ sed 's/.*/from="'"$f"'" &/' $origkeys >$authkeys
+ from=`head -1 $authkeys | cut -f1 -d ' '`
+ verbose "key option $from"
+ r=`${SSH} -q -F $OBJ/ssh_proxy somehost 'echo true'`
+ if [ "$r" = "true" ]; then
+ fail "key option $from not restricted"
+ fi
+
+ r=`${SSH} -q -F $OBJ/ssh_config somehost 'echo true'`
+ if [ "$r" != "true" ]; then
+ fail "key option $from not allowed but should be"
+ fi
+done
+
+check_valid_before() {
+ which=$1
+ opts=$2
+ expect=$3
+ sed "s/.*/$opts &/" $origkeys >$authkeys
+ verbose "key option expiry-time $which"
+ ${SSH} -q -F $OBJ/ssh_proxy somehost true
+ r=$?
+ case "$expect" in
+ fail) test $r -eq 0 && fail "key option succeeded $which" ;;
+ pass) test $r -ne 0 && fail "key option failed $which" ;;
+ *) fatal "unknown expectation $expect" ;;
+ esac
+}
+check_valid_before "default" "" "pass"
+check_valid_before "invalid" 'expiry-time="INVALID"' "fail"
+check_valid_before "expired" 'expiry-time="19990101"' "fail"
+check_valid_before "valid" 'expiry-time="20380101"' "pass"
+
diff --git a/regress/keygen-change.sh b/regress/keygen-change.sh
new file mode 100644
index 00000000..3863e33b
--- /dev/null
+++ b/regress/keygen-change.sh
@@ -0,0 +1,22 @@
+# $OpenBSD: keygen-change.sh,v 1.9 2019/12/16 02:39:05 djm Exp $
+# Placed in the Public Domain.
+
+tid="change passphrase for key"
+
+S1="secret1"
+S2="2secret"
+
+for t in $SSH_KEYTYPES; do
+ trace "generating $t key"
+ rm -f $OBJ/$t-key
+ ${SSHKEYGEN} -q -N ${S1} -t $t -f $OBJ/$t-key
+ if [ $? -eq 0 ]; then
+ ${SSHKEYGEN} -p -P ${S1} -N ${S2} -f $OBJ/$t-key > /dev/null
+ if [ $? -ne 0 ]; then
+ fail "ssh-keygen -p failed for $t-key"
+ fi
+ else
+ fail "ssh-keygen for $t-key failed"
+ fi
+ rm -f $OBJ/$t-key $OBJ/$t-key.pub
+done
diff --git a/regress/keygen-comment.sh b/regress/keygen-comment.sh
new file mode 100644
index 00000000..af571d39
--- /dev/null
+++ b/regress/keygen-comment.sh
@@ -0,0 +1,52 @@
+#    Placed in the Public Domain.
+
+tid="Comment extraction from private key"
+
+S1="secret1"
+
+check_fingerprint () {
+ file="$1"
+ comment="$2"
+ trace "fingerprinting $file"
+ if ! ${SSHKEYGEN} -l -E sha256 -f $file > $OBJ/$t-fgp ; then
+ fail "ssh-keygen -l failed for $t-key"
+ fi
+ if ! egrep "^([0-9]+) SHA256:(.){43} ${comment} \(.*\)\$" \
+ $OBJ/$t-fgp >/dev/null 2>&1 ; then
+ fail "comment is not correctly recovered for $t-key"
+ fi
+ rm -f $OBJ/$t-fgp
+}
+
+for fmt in '' RFC4716 PKCS8 PEM; do
+ for t in $SSH_KEYTYPES; do
+ trace "generating $t key in '$fmt' format"
+ rm -f $OBJ/$t-key*
+ oldfmt=""
+ case "$fmt" in
+ PKCS8|PEM) oldfmt=1 ;;
+ esac
+ # Some key types like ssh-ed25519 and *@openssh.com are never
+ # stored in old formats.
+ case "$t" in
+ ssh-ed25519|*openssh.com) test -z "$oldfmt" || continue ;;
+ esac
+ comment="foo bar"
+ fmtarg=""
+ test -z "$fmt" || fmtarg="-m $fmt"
+ ${SSHKEYGEN} $fmtarg -N '' -C "${comment}" \
+ -t $t -f $OBJ/$t-key >/dev/null 2>&1 || \
+ fatal "keygen of $t in format $fmt failed"
+ check_fingerprint $OBJ/$t-key "${comment}"
+ check_fingerprint $OBJ/$t-key.pub "${comment}"
+ # Output fingerprint using only private file
+ trace "fingerprinting $t key using private key file"
+ rm -f $OBJ/$t-key.pub
+ if [ ! -z "$oldfmt" ] ; then
+ # Comment cannot be recovered from old format keys.
+ comment="no comment"
+ fi
+ check_fingerprint $OBJ/$t-key "${comment}"
+ rm -f $OBJ/$t-key*
+ done
+done
diff --git a/regress/keygen-convert.sh b/regress/keygen-convert.sh
new file mode 100644
index 00000000..fce110ea
--- /dev/null
+++ b/regress/keygen-convert.sh
@@ -0,0 +1,41 @@
+# $OpenBSD: keygen-convert.sh,v 1.2 2019/07/23 07:55:29 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
+
+for t in $types; 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"
+
+ 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 "import $t rfc4716 public"
+ ${SSHKEYGEN} -q -i -f $OBJ/$t-key-rfc >$OBJ/$t-rfc-imported || \
+ fail "$t import rfc4716 public"
+
+ 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"
+
+ 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
+done
diff --git a/regress/keygen-knownhosts.sh b/regress/keygen-knownhosts.sh
new file mode 100644
index 00000000..37af3476
--- /dev/null
+++ b/regress/keygen-knownhosts.sh
@@ -0,0 +1,220 @@
+# $OpenBSD: keygen-knownhosts.sh,v 1.4 2018/06/01 03:52:37 djm Exp $
+# Placed in the Public Domain.
+
+tid="ssh-keygen known_hosts"
+
+rm -f $OBJ/kh.*
+
+# Generate some keys for testing (just ed25519 for speed) and make a hosts file.
+for x in host-a host-b host-c host-d host-e host-f host-a2 host-b2; do
+ ${SSHKEYGEN} -qt ed25519 -f $OBJ/kh.$x -C "$x" -N "" || \
+ fatal "ssh-keygen failed"
+ # Add a comment that we expect should be preserved.
+ echo "# $x" >> $OBJ/kh.hosts
+ (
+ case "$x" in
+ host-a|host-b) printf "$x " ;;
+ host-c) printf "@cert-authority $x " ;;
+ host-d) printf "@revoked $x " ;;
+ host-e) printf "host-e* " ;;
+ host-f) printf "host-f,host-g,host-h " ;;
+ host-a2) printf "host-a " ;;
+ host-b2) printf "host-b " ;;
+ esac
+ cat $OBJ/kh.${x}.pub
+ # Blank line should be preserved.
+ echo "" >> $OBJ/kh.hosts
+ ) >> $OBJ/kh.hosts
+done
+
+# Generate a variant with an invalid line. We'll use this for most tests,
+# because keygen should be able to cope and it should be preserved in any
+# output file.
+cat $OBJ/kh.hosts >> $OBJ/kh.invalid
+echo "host-i " >> $OBJ/kh.invalid
+
+cp $OBJ/kh.invalid $OBJ/kh.invalid.orig
+cp $OBJ/kh.hosts $OBJ/kh.hosts.orig
+
+expect_key() {
+ _host=$1
+ _hosts=$2
+ _key=$3
+ _line=$4
+ _mark=$5
+ _marker=""
+ test "x$_mark" = "xCA" && _marker="@cert-authority "
+ test "x$_mark" = "xREVOKED" && _marker="@revoked "
+ test "x$_line" != "x" &&
+ echo "# Host $_host found: line $_line $_mark" >> $OBJ/kh.expect
+ printf "${_marker}$_hosts " >> $OBJ/kh.expect
+ cat $OBJ/kh.${_key}.pub >> $OBJ/kh.expect ||
+ fatal "${_key}.pub missing"
+}
+
+check_find() {
+ _host=$1
+ _name=$2
+ shift; shift
+ ${SSHKEYGEN} "$@" -f $OBJ/kh.invalid -F $_host > $OBJ/kh.result
+ if ! diff -w $OBJ/kh.expect $OBJ/kh.result ; then
+ fail "didn't find $_name"
+ fi
+}
+
+check_find_exit_code() {
+ _host=$1
+ _name=$2
+ _keygenopt=$3
+ _exp_exit_code=$4
+ ${SSHKEYGEN} $_keygenopt -f $OBJ/kh.invalid -F $_host > /dev/null
+ if [ "$?" != "$_exp_exit_code" ] ; then
+ fail "Unexpected exit code $_name"
+ fi
+}
+
+# Find key
+rm -f $OBJ/kh.expect
+expect_key host-a host-a host-a 2
+expect_key host-a host-a host-a2 20
+check_find host-a "simple find"
+
+# find CA key
+rm -f $OBJ/kh.expect
+expect_key host-c host-c host-c 8 CA
+check_find host-c "find CA key"
+
+# find revoked key
+rm -f $OBJ/kh.expect
+expect_key host-d host-d host-d 11 REVOKED
+check_find host-d "find revoked key"
+
+# find key with wildcard
+rm -f $OBJ/kh.expect
+expect_key host-e.somedomain "host-e*" host-e 14
+check_find host-e.somedomain "find wildcard key"
+
+# find key among multiple hosts
+rm -f $OBJ/kh.expect
+expect_key host-h "host-f,host-g,host-h " host-f 17
+check_find host-h "find multiple hosts"
+
+# Check exit code, known host
+check_find_exit_code host-a "known host" "-q" "0"
+
+# Check exit code, unknown host
+check_find_exit_code host-aa "unknown host" "-q" "1"
+
+# Check exit code, the hash mode, known host
+check_find_exit_code host-a "known host" "-q -H" "0"
+
+# Check exit code, the hash mode, unknown host
+check_find_exit_code host-aa "unknown host" "-q -H" "1"
+
+check_hashed_find() {
+ _host=$1
+ _name=$2
+ _file=$3
+ test "x$_file" = "x" && _file=$OBJ/kh.invalid
+ ${SSHKEYGEN} -f $_file -HF $_host | grep '|1|' | \
+ sed "s/^[^ ]*/$_host/" > $OBJ/kh.result
+ if ! diff -w $OBJ/kh.expect $OBJ/kh.result ; then
+ fail "didn't find $_name"
+ fi
+}
+
+# Find key and hash
+rm -f $OBJ/kh.expect
+expect_key host-a host-a host-a
+expect_key host-a host-a host-a2
+check_hashed_find host-a "find simple and hash"
+
+# Find CA key and hash
+rm -f $OBJ/kh.expect
+expect_key host-c host-c host-c "" CA
+# CA key output is not hashed.
+check_find host-c "find simple and hash" -Hq
+
+# Find revoked key and hash
+rm -f $OBJ/kh.expect
+expect_key host-d host-d host-d "" REVOKED
+# Revoked key output is not hashed.
+check_find host-d "find simple and hash" -Hq
+
+# find key with wildcard and hash
+rm -f $OBJ/kh.expect
+expect_key host-e "host-e*" host-e ""
+# Key with wildcard hostname should not be hashed.
+check_find host-e "find wildcard key" -Hq
+
+# find key among multiple hosts
+rm -f $OBJ/kh.expect
+# Comma-separated hostnames should be expanded and hashed.
+expect_key host-f "host-h " host-f
+expect_key host-g "host-h " host-f
+expect_key host-h "host-h " host-f
+check_hashed_find host-h "find multiple hosts"
+
+# Attempt remove key on invalid file.
+cp $OBJ/kh.invalid.orig $OBJ/kh.invalid
+${SSHKEYGEN} -qf $OBJ/kh.invalid -R host-a 2>/dev/null
+diff $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "remove on invalid succeeded"
+
+# Remove key
+cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
+${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-a 2>/dev/null
+grep -v "^host-a " $OBJ/kh.hosts.orig > $OBJ/kh.expect
+diff $OBJ/kh.hosts $OBJ/kh.expect || fail "remove simple"
+
+# Remove CA key
+cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
+${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-c 2>/dev/null
+# CA key should not be removed.
+diff $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove CA"
+
+# Remove revoked key
+cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
+${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-d 2>/dev/null
+# revoked key should not be removed.
+diff $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove revoked"
+
+# Remove wildcard
+cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
+${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-e.blahblah 2>/dev/null
+grep -v "^host-e[*] " $OBJ/kh.hosts.orig > $OBJ/kh.expect
+diff $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard"
+
+# Remove multiple
+cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
+${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-h 2>/dev/null
+grep -v "^host-f," $OBJ/kh.hosts.orig > $OBJ/kh.expect
+diff $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard"
+
+# Attempt hash on invalid file
+cp $OBJ/kh.invalid.orig $OBJ/kh.invalid
+${SSHKEYGEN} -qf $OBJ/kh.invalid -H 2>/dev/null && fail "hash invalid succeeded"
+diff $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "invalid file modified"
+
+# Hash valid file
+cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
+${SSHKEYGEN} -qf $OBJ/kh.hosts -H 2>/dev/null || fail "hash failed"
+diff $OBJ/kh.hosts.old $OBJ/kh.hosts.orig || fail "backup differs"
+grep "^host-[abfgh]" $OBJ/kh.hosts && fail "original hostnames persist"
+
+cp $OBJ/kh.hosts $OBJ/kh.hashed.orig
+
+# Test lookup
+rm -f $OBJ/kh.expect
+expect_key host-a host-a host-a
+expect_key host-a host-a host-a2
+check_hashed_find host-a "find simple in hashed" $OBJ/kh.hosts
+
+# Test multiple expanded
+rm -f $OBJ/kh.expect
+expect_key host-h host-h host-f
+check_hashed_find host-h "find simple in hashed" $OBJ/kh.hosts
+
+# Test remove
+cp $OBJ/kh.hashed.orig $OBJ/kh.hashed
+${SSHKEYGEN} -qf $OBJ/kh.hashed -R host-a 2>/dev/null
+${SSHKEYGEN} -qf $OBJ/kh.hashed -F host-a && fail "found key after hashed remove"
diff --git a/regress/keygen-moduli.sh b/regress/keygen-moduli.sh
new file mode 100644
index 00000000..8be53f92
--- /dev/null
+++ b/regress/keygen-moduli.sh
@@ -0,0 +1,27 @@
+# $OpenBSD: keygen-moduli.sh,v 1.4 2020/01/02 13:25:38 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="keygen moduli"
+
+dhgex=0
+for kex in `${SSH} -Q kex`; do
+ case $kex in
+ diffie-hellman-group*) dhgex=1 ;;
+ esac
+done
+
+# Try "start at the beginning and stop after 1", "skip 1 then stop after 1"
+# and "skip 2 and run to the end with checkpointing". Since our test data
+# file has 3 lines, these should always result in 1 line of output.
+if [ "x$dhgex" = "x1" ]; then
+ for i in "-O lines=1" "-O start-line=1 -O lines=1" "-O start-line=2 -O checkpoint=$OBJ/moduli.ckpt"; do
+ trace "keygen $i"
+ rm -f $OBJ/moduli.out $OBJ/moduli.ckpt
+ ${SSHKEYGEN} -M screen -f ${SRC}/moduli.in $i $OBJ/moduli.out 2>/dev/null || \
+ fail "keygen screen failed $i"
+ lines=`wc -l <$OBJ/moduli.out`
+ test "$lines" -eq "1" || fail "expected 1 line, got $lines"
+ done
+fi
+
+rm -f $OBJ/moduli.out $OBJ/moduli.ckpt
diff --git a/regress/keys-command.sh b/regress/keys-command.sh
new file mode 100644
index 00000000..33b6e7b4
--- /dev/null
+++ b/regress/keys-command.sh
@@ -0,0 +1,81 @@
+# $OpenBSD: keys-command.sh,v 1.6 2019/07/25 08:48:11 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="authorized keys from command"
+
+if [ -z "$SUDO" -a ! -w /var/run ]; then
+ echo "skipped (SUDO not set)"
+ echo "need SUDO to create file in /var/run, test won't work without"
+ exit 0
+fi
+
+rm -f $OBJ/keys-command-args
+
+touch $OBJ/keys-command-args
+chmod a+rw $OBJ/keys-command-args
+
+expected_key_text=`awk '{ print $2 }' < $OBJ/ssh-ed25519.pub`
+expected_key_fp=`$SSHKEYGEN -lf $OBJ/ssh-ed25519.pub | awk '{ print $2 }'`
+
+# Establish a AuthorizedKeysCommand in /var/run where it will have
+# acceptable directory permissions.
+KEY_COMMAND="/var/run/keycommand_${LOGNAME}.$$"
+trap "${SUDO} rm -f ${KEY_COMMAND}" 0
+cat << _EOF | $SUDO sh -c "rm -f '$KEY_COMMAND' ; cat > '$KEY_COMMAND'"
+#!/bin/sh
+echo args: "\$@" >> $OBJ/keys-command-args
+echo "$PATH" | grep -q mekmitasdigoat && exit 7
+test "x\$1" != "x${LOGNAME}" && exit 1
+if test $# -eq 6 ; then
+ test "x\$2" != "xblah" && exit 2
+ test "x\$3" != "x${expected_key_text}" && exit 3
+ test "x\$4" != "xssh-rsa" && exit 4
+ test "x\$5" != "x${expected_key_fp}" && exit 5
+ test "x\$6" != "xblah" && exit 6
+fi
+exec cat "$OBJ/authorized_keys_${LOGNAME}"
+_EOF
+$SUDO chmod 0755 "$KEY_COMMAND"
+
+if ! $OBJ/check-perm -m keys-command $KEY_COMMAND ; then
+ echo "skipping: $KEY_COMMAND is unsuitable as AuthorizedKeysCommand"
+ $SUDO rm -f $KEY_COMMAND
+ exit 0
+fi
+
+if [ -x $KEY_COMMAND ]; then
+ cp $OBJ/sshd_proxy $OBJ/sshd_proxy.bak
+
+ verbose "AuthorizedKeysCommand with arguments"
+ (
+ grep -vi AuthorizedKeysFile $OBJ/sshd_proxy.bak
+ echo AuthorizedKeysFile none
+ echo AuthorizedKeysCommand $KEY_COMMAND %u blah %k %t %f blah
+ echo AuthorizedKeysCommandUser ${LOGNAME}
+ ) > $OBJ/sshd_proxy
+
+ # Ensure that $PATH is sanitised in sshd
+ env PATH=$PATH:/sbin/mekmitasdigoat \
+ ${SSH} -F $OBJ/ssh_proxy somehost true
+ if [ $? -ne 0 ]; then
+ fail "connect failed"
+ fi
+
+ verbose "AuthorizedKeysCommand without arguments"
+ # Check legacy behavior of no-args resulting in username being passed.
+ (
+ grep -vi AuthorizedKeysFile $OBJ/sshd_proxy.bak
+ echo AuthorizedKeysFile none
+ echo AuthorizedKeysCommand $KEY_COMMAND
+ echo AuthorizedKeysCommandUser ${LOGNAME}
+ ) > $OBJ/sshd_proxy
+
+ # Ensure that $PATH is sanitised in sshd
+ env PATH=$PATH:/sbin/mekmitasdigoat \
+ ${SSH} -F $OBJ/ssh_proxy somehost true
+ if [ $? -ne 0 ]; then
+ fail "connect failed"
+ fi
+else
+ echo "SKIPPED: $KEY_COMMAND not executable (/var/run mounted noexec?)"
+fi
diff --git a/regress/keyscan.sh b/regress/keyscan.sh
new file mode 100644
index 00000000..75a14ee0
--- /dev/null
+++ b/regress/keyscan.sh
@@ -0,0 +1,25 @@
+# $OpenBSD: keyscan.sh,v 1.13 2020/01/22 07:31:27 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="keyscan"
+
+for i in $SSH_KEYTYPES; do
+ if [ -z "$algs" ]; then
+ algs="$i"
+ else
+ algs="$algs,$i"
+ fi
+done
+echo "HostKeyAlgorithms $algs" >> $OBJ/sshd_config
+
+start_sshd
+
+for t in $SSH_KEYTYPES; do
+ trace "keyscan type $t"
+ ${SSHKEYSCAN} -t $t -T 15 -p $PORT 127.0.0.1 127.0.0.1 127.0.0.1 \
+ > /dev/null 2>&1
+ r=$?
+ if [ $r -ne 0 ]; then
+ fail "ssh-keyscan -t $t failed with: $r"
+ fi
+done
diff --git a/regress/keytype.sh b/regress/keytype.sh
new file mode 100644
index 00000000..20a8ceaf
--- /dev/null
+++ b/regress/keytype.sh
@@ -0,0 +1,83 @@
+# $OpenBSD: keytype.sh,v 1.10 2019/12/16 02:39:05 djm Exp $
+# Placed in the Public Domain.
+
+tid="login with different key types"
+
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
+
+# Construct list of key types based on what the built binaries support.
+ktypes=""
+for i in ${SSH_KEYTYPES}; do
+ case "$i" in
+ ssh-dss) ktypes="$ktypes dsa-1024" ;;
+ ssh-rsa) ktypes="$ktypes rsa-2048 rsa-3072" ;;
+ ssh-ed25519) ktypes="$ktypes ed25519-512" ;;
+ ecdsa-sha2-nistp256) ktypes="$ktypes ecdsa-256" ;;
+ ecdsa-sha2-nistp384) ktypes="$ktypes ecdsa-384" ;;
+ ecdsa-sha2-nistp521) ktypes="$ktypes ecdsa-521" ;;
+ sk-ssh-ed25519*) ktypes="$ktypes ed25519-sk" ;;
+ sk-ecdsa-sha2-nistp256*) ktypes="$ktypes ecdsa-sk" ;;
+ esac
+done
+
+for kt in $ktypes; do
+ rm -f $OBJ/key.$kt
+ xbits=`echo ${kt} | awk -F- '{print $2}'`
+ xtype=`echo ${kt} | awk -F- '{print $1}'`
+ case "$kt" in
+ *sk) type="$kt"; bits="n/a"; bits_arg="";;
+ *) type=$xtype; bits=$xbits; bits_arg="-b $bits";;
+ esac
+ verbose "keygen $type, $bits bits"
+ ${SSHKEYGEN} $bits_arg -q -N '' -t $type -f $OBJ/key.$kt || \
+ fail "ssh-keygen for type $type, $bits bits failed"
+done
+
+kname_to_ktype() {
+ case $1 in
+ dsa-1024) echo ssh-dss;;
+ ecdsa-256) echo ecdsa-sha2-nistp256;;
+ ecdsa-384) echo ecdsa-sha2-nistp384;;
+ ecdsa-521) echo ecdsa-sha2-nistp521;;
+ ed25519-512) echo ssh-ed25519;;
+ rsa-*) echo rsa-sha2-512,rsa-sha2-256,ssh-rsa;;
+ ed25519-sk) echo sk-ssh-ed25519@openssh.com;;
+ ecdsa-sk) echo sk-ecdsa-sha2-nistp256@openssh.com;;
+ esac
+}
+
+tries="1 2 3"
+for ut in $ktypes; do
+ user_type=`kname_to_ktype "$ut"`
+ htypes="$ut"
+ #htypes=$ktypes
+ for ht in $htypes; do
+ host_type=`kname_to_ktype "$ht"`
+ trace "ssh connect, userkey $ut, hostkey $ht"
+ (
+ grep -v HostKey $OBJ/sshd_proxy_bak
+ echo HostKey $OBJ/key.$ht
+ echo PubkeyAcceptedKeyTypes $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 HostKeyAlgorithms $host_type
+ ) > $OBJ/ssh_proxy
+ (
+ printf 'localhost-with-alias,127.0.0.1,::1 '
+ cat $OBJ/key.$ht.pub
+ ) > $OBJ/known_hosts
+ cat $OBJ/key.$ut.pub > $OBJ/authorized_keys_$USER
+ for i in $tries; do
+ verbose "userkey $ut, hostkey ${ht}"
+ ${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true
+ if [ $? -ne 0 ]; then
+ fail "ssh userkey $ut, hostkey $ht failed"
+ fi
+ done
+ done
+done
diff --git a/regress/krl.sh b/regress/krl.sh
new file mode 100644
index 00000000..c381225e
--- /dev/null
+++ b/regress/krl.sh
@@ -0,0 +1,217 @@
+# $OpenBSD: krl.sh,v 1.11 2019/12/16 02:39:05 djm Exp $
+# Placed in the Public Domain.
+
+tid="key revocation lists"
+
+# Use ed25519 by default since it's fast and it's supported when building
+# w/out OpenSSL. Populate ktype[2-4] with the other types if supported.
+ktype1=ed25519; ktype2=ed25519; ktype3=ed25519;
+ktype4=ed25519; ktype5=ed25519; ktype6=ed25519;
+for t in $SSH_KEYTYPES; do
+ case "$t" in
+ ecdsa*) ktype2=ecdsa ;;
+ ssh-rsa) ktype3=rsa ;;
+ ssh-dss) ktype4=dsa ;;
+ sk-ssh-ed25519@openssh.com) ktype5=ed25519-sk ;;
+ sk-ecdsa-sha2-nistp256@openssh.com) ktype6=ecdsa-sk ;;
+ esac
+done
+
+# Do most testing with ssh-keygen; it uses the same verification code as sshd.
+
+# Old keys will interfere with ssh-keygen.
+rm -f $OBJ/revoked-* $OBJ/krl-*
+
+# Generate a CA key
+$SSHKEYGEN -t $ktype1 -f $OBJ/revoked-ca -C "" -N "" > /dev/null ||
+ fatal "$SSHKEYGEN CA failed"
+$SSHKEYGEN -t $ktype2 -f $OBJ/revoked-ca2 -C "" -N "" > /dev/null ||
+ fatal "$SSHKEYGEN CA2 failed"
+
+# A specification that revokes some certificates by serial numbers
+# The serial pattern is chosen to ensure the KRL includes list, range and
+# bitmap sections.
+cat << EOF >> $OBJ/revoked-serials
+serial: 1-4
+serial: 10
+serial: 15
+serial: 30
+serial: 50
+serial: 90
+serial: 999
+# The following sum to 500-799
+serial: 500
+serial: 501
+serial: 502
+serial: 503-600
+serial: 700-797
+serial: 798
+serial: 799
+serial: 599-701
+# Some multiple consecutive serial number ranges
+serial: 10000-20000
+serial: 30000-40000
+EOF
+
+# A specification that revokes some certificated by key ID.
+touch $OBJ/revoked-keyid
+for n in 1 2 3 4 10 15 30 50 90 `jot 500 300` 999 1000 1001 1002; do
+ test "x$n" = "x499" && continue
+ # Fill in by-ID revocation spec.
+ echo "id: revoked $n" >> $OBJ/revoked-keyid
+done
+
+keygen() {
+ N=$1
+ f=$OBJ/revoked-`printf "%04d" $N`
+ # Vary the keytype. We use mostly ed25519 since this is fast and well
+ # supported.
+ keytype=$ktype1
+ case $N in
+ 2 | 10 | 510 | 1001) keytype=$ktype2 ;;
+ 4 | 30 | 520 | 1002) keytype=$ktype3 ;;
+ 8 | 50 | 530 | 1003) keytype=$ktype4 ;;
+ 16 | 70 | 540 | 1004) keytype=$ktype5 ;;
+ 32 | 90 | 550 | 1005) keytype=$ktype6 ;;
+ esac
+ $SSHKEYGEN -t $keytype -f $f -C "" -N "" > /dev/null \
+ || fatal "$SSHKEYGEN failed"
+ # Sign cert
+ $SSHKEYGEN -s $OBJ/revoked-ca -z $n -I "revoked $N" $f >/dev/null 2>&1 \
+ || fatal "$SSHKEYGEN sign failed"
+ echo $f
+}
+
+# Generate some keys.
+verbose "$tid: generating test keys"
+REVOKED_SERIALS="1 4 10 50 90 500 510 520 550 799 999"
+for n in $REVOKED_SERIALS ; do
+ f=`keygen $n`
+ RKEYS="$RKEYS ${f}.pub"
+ RCERTS="$RCERTS ${f}-cert.pub"
+done
+UNREVOKED_SERIALS="5 9 14 16 29 49 51 499 800 1010 1011"
+UNREVOKED=""
+for n in $UNREVOKED_SERIALS ; do
+ f=`keygen $n`
+ UKEYS="$UKEYS ${f}.pub"
+ UCERTS="$UCERTS ${f}-cert.pub"
+done
+
+# Specifications that revoke keys by hash.
+touch $OBJ/revoked-sha1 $OBJ/revoked-sha256 $OBJ/revoked-hash
+for rkey in $RKEYS; do
+ (printf "sha1: "; cat $rkey) >> $OBJ/revoked-sha1
+ (printf "sha256: "; cat $rkey) >> $OBJ/revoked-sha256
+ (printf "hash: "; $SSHKEYGEN -lf $rkey | \
+ awk '{ print $2 }') >> $OBJ/revoked-hash
+done
+
+genkrls() {
+ OPTS=$1
+$SSHKEYGEN $OPTS -kf $OBJ/krl-empty - </dev/null \
+ >/dev/null || fatal "$SSHKEYGEN KRL failed"
+$SSHKEYGEN $OPTS -kf $OBJ/krl-keys $RKEYS \
+ >/dev/null || fatal "$SSHKEYGEN KRL failed"
+$SSHKEYGEN $OPTS -kf $OBJ/krl-cert $RCERTS \
+ >/dev/null || fatal "$SSHKEYGEN KRL failed"
+$SSHKEYGEN $OPTS -kf $OBJ/krl-all $RKEYS $RCERTS \
+ >/dev/null || fatal "$SSHKEYGEN KRL failed"
+$SSHKEYGEN $OPTS -kf $OBJ/krl-ca $OBJ/revoked-ca.pub \
+ >/dev/null || fatal "$SSHKEYGEN KRL failed"
+$SSHKEYGEN $OPTS -kf $OBJ/krl-sha1 $OBJ/revoked-sha1 \
+ >/dev/null 2>&1 || fatal "$SSHKEYGEN KRL failed"
+$SSHKEYGEN $OPTS -kf $OBJ/krl-sha256 $OBJ/revoked-sha256 \
+ >/dev/null 2>&1 || fatal "$SSHKEYGEN KRL failed"
+$SSHKEYGEN $OPTS -kf $OBJ/krl-hash $OBJ/revoked-hash \
+ >/dev/null 2>&1 || fatal "$SSHKEYGEN KRL failed"
+# This should fail as KRLs from serial/key-id spec need the CA specified.
+$SSHKEYGEN $OPTS -kf $OBJ/krl-serial $OBJ/revoked-serials \
+ >/dev/null 2>&1 && fatal "$SSHKEYGEN KRL succeeded unexpectedly"
+$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid $OBJ/revoked-keyid \
+ >/dev/null 2>&1 && fatal "$SSHKEYGEN KRL succeeded unexpectedly"
+# These should succeed; they specify an explicit CA key.
+$SSHKEYGEN $OPTS -kf $OBJ/krl-serial -s $OBJ/revoked-ca \
+ $OBJ/revoked-serials >/dev/null || fatal "$SSHKEYGEN KRL failed"
+$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid -s $OBJ/revoked-ca.pub \
+ $OBJ/revoked-keyid >/dev/null || fatal "$SSHKEYGEN KRL failed"
+# These should succeed; they specify an wildcard CA key.
+$SSHKEYGEN $OPTS -kf $OBJ/krl-serial-wild -s NONE $OBJ/revoked-serials \
+ >/dev/null || fatal "$SSHKEYGEN KRL failed"
+$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid-wild -s NONE $OBJ/revoked-keyid \
+ >/dev/null || fatal "$SSHKEYGEN KRL failed"
+# Revoke the same serials with the second CA key to ensure a multi-CA
+# KRL is generated.
+$SSHKEYGEN $OPTS -kf $OBJ/krl-serial -u -s $OBJ/revoked-ca2 \
+ $OBJ/revoked-serials >/dev/null || fatal "$SSHKEYGEN KRL failed"
+}
+
+## XXX dump with trace and grep for set cert serials
+## XXX test ranges near (u64)-1, etc.
+
+verbose "$tid: generating KRLs"
+genkrls
+
+check_krl() {
+ KEY=$1
+ KRL=$2
+ EXPECT_REVOKED=$3
+ TAG=$4
+ $SSHKEYGEN -Qf $KRL $KEY >/dev/null
+ result=$?
+ if test "x$EXPECT_REVOKED" = "xy" -a $result -eq 0 ; then
+ fatal "key $KEY not revoked by KRL $KRL: $TAG"
+ elif test "x$EXPECT_REVOKED" = "xn" -a $result -ne 0 ; then
+ fatal "key $KEY unexpectedly revoked by KRL $KRL: $TAG"
+ fi
+}
+test_rev() {
+ FILES=$1
+ TAG=$2
+ KEYS_RESULT=$3
+ ALL_RESULT=$4
+ HASH_RESULT=$5
+ SERIAL_RESULT=$6
+ KEYID_RESULT=$7
+ CERTS_RESULT=$8
+ CA_RESULT=$9
+ SERIAL_WRESULT=$10
+ KEYID_WRESULT=$11
+ verbose "$tid: checking revocations for $TAG"
+ for f in $FILES ; do
+ check_krl $f $OBJ/krl-empty no "$TAG"
+ check_krl $f $OBJ/krl-keys $KEYS_RESULT "$TAG"
+ check_krl $f $OBJ/krl-all $ALL_RESULT "$TAG"
+ check_krl $f $OBJ/krl-sha1 $HASH_RESULT "$TAG"
+ check_krl $f $OBJ/krl-sha256 $HASH_RESULT "$TAG"
+ check_krl $f $OBJ/krl-hash $HASH_RESULT "$TAG"
+ check_krl $f $OBJ/krl-serial $SERIAL_RESULT "$TAG"
+ check_krl $f $OBJ/krl-keyid $KEYID_RESULT "$TAG"
+ check_krl $f $OBJ/krl-cert $CERTS_RESULT "$TAG"
+ check_krl $f $OBJ/krl-ca $CA_RESULT "$TAG"
+ check_krl $f $OBJ/krl-serial-wild $SERIAL_WRESULT "$TAG"
+ check_krl $f $OBJ/krl-keyid-wild $KEYID_WRESULT "$TAG"
+ done
+}
+
+test_all() {
+ # wildcard
+ # keys all hash sr# ID cert CA srl ID
+ test_rev "$RKEYS" "revoked keys" y y y n n n n n n
+ test_rev "$UKEYS" "unrevoked keys" n n n n n n n n n
+ test_rev "$RCERTS" "revoked certs" y y y y y y y y y
+ test_rev "$UCERTS" "unrevoked certs" n n n n n n y n n
+}
+
+test_all
+
+# Check update. Results should be identical.
+verbose "$tid: testing KRL update"
+for f in $OBJ/krl-keys $OBJ/krl-cert $OBJ/krl-all \
+ $OBJ/krl-ca $OBJ/krl-serial $OBJ/krl-keyid \
+ $OBJ/krl-serial-wild $OBJ/krl-keyid-wild; do
+ cp -f $OBJ/krl-empty $f
+ genkrls -u
+done
+
+test_all
diff --git a/regress/limit-keytype.sh b/regress/limit-keytype.sh
new file mode 100644
index 00000000..010a88cd
--- /dev/null
+++ b/regress/limit-keytype.sh
@@ -0,0 +1,133 @@
+# $OpenBSD: limit-keytype.sh,v 1.9 2019/12/16 02:39:05 djm Exp $
+# Placed in the Public Domain.
+
+tid="restrict pubkey type"
+
+# XXX sk-* keys aren't actually tested ATM.
+
+rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/user_key*
+rm -f $OBJ/authorized_principals_$USER $OBJ/cert_user_key*
+
+mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
+mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig
+
+ktype1=ed25519; ktype2=ed25519; ktype3=ed25519;
+ktype4=ed25519; ktype5=ed25519; ktype6=ed25519;
+for t in $SSH_KEYTYPES ; do
+ case "$t" in
+ ssh-rsa) ktype2=rsa ;;
+ ecdsa*) ktype3=ecdsa ;; # unused
+ ssh-dss) ktype4=dsa ;;
+ sk-ssh-ed25519@openssh.com) ktype5=ed25519-sk ;;
+ sk-ecdsa-sha2-nistp256@openssh.com) ktype6=ecdsa-sk ;;
+ esac
+done
+
+# Create a CA key
+${SSHKEYGEN} -q -N '' -t $ktype1 -f $OBJ/user_ca_key ||\
+ fatal "ssh-keygen failed"
+
+# Make some keys and a certificate.
+${SSHKEYGEN} -q -N '' -t $ktype1 -f $OBJ/user_key1 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t $ktype2 -f $OBJ/user_key2 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t $ktype2 -f $OBJ/user_key3 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t $ktype4 -f $OBJ/user_key4 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t $ktype5 -f $OBJ/user_key5 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t $ktype6 -f $OBJ/user_key6 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \
+ -z $$ -n ${USER},mekmitasdigoat $OBJ/user_key3 ||
+ fatal "couldn't sign user_key1"
+# Copy the private key alongside the cert to allow better control of when
+# it is offered.
+mv $OBJ/user_key3-cert.pub $OBJ/cert_user_key3.pub
+
+grep -v IdentityFile $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy
+
+opts="-oProtocol=2 -F $OBJ/ssh_proxy -oIdentitiesOnly=yes"
+certopts="$opts -i $OBJ/user_key3 -oCertificateFile=$OBJ/cert_user_key3.pub"
+
+echo mekmitasdigoat > $OBJ/authorized_principals_$USER
+cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
+cat $OBJ/user_key2.pub >> $OBJ/authorized_keys_$USER
+
+prepare_config() {
+ (
+ grep -v "Protocol" $OBJ/sshd_proxy.orig
+ echo "Protocol 2"
+ echo "AuthenticationMethods publickey"
+ echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
+ echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
+ for x in "$@" ; do
+ echo "$x"
+ done
+ ) > $OBJ/sshd_proxy
+}
+
+# Return the required parameter for PubkeyAcceptedKeyTypes corresponding to
+# the supplied key type.
+keytype() {
+ case "$1" in
+ ecdsa) printf "ecdsa-sha2-*" ;;
+ ed25519) printf "ssh-ed25519" ;;
+ dsa) printf "ssh-dss" ;;
+ rsa) printf "rsa-sha2-256,rsa-sha2-512,ssh-rsa" ;;
+ sk-ecdsa) printf "sk-ecdsa-*" ;;
+ sk-ssh-ed25519) printf "sk-ssh-ed25519-*" ;;
+ esac
+}
+
+prepare_config
+
+# Check we can log in with all key types.
+${SSH} $certopts proxy true || fatal "cert failed"
+${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed"
+${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`"
+${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`"
+${SSH} $certopts proxy true && fatal "cert succeeded"
+${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed"
+if [ "$ktype1" != "$ktype2" ]; then
+ ${SSH} $opts -i $OBJ/user_key2 proxy true && fatal "key2 succeeded"
+fi
+
+# Allow all certs. Plain keys should fail.
+verbose "allow cert only"
+prepare_config "PubkeyAcceptedKeyTypes *-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`"
+${SSH} $certopts proxy true && fatal "cert succeeded"
+if [ "$ktype1" != "$ktype2" ]; then
+ ${SSH} $opts -i $OBJ/user_key1 proxy true && fatal "key1 succeeded"
+fi
+${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`"
+${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/localcommand.sh b/regress/localcommand.sh
new file mode 100644
index 00000000..5224a16b
--- /dev/null
+++ b/regress/localcommand.sh
@@ -0,0 +1,13 @@
+# $OpenBSD: localcommand.sh,v 1.4 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="localcommand"
+
+echo 'PermitLocalCommand yes' >> $OBJ/ssh_proxy
+echo 'LocalCommand echo foo' >> $OBJ/ssh_proxy
+
+verbose "test $tid: proto $p localcommand"
+a=`${SSH} -F $OBJ/ssh_proxy somehost true`
+if [ "$a" != "foo" ] ; then
+ fail "$tid proto $p"
+fi
diff --git a/regress/login-timeout.sh b/regress/login-timeout.sh
new file mode 100644
index 00000000..4c2d07dc
--- /dev/null
+++ b/regress/login-timeout.sh
@@ -0,0 +1,18 @@
+# $OpenBSD: login-timeout.sh,v 1.9 2017/08/07 00:53:51 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="connect after login grace timeout"
+
+trace "test login grace with privsep"
+cp $OBJ/sshd_config $OBJ/sshd_config.orig
+grep -vi LoginGraceTime $OBJ/sshd_config.orig > $OBJ/sshd_config
+echo "LoginGraceTime 10s" >> $OBJ/sshd_config
+echo "MaxStartups 1" >> $OBJ/sshd_config
+start_sshd
+
+(echo SSH-2.0-fake; sleep 60) | telnet 127.0.0.1 ${PORT} >/dev/null 2>&1 &
+sleep 15
+${SSH} -F $OBJ/ssh_config somehost true
+if [ $? -ne 0 ]; then
+ fail "ssh connect after login grace timeout failed"
+fi
diff --git a/regress/misc/Makefile b/regress/misc/Makefile
new file mode 100644
index 00000000..cf95f265
--- /dev/null
+++ b/regress/misc/Makefile
@@ -0,0 +1,3 @@
+SUBDIR= kexfuzz sk-dummy
+
+.include <bsd.subdir.mk>
diff --git a/regress/misc/fuzz-harness/Makefile b/regress/misc/fuzz-harness/Makefile
new file mode 100644
index 00000000..64fbdbab
--- /dev/null
+++ b/regress/misc/fuzz-harness/Makefile
@@ -0,0 +1,38 @@
+# 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
+FUZZ_LIBS=-lFuzzer
+
+CXXFLAGS=-O2 -g -Wall -Wextra -Wno-unused-parameter -I ../../.. $(FUZZ_FLAGS)
+LDFLAGS=-L ../../.. -L ../../../openbsd-compat -g $(FUZZ_FLAGS)
+LIBS=-lssh -lopenbsd-compat -lcrypto -lfido2 -lcbor $(FUZZ_LIBS)
+COMMON_OBJS=ssh-sk-null.o
+
+TARGETS=pubkey_fuzz sig_fuzz authopt_fuzz sshsig_fuzz \
+ sshsigopt_fuzz privkey_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)
+
+sig_fuzz: sig_fuzz.o $(COMMON_OBJS)
+ $(CXX) -o $@ sig_fuzz.o $(COMMON_OBJS) $(LDFLAGS) $(LIBS)
+
+authopt_fuzz: authopt_fuzz.o $(COMMON_OBJS)
+ $(CXX) -o $@ authopt_fuzz.o $(COMMON_OBJS) ../../../auth-options.o $(LDFLAGS) $(LIBS)
+
+sshsig_fuzz: sshsig_fuzz.o $(COMMON_OBJS)
+ $(CXX) -o $@ sshsig_fuzz.o $(COMMON_OBJS) ../../../sshsig.o $(LDFLAGS) $(LIBS)
+
+sshsigopt_fuzz: sshsigopt_fuzz.o $(COMMON_OBJS)
+ $(CXX) -o $@ sshsigopt_fuzz.o $(COMMON_OBJS) ../../../sshsig.o $(LDFLAGS) $(LIBS)
+
+privkey_fuzz: privkey_fuzz.o $(COMMON_OBJS)
+ $(CXX) -o $@ privkey_fuzz.o $(COMMON_OBJS) $(LDFLAGS) $(LIBS)
+
+clean:
+ -rm -f *.o $(TARGETS)
diff --git a/regress/misc/fuzz-harness/README b/regress/misc/fuzz-harness/README
new file mode 100644
index 00000000..ae6fbe75
--- /dev/null
+++ b/regress/misc/fuzz-harness/README
@@ -0,0 +1 @@
+This directory contains fuzzing harnesses for use with clang's libfuzzer.
diff --git a/regress/misc/fuzz-harness/authopt_fuzz.cc b/regress/misc/fuzz-harness/authopt_fuzz.cc
new file mode 100644
index 00000000..a76d5a3f
--- /dev/null
+++ b/regress/misc/fuzz-harness/authopt_fuzz.cc
@@ -0,0 +1,33 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+extern "C" {
+
+#include "auth-options.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ char *cp = (char *)malloc(size + 1);
+ struct sshauthopt *opts = NULL, *merge = NULL, *add = sshauthopt_new();
+
+ if (cp == NULL || add == NULL)
+ goto out;
+ memcpy(cp, data, size);
+ cp[size] = '\0';
+ if ((opts = sshauthopt_parse(cp, NULL)) == NULL)
+ goto out;
+ if ((merge = sshauthopt_merge(opts, add, NULL)) == NULL)
+ goto out;
+
+ out:
+ free(cp);
+ sshauthopt_free(add);
+ sshauthopt_free(opts);
+ sshauthopt_free(merge);
+ return 0;
+}
+
+} // extern "C"
diff --git a/regress/misc/fuzz-harness/privkey_fuzz.cc b/regress/misc/fuzz-harness/privkey_fuzz.cc
new file mode 100644
index 00000000..ff0b0f77
--- /dev/null
+++ b/regress/misc/fuzz-harness/privkey_fuzz.cc
@@ -0,0 +1,21 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+
+extern "C" {
+
+#include "sshkey.h"
+#include "sshbuf.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ struct sshkey *k = NULL;
+ struct sshbuf *b = sshbuf_from(data, size);
+ int r = sshkey_private_deserialize(b, &k);
+ if (r == 0) sshkey_free(k);
+ sshbuf_free(b);
+ return 0;
+}
+
+} // extern
+
diff --git a/regress/misc/fuzz-harness/pubkey_fuzz.cc b/regress/misc/fuzz-harness/pubkey_fuzz.cc
new file mode 100644
index 00000000..8bbc1109
--- /dev/null
+++ b/regress/misc/fuzz-harness/pubkey_fuzz.cc
@@ -0,0 +1,18 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+
+extern "C" {
+
+#include "sshkey.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ struct sshkey *k = NULL;
+ int r = sshkey_from_blob(data, size, &k);
+ if (r == 0) sshkey_free(k);
+ return 0;
+}
+
+} // extern
+
diff --git a/regress/misc/fuzz-harness/sig_fuzz.cc b/regress/misc/fuzz-harness/sig_fuzz.cc
new file mode 100644
index 00000000..b32502ba
--- /dev/null
+++ b/regress/misc/fuzz-harness/sig_fuzz.cc
@@ -0,0 +1,62 @@
+// cc_fuzz_target test for public key parsing.
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern "C" {
+
+#include "includes.h"
+#include "sshkey.h"
+#include "ssherr.h"
+
+static struct sshkey *generate_or_die(int type, unsigned bits) {
+ int r;
+ struct sshkey *ret;
+ if ((r = sshkey_generate(type, bits, &ret)) != 0) {
+ fprintf(stderr, "generate(%d, %u): %s", type, bits, ssh_err(r));
+ abort();
+ }
+ return ret;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* sig, size_t slen)
+{
+#ifdef WITH_OPENSSL
+ static struct sshkey *rsa = generate_or_die(KEY_RSA, 2048);
+ static struct sshkey *dsa = generate_or_die(KEY_DSA, 1024);
+ static struct sshkey *ecdsa256 = generate_or_die(KEY_ECDSA, 256);
+ static struct sshkey *ecdsa384 = generate_or_die(KEY_ECDSA, 384);
+ static struct sshkey *ecdsa521 = generate_or_die(KEY_ECDSA, 521);
+#endif
+ struct sshkey_sig_details *details = NULL;
+ static struct sshkey *ed25519 = generate_or_die(KEY_ED25519, 0);
+ static const char *data = "If everyone started announcing his nose had "
+ "run away, I don’t know how it would all end";
+ static const size_t dlen = strlen(data);
+
+#ifdef WITH_OPENSSL
+ sshkey_verify(rsa, sig, slen, (const u_char *)data, dlen, NULL, 0, &details);
+ sshkey_sig_details_free(details);
+ details = NULL;
+ sshkey_verify(dsa, sig, slen, (const u_char *)data, dlen, NULL, 0, &details);
+ sshkey_sig_details_free(details);
+ details = NULL;
+ sshkey_verify(ecdsa256, sig, slen, (const u_char *)data, dlen, NULL, 0, &details);
+ sshkey_sig_details_free(details);
+ details = NULL;
+ sshkey_verify(ecdsa384, sig, slen, (const u_char *)data, dlen, NULL, 0, &details);
+ sshkey_sig_details_free(details);
+ details = NULL;
+ sshkey_verify(ecdsa521, sig, slen, (const u_char *)data, dlen, NULL, 0, &details);
+ sshkey_sig_details_free(details);
+ details = NULL;
+#endif
+ sshkey_verify(ed25519, sig, slen, (const u_char *)data, dlen, NULL, 0, &details);
+ sshkey_sig_details_free(details);
+ return 0;
+}
+
+} // extern
diff --git a/regress/misc/fuzz-harness/ssh-sk-null.cc b/regress/misc/fuzz-harness/ssh-sk-null.cc
new file mode 100644
index 00000000..199af112
--- /dev/null
+++ b/regress/misc/fuzz-harness/ssh-sk-null.cc
@@ -0,0 +1,51 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2019 Google LLC
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+extern "C" {
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include "ssherr.h"
+#include "ssh-sk.h"
+
+int
+sshsk_enroll(int type, const char *provider_path, const char *device,
+ const char *application, const char *userid, uint8_t flags,
+ const char *pin, struct sshbuf *challenge_buf,
+ struct sshkey **keyp, struct sshbuf *attest)
+{
+ return SSH_ERR_FEATURE_UNSUPPORTED;
+}
+
+int
+sshsk_sign(const char *provider_path, struct sshkey *key,
+ u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
+ u_int compat, const char *pin)
+{
+ return SSH_ERR_FEATURE_UNSUPPORTED;
+}
+
+int
+sshsk_load_resident(const char *provider_path, const char *device,
+ const char *pin, struct sshkey ***keysp, size_t *nkeysp)
+{
+ return SSH_ERR_FEATURE_UNSUPPORTED;
+}
+
+};
diff --git a/regress/misc/fuzz-harness/sshsig_fuzz.cc b/regress/misc/fuzz-harness/sshsig_fuzz.cc
new file mode 100644
index 00000000..02211a09
--- /dev/null
+++ b/regress/misc/fuzz-harness/sshsig_fuzz.cc
@@ -0,0 +1,37 @@
+// cc_fuzz_target test for sshsig verification.
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern "C" {
+
+#include "includes.h"
+#include "sshkey.h"
+#include "ssherr.h"
+#include "sshbuf.h"
+#include "sshsig.h"
+#include "log.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t* sig, size_t slen)
+{
+ static const char *data = "If everyone started announcing his nose had "
+ "run away, I don’t know how it would all end";
+ struct sshbuf *signature = sshbuf_from(sig, slen);
+ struct sshbuf *message = sshbuf_from(data, strlen(data));
+ struct sshkey *k = NULL;
+ struct sshkey_sig_details *details = NULL;
+ extern char *__progname;
+
+ log_init(__progname, SYSLOG_LEVEL_QUIET, SYSLOG_FACILITY_USER, 1);
+ sshsig_verifyb(signature, message, "castle", &k, &details);
+ sshkey_sig_details_free(details);
+ sshkey_free(k);
+ sshbuf_free(signature);
+ sshbuf_free(message);
+ return 0;
+}
+
+} // extern
diff --git a/regress/misc/fuzz-harness/sshsigopt_fuzz.cc b/regress/misc/fuzz-harness/sshsigopt_fuzz.cc
new file mode 100644
index 00000000..7424fcbe
--- /dev/null
+++ b/regress/misc/fuzz-harness/sshsigopt_fuzz.cc
@@ -0,0 +1,29 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+extern "C" {
+
+#include "sshsig.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ char *cp = (char *)malloc(size + 1);
+ struct sshsigopt *opts = NULL;
+
+ if (cp == NULL)
+ goto out;
+ memcpy(cp, data, size);
+ cp[size] = '\0';
+ if ((opts = sshsigopt_parse(cp, "libfuzzer", 0, NULL)) == NULL)
+ goto out;
+
+ out:
+ free(cp);
+ sshsigopt_free(opts);
+ return 0;
+}
+
+} // extern "C"
diff --git a/regress/misc/kexfuzz/Makefile b/regress/misc/kexfuzz/Makefile
new file mode 100644
index 00000000..ede5e2fb
--- /dev/null
+++ b/regress/misc/kexfuzz/Makefile
@@ -0,0 +1,101 @@
+# $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
new file mode 100644
index 00000000..504c26f3
--- /dev/null
+++ b/regress/misc/kexfuzz/README
@@ -0,0 +1,34 @@
+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
new file mode 100644
index 00000000..56697c91
--- /dev/null
+++ b/regress/misc/kexfuzz/kexfuzz.c
@@ -0,0 +1,453 @@
+/* $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/Makefile b/regress/misc/sk-dummy/Makefile
new file mode 100644
index 00000000..29e313c8
--- /dev/null
+++ b/regress/misc/sk-dummy/Makefile
@@ -0,0 +1,66 @@
+# $OpenBSD: Makefile,v 1.2 2019/11/29 00:13:29 djm Exp $
+
+.include <bsd.own.mk>
+.include <bsd.obj.mk>
+
+PROG= sk-dummy.so
+NOMAN=
+
+SSHREL=../../../../../usr.bin/ssh
+.PATH: ${.CURDIR}/${SSHREL}
+
+SRCS=sk-dummy.c
+# From usr.bin/ssh
+SRCS+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
+OPENSSL?= yes
+
+CFLAGS+= -fPIC
+
+.if (${OPENSSL:L} == "yes")
+CFLAGS+= -DWITH_OPENSSL
+.endif
+
+# enable warnings
+WARNINGS=Yes
+
+DEBUG=-g
+CFLAGS+= -fstack-protector-all
+CDIAGFLAGS= -Wall
+CDIAGFLAGS+= -Wextra
+CDIAGFLAGS+= -Werror
+CDIAGFLAGS+= -Wchar-subscripts
+CDIAGFLAGS+= -Wcomment
+CDIAGFLAGS+= -Wformat
+CDIAGFLAGS+= -Wformat-security
+CDIAGFLAGS+= -Wimplicit
+CDIAGFLAGS+= -Winline
+CDIAGFLAGS+= -Wmissing-declarations
+CDIAGFLAGS+= -Wmissing-prototypes
+CDIAGFLAGS+= -Wparentheses
+CDIAGFLAGS+= -Wpointer-arith
+CDIAGFLAGS+= -Wreturn-type
+CDIAGFLAGS+= -Wshadow
+CDIAGFLAGS+= -Wsign-compare
+CDIAGFLAGS+= -Wstrict-aliasing
+CDIAGFLAGS+= -Wstrict-prototypes
+CDIAGFLAGS+= -Wswitch
+CDIAGFLAGS+= -Wtrigraphs
+CDIAGFLAGS+= -Wuninitialized
+CDIAGFLAGS+= -Wunused
+CDIAGFLAGS+= -Wno-unused-parameter
+.if ${COMPILER_VERSION:L} != "gcc3"
+CDIAGFLAGS+= -Wold-style-definition
+.endif
+
+CFLAGS+=-I${.CURDIR}/${SSHREL}
+
+.if (${OPENSSL:L} == "yes")
+LDADD+= -lcrypto
+DPADD+= ${LIBCRYPTO}
+.endif
+
+$(PROG): $(OBJS)
+ $(CC) $(LDFLAGS) -shared -o $@ $(OBJS) $(LDADD)
+
+.include <bsd.prog.mk>
+
diff --git a/regress/misc/sk-dummy/fatal.c b/regress/misc/sk-dummy/fatal.c
new file mode 100644
index 00000000..7cdc74b9
--- /dev/null
+++ b/regress/misc/sk-dummy/fatal.c
@@ -0,0 +1,20 @@
+/* public domain */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+void fatal(char *fmt, ...);
+
+void
+fatal(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ _exit(1);
+}
diff --git a/regress/misc/sk-dummy/sk-dummy.c b/regress/misc/sk-dummy/sk-dummy.c
new file mode 100644
index 00000000..f3acb2fb
--- /dev/null
+++ b/regress/misc/sk-dummy/sk-dummy.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright (c) 2019 Markus Friedl
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+
+#include "crypto_api.h"
+#include "sk-api.h"
+
+#include <openssl/opensslv.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/pem.h>
+
+/* #define SK_DEBUG 1 */
+
+/* Compatibility with OpenSSH 1.0.x */
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
+#define ECDSA_SIG_get0(sig, pr, ps) \
+ do { \
+ (*pr) = sig->r; \
+ (*ps) = sig->s; \
+ } while (0)
+#endif
+
+#if SSH_SK_VERSION_MAJOR != 0x00050000
+# error SK API has changed, sk-dummy.c needs an update
+#endif
+
+static void skdebug(const char *func, const char *fmt, ...)
+ __attribute__((__format__ (printf, 2, 3)));
+
+static void
+skdebug(const char *func, const char *fmt, ...)
+{
+#if defined(SK_DEBUG)
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "sk-dummy %s: ", func);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+#else
+ (void)func; /* XXX */
+ (void)fmt; /* XXX */
+#endif
+}
+
+uint32_t
+sk_api_version(void)
+{
+ return SSH_SK_VERSION_MAJOR;
+}
+
+static int
+pack_key_ecdsa(struct sk_enroll_response *response)
+{
+#ifdef OPENSSL_HAS_ECC
+ EC_KEY *key = NULL;
+ const EC_GROUP *g;
+ const EC_POINT *q;
+ int ret = -1;
+ long privlen;
+ BIO *bio = NULL;
+ char *privptr;
+
+ response->public_key = NULL;
+ response->public_key_len = 0;
+ response->key_handle = NULL;
+ response->key_handle_len = 0;
+
+ if ((key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)) == NULL) {
+ skdebug(__func__, "EC_KEY_new_by_curve_name");
+ goto out;
+ }
+ if (EC_KEY_generate_key(key) != 1) {
+ skdebug(__func__, "EC_KEY_generate_key");
+ goto out;
+ }
+ EC_KEY_set_asn1_flag(key, OPENSSL_EC_NAMED_CURVE);
+ if ((bio = BIO_new(BIO_s_mem())) == NULL ||
+ (g = EC_KEY_get0_group(key)) == NULL ||
+ (q = EC_KEY_get0_public_key(key)) == NULL) {
+ skdebug(__func__, "couldn't get key parameters");
+ goto out;
+ }
+ response->public_key_len = EC_POINT_point2oct(g, q,
+ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+ if (response->public_key_len == 0 || response->public_key_len > 2048) {
+ skdebug(__func__, "bad pubkey length %zu",
+ response->public_key_len);
+ goto out;
+ }
+ if ((response->public_key = malloc(response->public_key_len)) == NULL) {
+ skdebug(__func__, "malloc pubkey failed");
+ goto out;
+ }
+ if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED,
+ response->public_key, response->public_key_len, NULL) == 0) {
+ skdebug(__func__, "EC_POINT_point2oct failed");
+ goto out;
+ }
+ /* Key handle contains PEM encoded private key */
+ if (!PEM_write_bio_ECPrivateKey(bio, key, NULL, NULL, 0, NULL, NULL)) {
+ skdebug(__func__, "PEM_write_bio_ECPrivateKey failed");
+ goto out;
+ }
+ if ((privlen = BIO_get_mem_data(bio, &privptr)) <= 0) {
+ skdebug(__func__, "BIO_get_mem_data failed");
+ goto out;
+ }
+ if ((response->key_handle = malloc(privlen)) == NULL) {
+ skdebug(__func__, "malloc key_handle failed");
+ goto out;
+ }
+ response->key_handle_len = (size_t)privlen;
+ memcpy(response->key_handle, privptr, response->key_handle_len);
+ /* success */
+ ret = 0;
+ out:
+ if (ret != 0) {
+ if (response->public_key != NULL) {
+ memset(response->public_key, 0,
+ response->public_key_len);
+ free(response->public_key);
+ response->public_key = NULL;
+ }
+ if (response->key_handle != NULL) {
+ memset(response->key_handle, 0,
+ response->key_handle_len);
+ free(response->key_handle);
+ response->key_handle = NULL;
+ }
+ }
+ BIO_free(bio);
+ EC_KEY_free(key);
+ return ret;
+#else
+ return -1;
+#endif
+}
+
+static int
+pack_key_ed25519(struct sk_enroll_response *response)
+{
+ int ret = -1;
+ u_char pk[crypto_sign_ed25519_PUBLICKEYBYTES];
+ u_char sk[crypto_sign_ed25519_SECRETKEYBYTES];
+
+ response->public_key = NULL;
+ response->public_key_len = 0;
+ response->key_handle = NULL;
+ response->key_handle_len = 0;
+
+ memset(pk, 0, sizeof(pk));
+ memset(sk, 0, sizeof(sk));
+ crypto_sign_ed25519_keypair(pk, sk);
+
+ response->public_key_len = sizeof(pk);
+ if ((response->public_key = malloc(response->public_key_len)) == NULL) {
+ skdebug(__func__, "malloc pubkey failed");
+ goto out;
+ }
+ memcpy(response->public_key, pk, sizeof(pk));
+ /* Key handle contains sk */
+ response->key_handle_len = sizeof(sk);
+ if ((response->key_handle = malloc(response->key_handle_len)) == NULL) {
+ skdebug(__func__, "malloc key_handle failed");
+ goto out;
+ }
+ memcpy(response->key_handle, sk, sizeof(sk));
+ /* success */
+ ret = 0;
+ out:
+ if (ret != 0)
+ free(response->public_key);
+ return ret;
+}
+
+static int
+check_options(struct sk_option **options)
+{
+ size_t i;
+
+ if (options == NULL)
+ return 0;
+ for (i = 0; options[i] != NULL; i++) {
+ skdebug(__func__, "requested unsupported option %s",
+ options[i]->name);
+ if (options[i]->required) {
+ skdebug(__func__, "unknown required option");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
+ const char *application, uint8_t flags, const char *pin,
+ struct sk_option **options, struct sk_enroll_response **enroll_response)
+{
+ struct sk_enroll_response *response = NULL;
+ int ret = SSH_SK_ERR_GENERAL;
+
+ (void)flags; /* XXX; unused */
+
+ if (enroll_response == NULL) {
+ skdebug(__func__, "enroll_response == NULL");
+ goto out;
+ }
+ *enroll_response = NULL;
+ if (check_options(options) != 0)
+ goto out; /* error already logged */
+ if ((response = calloc(1, sizeof(*response))) == NULL) {
+ skdebug(__func__, "calloc response failed");
+ goto out;
+ }
+ switch(alg) {
+ case SSH_SK_ECDSA:
+ if (pack_key_ecdsa(response) != 0)
+ goto out;
+ break;
+ case SSH_SK_ED25519:
+ if (pack_key_ed25519(response) != 0)
+ goto out;
+ break;
+ default:
+ skdebug(__func__, "unsupported key type %d", alg);
+ return -1;
+ }
+ /* Have to return something here */
+ if ((response->signature = calloc(1, 1)) == NULL) {
+ skdebug(__func__, "calloc signature failed");
+ goto out;
+ }
+ response->signature_len = 0;
+
+ *enroll_response = response;
+ response = NULL;
+ ret = 0;
+ out:
+ if (response != NULL) {
+ free(response->public_key);
+ free(response->key_handle);
+ free(response->signature);
+ free(response->attestation_cert);
+ free(response);
+ }
+ return ret;
+}
+
+static void
+dump(const char *preamble, const void *sv, size_t l)
+{
+#ifdef SK_DEBUG
+ const u_char *s = (const u_char *)sv;
+ size_t i;
+
+ fprintf(stderr, "%s (len %zu):\n", preamble, l);
+ for (i = 0; i < l; i++) {
+ if (i % 16 == 0)
+ fprintf(stderr, "%04zu: ", i);
+ fprintf(stderr, "%02x", s[i]);
+ if (i % 16 == 15 || i == l - 1)
+ fprintf(stderr, "\n");
+ }
+#endif
+}
+
+static int
+sig_ecdsa(const uint8_t *message, size_t message_len,
+ const char *application, uint32_t counter, uint8_t flags,
+ const uint8_t *key_handle, size_t key_handle_len,
+ struct sk_sign_response *response)
+{
+#ifdef OPENSSL_HAS_ECC
+ ECDSA_SIG *sig = NULL;
+ const BIGNUM *sig_r, *sig_s;
+ int ret = -1;
+ BIO *bio = NULL;
+ EVP_PKEY *pk = NULL;
+ EC_KEY *ec = NULL;
+ SHA256_CTX ctx;
+ uint8_t apphash[SHA256_DIGEST_LENGTH];
+ uint8_t sighash[SHA256_DIGEST_LENGTH];
+ uint8_t countbuf[4];
+
+ /* Decode EC_KEY from key handle */
+ if ((bio = BIO_new(BIO_s_mem())) == NULL ||
+ BIO_write(bio, key_handle, key_handle_len) != (int)key_handle_len) {
+ skdebug(__func__, "BIO setup failed");
+ goto out;
+ }
+ if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, "")) == NULL) {
+ skdebug(__func__, "PEM_read_bio_PrivateKey failed");
+ goto out;
+ }
+ if (EVP_PKEY_base_id(pk) != EVP_PKEY_EC) {
+ skdebug(__func__, "Not an EC key: %d", EVP_PKEY_base_id(pk));
+ goto out;
+ }
+ if ((ec = EVP_PKEY_get1_EC_KEY(pk)) == NULL) {
+ skdebug(__func__, "EVP_PKEY_get1_EC_KEY failed");
+ goto out;
+ }
+ /* Expect message to be pre-hashed */
+ if (message_len != SHA256_DIGEST_LENGTH) {
+ skdebug(__func__, "bad message len %zu", message_len);
+ goto out;
+ }
+ /* Prepare data to be signed */
+ dump("message", message, message_len);
+ SHA256_Init(&ctx);
+ SHA256_Update(&ctx, application, strlen(application));
+ SHA256_Final(apphash, &ctx);
+ dump("apphash", apphash, sizeof(apphash));
+ countbuf[0] = (counter >> 24) & 0xff;
+ countbuf[1] = (counter >> 16) & 0xff;
+ countbuf[2] = (counter >> 8) & 0xff;
+ countbuf[3] = counter & 0xff;
+ dump("countbuf", countbuf, sizeof(countbuf));
+ dump("flags", &flags, sizeof(flags));
+ SHA256_Init(&ctx);
+ SHA256_Update(&ctx, apphash, sizeof(apphash));
+ SHA256_Update(&ctx, &flags, sizeof(flags));
+ SHA256_Update(&ctx, countbuf, sizeof(countbuf));
+ SHA256_Update(&ctx, message, message_len);
+ SHA256_Final(sighash, &ctx);
+ dump("sighash", sighash, sizeof(sighash));
+ /* create and encode signature */
+ if ((sig = ECDSA_do_sign(sighash, sizeof(sighash), ec)) == NULL) {
+ skdebug(__func__, "ECDSA_do_sign failed");
+ goto out;
+ }
+ ECDSA_SIG_get0(sig, &sig_r, &sig_s);
+ response->sig_r_len = BN_num_bytes(sig_r);
+ response->sig_s_len = BN_num_bytes(sig_s);
+ if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL ||
+ (response->sig_s = calloc(1, response->sig_s_len)) == NULL) {
+ skdebug(__func__, "calloc signature failed");
+ goto out;
+ }
+ BN_bn2bin(sig_r, response->sig_r);
+ BN_bn2bin(sig_s, response->sig_s);
+ ret = 0;
+ out:
+ explicit_bzero(&ctx, sizeof(ctx));
+ explicit_bzero(&apphash, sizeof(apphash));
+ explicit_bzero(&sighash, sizeof(sighash));
+ ECDSA_SIG_free(sig);
+ if (ret != 0) {
+ free(response->sig_r);
+ free(response->sig_s);
+ response->sig_r = NULL;
+ response->sig_s = NULL;
+ }
+ BIO_free(bio);
+ EC_KEY_free(ec);
+ EVP_PKEY_free(pk);
+ return ret;
+#else
+ return -1;
+#endif
+}
+
+static int
+sig_ed25519(const uint8_t *message, size_t message_len,
+ const char *application, uint32_t counter, uint8_t flags,
+ const uint8_t *key_handle, size_t key_handle_len,
+ struct sk_sign_response *response)
+{
+ size_t o;
+ int ret = -1;
+ SHA256_CTX ctx;
+ uint8_t apphash[SHA256_DIGEST_LENGTH];
+ uint8_t signbuf[sizeof(apphash) + sizeof(flags) +
+ sizeof(counter) + SHA256_DIGEST_LENGTH];
+ uint8_t sig[crypto_sign_ed25519_BYTES + sizeof(signbuf)];
+ unsigned long long smlen;
+
+ if (key_handle_len != crypto_sign_ed25519_SECRETKEYBYTES) {
+ skdebug(__func__, "bad key handle length %zu", key_handle_len);
+ goto out;
+ }
+ /* Expect message to be pre-hashed */
+ if (message_len != SHA256_DIGEST_LENGTH) {
+ skdebug(__func__, "bad message len %zu", message_len);
+ goto out;
+ }
+ /* Prepare data to be signed */
+ dump("message", message, message_len);
+ SHA256_Init(&ctx);
+ SHA256_Update(&ctx, application, strlen(application));
+ SHA256_Final(apphash, &ctx);
+ dump("apphash", apphash, sizeof(apphash));
+
+ memcpy(signbuf, apphash, sizeof(apphash));
+ o = sizeof(apphash);
+ signbuf[o++] = flags;
+ signbuf[o++] = (counter >> 24) & 0xff;
+ signbuf[o++] = (counter >> 16) & 0xff;
+ signbuf[o++] = (counter >> 8) & 0xff;
+ signbuf[o++] = counter & 0xff;
+ memcpy(signbuf + o, message, message_len);
+ o += message_len;
+ if (o != sizeof(signbuf)) {
+ skdebug(__func__, "bad sign buf len %zu, expected %zu",
+ o, sizeof(signbuf));
+ goto out;
+ }
+ dump("signbuf", signbuf, sizeof(signbuf));
+ /* create and encode signature */
+ smlen = sizeof(signbuf);
+ if (crypto_sign_ed25519(sig, &smlen, signbuf, sizeof(signbuf),
+ key_handle) != 0) {
+ skdebug(__func__, "crypto_sign_ed25519 failed");
+ goto out;
+ }
+ if (smlen <= sizeof(signbuf)) {
+ skdebug(__func__, "bad sign smlen %llu, expected min %zu",
+ smlen, sizeof(signbuf) + 1);
+ goto out;
+ }
+ response->sig_r_len = (size_t)(smlen - sizeof(signbuf));
+ if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) {
+ skdebug(__func__, "calloc signature failed");
+ goto out;
+ }
+ memcpy(response->sig_r, sig, response->sig_r_len);
+ dump("sig_r", response->sig_r, response->sig_r_len);
+ ret = 0;
+ out:
+ explicit_bzero(&ctx, sizeof(ctx));
+ explicit_bzero(&apphash, sizeof(apphash));
+ explicit_bzero(&signbuf, sizeof(signbuf));
+ explicit_bzero(&sig, sizeof(sig));
+ if (ret != 0) {
+ free(response->sig_r);
+ response->sig_r = NULL;
+ }
+ return ret;
+}
+
+int
+sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
+ const char *application, const uint8_t *key_handle, size_t key_handle_len,
+ uint8_t flags, const char *pin, struct sk_option **options,
+ struct sk_sign_response **sign_response)
+{
+ struct sk_sign_response *response = NULL;
+ int ret = SSH_SK_ERR_GENERAL;
+ SHA256_CTX ctx;
+ uint8_t message[32];
+
+ if (sign_response == NULL) {
+ skdebug(__func__, "sign_response == NULL");
+ goto out;
+ }
+ *sign_response = NULL;
+ if (check_options(options) != 0)
+ goto out; /* error already logged */
+ if ((response = calloc(1, sizeof(*response))) == NULL) {
+ skdebug(__func__, "calloc response failed");
+ goto out;
+ }
+ SHA256_Init(&ctx);
+ SHA256_Update(&ctx, data, datalen);
+ SHA256_Final(message, &ctx);
+ response->flags = flags;
+ response->counter = 0x12345678;
+ switch(alg) {
+ case SSH_SK_ECDSA:
+ if (sig_ecdsa(message, sizeof(message), application,
+ response->counter, flags, key_handle, key_handle_len,
+ response) != 0)
+ goto out;
+ break;
+ case SSH_SK_ED25519:
+ if (sig_ed25519(message, sizeof(message), application,
+ response->counter, flags, key_handle, key_handle_len,
+ response) != 0)
+ goto out;
+ break;
+ default:
+ skdebug(__func__, "unsupported key type %d", alg);
+ return -1;
+ }
+ *sign_response = response;
+ response = NULL;
+ ret = 0;
+ out:
+ explicit_bzero(message, sizeof(message));
+ if (response != NULL) {
+ free(response->sig_r);
+ free(response->sig_s);
+ free(response);
+ }
+ return ret;
+}
+
+int
+sk_load_resident_keys(const char *pin, struct sk_option **options,
+ struct sk_resident_key ***rks, size_t *nrks)
+{
+ return SSH_SK_ERR_UNSUPPORTED;
+}
diff --git a/regress/mkdtemp.c b/regress/mkdtemp.c
new file mode 100644
index 00000000..a7be1bda
--- /dev/null
+++ b/regress/mkdtemp.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 Colin Watson <cjwatson@debian.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.
+ */
+
+/* Roughly equivalent to "mktemp -d -t TEMPLATE", but portable. */
+
+#include "includes.h"
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "log.h"
+
+static void
+usage(void)
+{
+ fprintf(stderr, "mkdtemp template\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ const char *base;
+ const char *tmpdir;
+ char template[PATH_MAX];
+ int r;
+ char *dir;
+
+ if (argc != 2)
+ usage();
+ base = argv[1];
+
+ if ((tmpdir = getenv("TMPDIR")) == NULL)
+ tmpdir = "/tmp";
+ r = snprintf(template, sizeof(template), "%s/%s", tmpdir, base);
+ if (r < 0 || (size_t)r >= sizeof(template))
+ fatal("template string too long");
+ dir = mkdtemp(template);
+ if (dir == NULL) {
+ perror("mkdtemp");
+ exit(1);
+ }
+ puts(dir);
+ return 0;
+}
diff --git a/regress/modpipe.c b/regress/modpipe.c
new file mode 100644
index 00000000..5f4824b5
--- /dev/null
+++ b/regress/modpipe.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+/* $OpenBSD: modpipe.c,v 1.6 2013/11/21 03:16:47 djm Exp $ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef HAVE_ERR_H
+# include <err.h>
+#endif
+#include "openbsd-compat/getopt_long.c"
+
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: modpipe -w [-m modspec ...] < in > out\n");
+ fprintf(stderr, "modspec is one of:\n");
+ fprintf(stderr, " xor:offset:value - XOR \"value\" at \"offset\"\n");
+ fprintf(stderr, " andor:offset:val1:val2 - AND \"val1\" then OR \"val2\" at \"offset\"\n");
+ exit(1);
+}
+
+#define MAX_MODIFICATIONS 256
+struct modification {
+ enum { MOD_XOR, MOD_AND_OR } what;
+ unsigned long long offset;
+ u_int8_t m1, m2;
+};
+
+static void
+parse_modification(const char *s, struct modification *m)
+{
+ char what[16+1];
+ int n, m1, m2;
+
+ bzero(m, sizeof(*m));
+ if ((n = sscanf(s, "%16[^:]%*[:]%llu%*[:]%i%*[:]%i",
+ what, &m->offset, &m1, &m2)) < 3)
+ errx(1, "Invalid modification spec \"%s\"", s);
+ if (strcasecmp(what, "xor") == 0) {
+ if (n > 3)
+ errx(1, "Invalid modification spec \"%s\"", s);
+ if (m1 < 0 || m1 > 0xff)
+ errx(1, "Invalid XOR modification value");
+ m->what = MOD_XOR;
+ m->m1 = m1;
+ } else if (strcasecmp(what, "andor") == 0) {
+ if (n != 4)
+ errx(1, "Invalid modification spec \"%s\"", s);
+ if (m1 < 0 || m1 > 0xff)
+ errx(1, "Invalid AND modification value");
+ if (m2 < 0 || m2 > 0xff)
+ errx(1, "Invalid OR modification value");
+ m->what = MOD_AND_OR;
+ m->m1 = m1;
+ m->m2 = m2;
+ } else
+ errx(1, "Invalid modification type \"%s\"", what);
+}
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+ u_char buf[8192];
+ size_t total;
+ ssize_t r, s, o;
+ struct modification mods[MAX_MODIFICATIONS];
+ u_int i, wflag = 0, num_mods = 0;
+
+ while ((ch = getopt(argc, argv, "wm:")) != -1) {
+ switch (ch) {
+ case 'm':
+ if (num_mods >= MAX_MODIFICATIONS)
+ errx(1, "Too many modifications");
+ parse_modification(optarg, &(mods[num_mods++]));
+ break;
+ case 'w':
+ wflag = 1;
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ for (total = 0;;) {
+ r = s = read(STDIN_FILENO, buf, sizeof(buf));
+ if (r == 0)
+ break;
+ if (r < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ err(1, "read");
+ }
+ for (i = 0; i < num_mods; i++) {
+ if (mods[i].offset < total ||
+ mods[i].offset >= total + s)
+ continue;
+ switch (mods[i].what) {
+ case MOD_XOR:
+ buf[mods[i].offset - total] ^= mods[i].m1;
+ break;
+ case MOD_AND_OR:
+ buf[mods[i].offset - total] &= mods[i].m1;
+ buf[mods[i].offset - total] |= mods[i].m2;
+ break;
+ }
+ }
+ for (o = 0; o < s; o += r) {
+ r = write(STDOUT_FILENO, buf, s - o);
+ if (r == 0)
+ break;
+ if (r < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ err(1, "write");
+ }
+ }
+ total += s;
+ }
+ /* Warn if modifications not reached in input stream */
+ r = 0;
+ for (i = 0; wflag && i < num_mods; i++) {
+ if (mods[i].offset < total)
+ continue;
+ r = 1;
+ fprintf(stderr, "modpipe: warning - mod %u not reached\n", i);
+ }
+ return r;
+}
diff --git a/regress/moduli.in b/regress/moduli.in
new file mode 100644
index 00000000..e69c902a
--- /dev/null
+++ b/regress/moduli.in
@@ -0,0 +1,3 @@
+20160301052556 2 6 100 2047 5 DA57B18976E9C55CEAC3BFFF70419A1550258EA7359400BD4FAC8F4203B73E0BC54D62C0A2D9AA9B543FACA0290514EA426DE6FEF897CB858243511DCE5170420C799D888DCFDC4502FF49B66F34E75C00E98A55408A791FF5CFEA7C288F8E6664226A6A90BE237D2E40C207B5AD0CAEDFDA4946E63AEA351A09EF462515FED4098694241CD07E2CB7727B39B8B1B9467D72DFB908D8169F5DB3CD5A6BEBE1344C585A882508B760402E86EB9B5548A7B98635ECFCDC02FF62B29C53847142FC598ADC66F622F6E9F73BDF02B3D795C0DF23D00E5A3A7748F3E1D5B06F46D4568CE3F4CC57E67D4C36DF5C12800620698C727CC5F5BCACF3B7E17E37D19F4647
+20160301052601 2 6 100 2047 2 DA57B18976E9C55CEAC3BFFF70419A1550258EA7359400BD4FAC8F4203B73E0BC54D62C0A2D9AA9B543FACA0290514EA426DE6FEF897CB858243511DCE5170420C799D888DCFDC4502FF49B66F34E75C00E98A55408A791FF5CFEA7C288F8E6664226A6A90BE237D2E40C207B5AD0CAEDFDA4946E63AEA351A09EF462515FED4098694241CD07E2CB7727B39B8B1B9467D72DFB908D8169F5DB3CD5A6BEBE1344C585A882508B760402E86EB9B5548A7B98635ECFCDC02FF62B29C53847142FC598ADC66F622F6E9F73BDF02B3D795C0DF23D00E5A3A7748F3E1D5B06F46D4568CE3F4CC57E67D4C36DF5C12800620698C727CC5F5BCACF3B7E17E37D1A5C13B
+20160301052612 2 6 100 2047 5 DA57B18976E9C55CEAC3BFFF70419A1550258EA7359400BD4FAC8F4203B73E0BC54D62C0A2D9AA9B543FACA0290514EA426DE6FEF897CB858243511DCE5170420C799D888DCFDC4502FF49B66F34E75C00E98A55408A791FF5CFEA7C288F8E6664226A6A90BE237D2E40C207B5AD0CAEDFDA4946E63AEA351A09EF462515FED4098694241CD07E2CB7727B39B8B1B9467D72DFB908D8169F5DB3CD5A6BEBE1344C585A882508B760402E86EB9B5548A7B98635ECFCDC02FF62B29C53847142FC598ADC66F622F6E9F73BDF02B3D795C0DF23D00E5A3A7748F3E1D5B06F46D4568CE3F4CC57E67D4C36DF5C12800620698C727CC5F5BCACF3B7E17E37D1B7A3EF
diff --git a/regress/multiplex.sh b/regress/multiplex.sh
new file mode 100644
index 00000000..817ddbfa
--- /dev/null
+++ b/regress/multiplex.sh
@@ -0,0 +1,197 @@
+# $OpenBSD: multiplex.sh,v 1.32 2020/01/25 02:57:53 dtucker Exp $
+# Placed in the Public Domain.
+
+make_tmpdir
+CTL=${SSH_REGRESS_TMP}/ctl-sock
+
+tid="connection multiplexing"
+
+trace "will use ProxyCommand $proxycmd"
+if config_defined DISABLE_FD_PASSING ; then
+ echo "skipped (not supported on this platform)"
+ exit 0
+fi
+
+P=3301 # test port
+
+wait_for_mux_master_ready()
+{
+ for i in 1 2 3 4 5 6 7 8 9; do
+ ${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost \
+ >/dev/null 2>&1 && return 0
+ sleep $i
+ done
+ fatal "mux master never becomes ready"
+}
+
+start_sshd
+
+start_mux_master()
+{
+ trace "start master, fork to background"
+ ${SSH} -Nn2 -MS$CTL -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" somehost \
+ -E $TEST_REGRESS_LOGFILE 2>&1 &
+ # NB. $SSH_PID will be killed by test-exec.sh:cleanup on fatal errors.
+ SSH_PID=$!
+ wait_for_mux_master_ready
+}
+
+start_mux_master
+
+verbose "test $tid: envpass"
+trace "env passing over multiplexed connection"
+_XXX_TEST=blah ${SSH} -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" -S$CTL otherhost sh << 'EOF'
+ test X"$_XXX_TEST" = X"blah"
+EOF
+if [ $? -ne 0 ]; then
+ fail "environment not found"
+fi
+
+verbose "test $tid: transfer"
+rm -f ${COPY}
+trace "ssh transfer over multiplexed connection and check result"
+${SSH} -F $OBJ/ssh_config -S$CTL otherhost cat ${DATA} > ${COPY}
+test -f ${COPY} || fail "ssh -Sctl: failed copy ${DATA}"
+cmp ${DATA} ${COPY} || fail "ssh -Sctl: corrupted copy of ${DATA}"
+
+rm -f ${COPY}
+trace "ssh transfer over multiplexed connection and check result"
+${SSH} -F $OBJ/ssh_config -S $CTL otherhost cat ${DATA} > ${COPY}
+test -f ${COPY} || fail "ssh -S ctl: failed copy ${DATA}"
+cmp ${DATA} ${COPY} || fail "ssh -S ctl: corrupted copy of ${DATA}"
+
+rm -f ${COPY}
+trace "sftp transfer over multiplexed connection and check result"
+echo "get ${DATA} ${COPY}" | \
+ ${SFTP} -S ${SSH} -F $OBJ/ssh_config -oControlPath=$CTL otherhost >>$TEST_REGRESS_LOGFILE 2>&1
+test -f ${COPY} || fail "sftp: failed copy ${DATA}"
+cmp ${DATA} ${COPY} || fail "sftp: corrupted copy of ${DATA}"
+
+rm -f ${COPY}
+trace "scp transfer over multiplexed connection and check result"
+${SCP} -S ${SSH} -F $OBJ/ssh_config -oControlPath=$CTL otherhost:${DATA} ${COPY} >>$TEST_REGRESS_LOGFILE 2>&1
+test -f ${COPY} || fail "scp: failed copy ${DATA}"
+cmp ${DATA} ${COPY} || fail "scp: corrupted copy of ${DATA}"
+
+rm -f ${COPY}
+verbose "test $tid: forward"
+trace "forward over TCP/IP and check result"
+$NC -N -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} > /dev/null &
+netcat_pid=$!
+${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L127.0.0.1:$((${PORT} + 2)):127.0.0.1:$((${PORT} + 1)) otherhost >>$TEST_SSH_LOGFILE 2>&1
+sleep 1 # XXX remove once race fixed
+$NC 127.0.0.1 $((${PORT} + 2)) < /dev/null > ${COPY}
+cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
+kill $netcat_pid 2>/dev/null
+rm -f ${COPY} $OBJ/unix-[123].fwd
+
+trace "forward over UNIX and check result"
+$NC -N -Ul $OBJ/unix-1.fwd < ${DATA} > /dev/null &
+netcat_pid=$!
+${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L$OBJ/unix-2.fwd:$OBJ/unix-1.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
+${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R$OBJ/unix-3.fwd:$OBJ/unix-2.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
+sleep 1 # XXX remove once race fixed
+$NC -U $OBJ/unix-3.fwd < /dev/null > ${COPY}
+cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
+kill $netcat_pid 2>/dev/null
+rm -f ${COPY} $OBJ/unix-[123].fwd
+
+for s in 0 1 4 5 44; do
+ trace "exit status $s over multiplexed connection"
+ verbose "test $tid: status $s"
+ ${SSH} -F $OBJ/ssh_config -S $CTL otherhost exit $s
+ r=$?
+ if [ $r -ne $s ]; then
+ fail "exit code mismatch: $r != $s"
+ fi
+
+ # same with early close of stdout/err
+ trace "exit status $s with early close over multiplexed connection"
+ ${SSH} -F $OBJ/ssh_config -S $CTL -n otherhost \
+ exec sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\'
+ r=$?
+ if [ $r -ne $s ]; then
+ fail "exit code (with sleep) mismatch: $r != $s"
+ fi
+done
+
+verbose "test $tid: cmd check"
+${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
+ || fail "check command failed"
+
+verbose "test $tid: cmd forward local (TCP)"
+${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $P:localhost:$PORT otherhost \
+ || fail "request local forward failed"
+sleep 1 # XXX remove once race fixed
+${SSH} -F $OBJ/ssh_config -p$P otherhost true \
+ || fail "connect to local forward port failed"
+${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $P:localhost:$PORT otherhost \
+ || fail "cancel local forward failed"
+${SSH} -F $OBJ/ssh_config -p$P otherhost true \
+ && fail "local forward port still listening"
+
+verbose "test $tid: cmd forward remote (TCP)"
+${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $P:localhost:$PORT otherhost \
+ || fail "request remote forward failed"
+sleep 1 # XXX remove once race fixed
+${SSH} -F $OBJ/ssh_config -p$P otherhost true \
+ || fail "connect to remote forwarded port failed"
+${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $P:localhost:$PORT otherhost \
+ || fail "cancel remote forward failed"
+${SSH} -F $OBJ/ssh_config -p$P otherhost true \
+ && fail "remote forward port still listening"
+
+verbose "test $tid: cmd forward local (UNIX)"
+${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \
+ || fail "request local forward failed"
+sleep 1 # XXX remove once race fixed
+echo "" | $NC -U $OBJ/unix-1.fwd | \
+ grep "Invalid SSH identification string" >/dev/null 2>&1 \
+ || fail "connect to local forward path failed"
+${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \
+ || fail "cancel local forward failed"
+N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l)
+test ${N} -eq 0 || fail "local forward path still listening"
+rm -f $OBJ/unix-1.fwd
+
+verbose "test $tid: cmd forward remote (UNIX)"
+${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \
+ || fail "request remote forward failed"
+sleep 1 # XXX remove once race fixed
+echo "" | $NC -U $OBJ/unix-1.fwd | \
+ grep "Invalid SSH identification string" >/dev/null 2>&1 \
+ || fail "connect to remote forwarded path failed"
+${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \
+ || fail "cancel remote forward failed"
+N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l)
+test ${N} -eq 0 || fail "remote forward path still listening"
+rm -f $OBJ/unix-1.fwd
+
+verbose "test $tid: cmd exit"
+${SSH} -F $OBJ/ssh_config -S $CTL -Oexit otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
+ || fail "send exit command failed"
+
+# Wait for master to exit
+wait $SSH_PID
+kill -0 $SSH_PID >/dev/null 2>&1 && fail "exit command failed"
+
+# Restart master and test -O stop command with master using -N
+verbose "test $tid: cmd stop"
+trace "restart master, fork to background"
+start_mux_master
+
+# start a long-running command then immediately request a stop
+${SSH} -F $OBJ/ssh_config -S $CTL otherhost "sleep 10; exit 0" \
+ >>$TEST_REGRESS_LOGFILE 2>&1 &
+SLEEP_PID=$!
+${SSH} -F $OBJ/ssh_config -S $CTL -Ostop otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
+ || fail "send stop command failed"
+
+# wait until both long-running command and master have exited.
+wait $SLEEP_PID
+[ $! != 0 ] || fail "waiting for concurrent command"
+wait $SSH_PID
+[ $! != 0 ] || fail "waiting for master stop"
+kill -0 $SSH_PID >/dev/null 2>&1 && fatal "stop command failed"
+SSH_PID="" # Already gone, so don't kill in cleanup
+
diff --git a/regress/multipubkey.sh b/regress/multipubkey.sh
new file mode 100644
index 00000000..9b227335
--- /dev/null
+++ b/regress/multipubkey.sh
@@ -0,0 +1,66 @@
+# $OpenBSD: multipubkey.sh,v 1.3 2019/12/11 18:47:14 djm Exp $
+# Placed in the Public Domain.
+
+tid="multiple pubkey"
+
+rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/user_key*
+rm -f $OBJ/authorized_principals_$USER $OBJ/cert_user_key*
+
+mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
+mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig
+
+# Create a CA key
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key ||\
+ fatal "ssh-keygen failed"
+
+# Make some keys and a certificate.
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key1 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key2 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \
+ -z $$ -n ${USER},mekmitasdigoat $OBJ/user_key1 ||
+ fail "couldn't sign user_key1"
+# Copy the private key alongside the cert to allow better control of when
+# it is offered.
+mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1.pub
+cp -p $OBJ/user_key1 $OBJ/cert_user_key1
+
+grep -v IdentityFile $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy
+
+opts="-oProtocol=2 -F $OBJ/ssh_proxy -oIdentitiesOnly=yes"
+opts="$opts -i $OBJ/cert_user_key1 -i $OBJ/user_key1 -i $OBJ/user_key2"
+
+for privsep in yes ; do
+ (
+ grep -v "Protocol" $OBJ/sshd_proxy.orig
+ echo "Protocol 2"
+ echo "UsePrivilegeSeparation $privsep"
+ echo "AuthenticationMethods publickey,publickey"
+ echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
+ echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
+ ) > $OBJ/sshd_proxy
+
+ # Single key should fail.
+ rm -f $OBJ/authorized_principals_$USER
+ cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
+ ${SSH} $opts proxy true && fail "ssh succeeded with key"
+
+ # Single key with same-public cert should fail.
+ echo mekmitasdigoat > $OBJ/authorized_principals_$USER
+ cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
+ ${SSH} $opts proxy true && fail "ssh succeeded with key+cert"
+
+ # Multiple plain keys should succeed.
+ rm -f $OBJ/authorized_principals_$USER
+ cat $OBJ/user_key1.pub $OBJ/user_key2.pub > \
+ $OBJ/authorized_keys_$USER
+ ${SSH} $opts proxy true || fail "ssh failed with multiple keys"
+ # Cert and different key should succeed
+
+ # Key and different-public cert should succeed.
+ echo mekmitasdigoat > $OBJ/authorized_principals_$USER
+ cat $OBJ/user_key2.pub > $OBJ/authorized_keys_$USER
+ ${SSH} $opts proxy true || fail "ssh failed with key/cert"
+done
+
diff --git a/regress/netcat.c b/regress/netcat.c
new file mode 100644
index 00000000..fe94dd90
--- /dev/null
+++ b/regress/netcat.c
@@ -0,0 +1,1671 @@
+/* $OpenBSD: netcat.c,v 1.126 2014/10/30 16:08:31 tedu Exp $ */
+/*
+ * Copyright (c) 2001 Eric Jackson <ericj@monkey.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.
+ * 3. 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.
+ */
+
+/*
+ * Re-written nc(1) for OpenBSD. Original implementation by
+ * *Hobbit* <hobbit@avian.org>.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netinet/ip.h>
+
+#include <errno.h>
+#include <netdb.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
+#include <poll.h>
+#else
+# ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+# endif
+#endif
+#ifdef HAVE_ERR_H
+# include <err.h>
+#endif
+#ifdef HAVE_SYS_BYTEORDER_H
+# include <sys/byteorder.h>
+#endif
+
+/* Telnet options from arpa/telnet.h */
+#define IAC 255
+#define DONT 254
+#define DO 253
+#define WONT 252
+#define WILL 251
+
+#ifndef SUN_LEN
+#define SUN_LEN(su) \
+ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
+#endif
+
+#define PORT_MAX 65535
+#define PORT_MAX_LEN 6
+#define UNIX_DG_TMP_SOCKET_SIZE 19
+
+#define POLL_STDIN 0
+#define POLL_NETOUT 1
+#define POLL_NETIN 2
+#define POLL_STDOUT 3
+#define BUFSIZE 16384
+
+/* Command Line Options */
+int dflag; /* detached, no stdin */
+int Fflag; /* fdpass sock to stdout */
+unsigned int iflag; /* Interval Flag */
+int kflag; /* More than one connect */
+int lflag; /* Bind to local port */
+int Nflag; /* shutdown() network socket */
+int nflag; /* Don't do name look up */
+char *Pflag; /* Proxy username */
+char *pflag; /* Localport flag */
+int rflag; /* Random ports flag */
+char *sflag; /* Source Address */
+int tflag; /* Telnet Emulation */
+int uflag; /* UDP - Default to TCP */
+int vflag; /* Verbosity */
+int xflag; /* Socks proxy */
+int zflag; /* Port Scan Flag */
+int Dflag; /* sodebug */
+int Iflag; /* TCP receive buffer size */
+int Oflag; /* TCP send buffer size */
+int Sflag; /* TCP MD5 signature option */
+int Tflag = -1; /* IP Type of Service */
+int rtableid = -1;
+
+int timeout = -1;
+int family = AF_UNSPEC;
+char *portlist[PORT_MAX+1];
+char *unix_dg_tmp_socket;
+
+void atelnet(int, unsigned char *, unsigned int);
+void build_ports(char *);
+void help(void);
+int local_listen(char *, char *, struct addrinfo);
+void readwrite(int);
+void fdpass(int nfd) __attribute__((noreturn));
+int remote_connect(const char *, const char *, struct addrinfo);
+int timeout_connect(int, const struct sockaddr *, socklen_t);
+int socks_connect(const char *, const char *, struct addrinfo,
+ const char *, const char *, struct addrinfo, int, const char *);
+int udptest(int);
+int unix_bind(char *);
+int unix_connect(char *);
+int unix_listen(char *);
+void set_common_sockopts(int);
+int map_tos(char *, int *);
+void report_connect(const struct sockaddr *, socklen_t);
+void usage(int);
+ssize_t drainbuf(int, unsigned char *, size_t *);
+ssize_t fillbuf(int, unsigned char *, size_t *);
+
+
+int
+main(int argc, char *argv[])
+{
+ int ch, s, ret, socksv;
+ char *host, *uport;
+ struct addrinfo hints;
+ struct servent *sv;
+ socklen_t len;
+ struct sockaddr_storage cliaddr;
+ char *proxy = NULL;
+ const char *errstr, *proxyhost = "", *proxyport = NULL;
+ struct addrinfo proxyhints;
+ char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
+
+ ret = 1;
+ s = 0;
+ socksv = 5;
+ host = NULL;
+ uport = NULL;
+ sv = NULL;
+
+ while ((ch = getopt(argc, argv,
+ "46DdFhI:i:klNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
+ switch (ch) {
+ case '4':
+ family = AF_INET;
+ break;
+ case '6':
+ family = AF_INET6;
+ break;
+ case 'U':
+ family = AF_UNIX;
+ break;
+ case 'X':
+ if (strcasecmp(optarg, "connect") == 0)
+ socksv = -1; /* HTTP proxy CONNECT */
+ else if (strcmp(optarg, "4") == 0)
+ socksv = 4; /* SOCKS v.4 */
+ else if (strcmp(optarg, "5") == 0)
+ socksv = 5; /* SOCKS v.5 */
+ else
+ errx(1, "unsupported proxy protocol");
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'F':
+ Fflag = 1;
+ break;
+ case 'h':
+ help();
+ break;
+ case 'i':
+ iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
+ if (errstr)
+ errx(1, "interval %s: %s", errstr, optarg);
+ break;
+ case 'k':
+ kflag = 1;
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'N':
+ Nflag = 1;
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 'P':
+ Pflag = optarg;
+ break;
+ case 'p':
+ pflag = optarg;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 's':
+ sflag = optarg;
+ break;
+ case 't':
+ tflag = 1;
+ break;
+ case 'u':
+ uflag = 1;
+ break;
+#ifdef SO_RTABLE
+ case 'V':
+ rtableid = (int)strtonum(optarg, 0,
+ RT_TABLEID_MAX, &errstr);
+ if (errstr)
+ errx(1, "rtable %s: %s", errstr, optarg);
+ break;
+#endif
+ case 'v':
+ vflag = 1;
+ break;
+ case 'w':
+ timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
+ if (errstr)
+ errx(1, "timeout %s: %s", errstr, optarg);
+ timeout *= 1000;
+ break;
+ case 'x':
+ xflag = 1;
+ if ((proxy = strdup(optarg)) == NULL)
+ errx(1, "strdup");
+ break;
+ case 'z':
+ zflag = 1;
+ break;
+ case 'D':
+ Dflag = 1;
+ break;
+ case 'I':
+ Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
+ if (errstr != NULL)
+ errx(1, "TCP receive window %s: %s",
+ errstr, optarg);
+ break;
+ case 'O':
+ Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
+ if (errstr != NULL)
+ errx(1, "TCP send window %s: %s",
+ errstr, optarg);
+ break;
+ case 'S':
+ Sflag = 1;
+ break;
+ case 'T':
+ errstr = NULL;
+ errno = 0;
+ if (map_tos(optarg, &Tflag))
+ break;
+ if (strlen(optarg) > 1 && optarg[0] == '0' &&
+ optarg[1] == 'x')
+ Tflag = (int)strtol(optarg, NULL, 16);
+ else
+ Tflag = (int)strtonum(optarg, 0, 255,
+ &errstr);
+ if (Tflag < 0 || Tflag > 255 || errstr || errno)
+ errx(1, "illegal tos value %s", optarg);
+ break;
+ default:
+ usage(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Cruft to make sure options are clean, and used properly. */
+ if (argv[0] && !argv[1] && family == AF_UNIX) {
+ host = argv[0];
+ uport = NULL;
+ } else if (argv[0] && !argv[1]) {
+ if (!lflag)
+ usage(1);
+ uport = argv[0];
+ host = NULL;
+ } else if (argv[0] && argv[1]) {
+ host = argv[0];
+ uport = argv[1];
+ } else
+ usage(1);
+
+ if (lflag && sflag)
+ errx(1, "cannot use -s and -l");
+ if (lflag && pflag)
+ errx(1, "cannot use -p and -l");
+ if (lflag && zflag)
+ errx(1, "cannot use -z and -l");
+ if (!lflag && kflag)
+ errx(1, "must use -l with -k");
+
+ /* Get name of temporary socket for unix datagram client */
+ if ((family == AF_UNIX) && uflag && !lflag) {
+ if (sflag) {
+ unix_dg_tmp_socket = sflag;
+ } else {
+ strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
+ UNIX_DG_TMP_SOCKET_SIZE);
+ if (mktemp(unix_dg_tmp_socket_buf) == NULL)
+ err(1, "mktemp");
+ unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
+ }
+ }
+
+ /* Initialize addrinfo structure. */
+ if (family != AF_UNIX) {
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = family;
+ hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
+ if (nflag)
+ hints.ai_flags |= AI_NUMERICHOST;
+ }
+
+ if (xflag) {
+ if (uflag)
+ errx(1, "no proxy support for UDP mode");
+
+ if (lflag)
+ errx(1, "no proxy support for listen");
+
+ if (family == AF_UNIX)
+ errx(1, "no proxy support for unix sockets");
+
+ /* XXX IPv6 transport to proxy would probably work */
+ if (family == AF_INET6)
+ errx(1, "no proxy support for IPv6");
+
+ if (sflag)
+ errx(1, "no proxy support for local source address");
+
+ proxyhost = strsep(&proxy, ":");
+ proxyport = proxy;
+
+ memset(&proxyhints, 0, sizeof(struct addrinfo));
+ proxyhints.ai_family = family;
+ proxyhints.ai_socktype = SOCK_STREAM;
+ proxyhints.ai_protocol = IPPROTO_TCP;
+ if (nflag)
+ proxyhints.ai_flags |= AI_NUMERICHOST;
+ }
+
+ if (lflag) {
+ int connfd;
+ ret = 0;
+
+ if (family == AF_UNIX) {
+ if (uflag)
+ s = unix_bind(host);
+ else
+ s = unix_listen(host);
+ }
+
+ /* Allow only one connection at a time, but stay alive. */
+ for (;;) {
+ if (family != AF_UNIX)
+ s = local_listen(host, uport, hints);
+ if (s < 0)
+ err(1, "local_listen");
+ /*
+ * For UDP and -k, don't connect the socket, let it
+ * receive datagrams from multiple socket pairs.
+ */
+ if (uflag && kflag)
+ readwrite(s);
+ /*
+ * For UDP and not -k, we will use recvfrom() initially
+ * to wait for a caller, then use the regular functions
+ * to talk to the caller.
+ */
+ else if (uflag && !kflag) {
+ int rv, plen;
+ char buf[16384];
+ struct sockaddr_storage z;
+
+ len = sizeof(z);
+ plen = 2048;
+ rv = recvfrom(s, buf, plen, MSG_PEEK,
+ (struct sockaddr *)&z, &len);
+ if (rv < 0)
+ err(1, "recvfrom");
+
+ rv = connect(s, (struct sockaddr *)&z, len);
+ if (rv < 0)
+ err(1, "connect");
+
+ if (vflag)
+ report_connect((struct sockaddr *)&z, len);
+
+ readwrite(s);
+ } else {
+ len = sizeof(cliaddr);
+ connfd = accept(s, (struct sockaddr *)&cliaddr,
+ &len);
+ if (connfd == -1) {
+ /* For now, all errnos are fatal */
+ err(1, "accept");
+ }
+ if (vflag)
+ report_connect((struct sockaddr *)&cliaddr, len);
+
+ readwrite(connfd);
+ close(connfd);
+ }
+
+ if (family != AF_UNIX)
+ close(s);
+ else if (uflag) {
+ if (connect(s, NULL, 0) < 0)
+ err(1, "connect");
+ }
+
+ if (!kflag)
+ break;
+ }
+ } else if (family == AF_UNIX) {
+ ret = 0;
+
+ if ((s = unix_connect(host)) > 0 && !zflag) {
+ readwrite(s);
+ close(s);
+ } else
+ ret = 1;
+
+ if (uflag)
+ unlink(unix_dg_tmp_socket);
+ exit(ret);
+
+ } else {
+ int i = 0;
+
+ /* Construct the portlist[] array. */
+ build_ports(uport);
+
+ /* Cycle through portlist, connecting to each port. */
+ for (i = 0; portlist[i] != NULL; i++) {
+ if (s)
+ close(s);
+
+ if (xflag)
+ s = socks_connect(host, portlist[i], hints,
+ proxyhost, proxyport, proxyhints, socksv,
+ Pflag);
+ else
+ s = remote_connect(host, portlist[i], hints);
+
+ if (s < 0)
+ continue;
+
+ ret = 0;
+ if (vflag || zflag) {
+ /* For UDP, make sure we are connected. */
+ if (uflag) {
+ if (udptest(s) == -1) {
+ ret = 1;
+ continue;
+ }
+ }
+
+ /* Don't look up port if -n. */
+ if (nflag)
+ sv = NULL;
+ else {
+ sv = getservbyport(
+ ntohs(atoi(portlist[i])),
+ uflag ? "udp" : "tcp");
+ }
+
+ fprintf(stderr,
+ "Connection to %s %s port [%s/%s] "
+ "succeeded!\n", host, portlist[i],
+ uflag ? "udp" : "tcp",
+ sv ? sv->s_name : "*");
+ }
+ if (Fflag)
+ fdpass(s);
+ else if (!zflag)
+ readwrite(s);
+ }
+ }
+
+ if (s)
+ close(s);
+
+ exit(ret);
+}
+
+/*
+ * unix_bind()
+ * Returns a unix socket bound to the given path
+ */
+int
+unix_bind(char *path)
+{
+ struct sockaddr_un sun_sa;
+ int s;
+
+ /* Create unix domain socket. */
+ if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM,
+ 0)) < 0)
+ return (-1);
+
+ memset(&sun_sa, 0, sizeof(struct sockaddr_un));
+ sun_sa.sun_family = AF_UNIX;
+
+ if (strlcpy(sun_sa.sun_path, path, sizeof(sun_sa.sun_path)) >=
+ sizeof(sun_sa.sun_path)) {
+ close(s);
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+
+ if (bind(s, (struct sockaddr *)&sun_sa, SUN_LEN(&sun_sa)) < 0) {
+ close(s);
+ return (-1);
+ }
+ return (s);
+}
+
+/*
+ * unix_connect()
+ * Returns a socket connected to a local unix socket. Returns -1 on failure.
+ */
+int
+unix_connect(char *path)
+{
+ struct sockaddr_un sun_sa;
+ int s;
+
+ if (uflag) {
+ if ((s = unix_bind(unix_dg_tmp_socket)) < 0)
+ return (-1);
+ } else {
+ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ return (-1);
+ }
+ (void)fcntl(s, F_SETFD, FD_CLOEXEC);
+
+ memset(&sun_sa, 0, sizeof(struct sockaddr_un));
+ sun_sa.sun_family = AF_UNIX;
+
+ if (strlcpy(sun_sa.sun_path, path, sizeof(sun_sa.sun_path)) >=
+ sizeof(sun_sa.sun_path)) {
+ close(s);
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ if (connect(s, (struct sockaddr *)&sun_sa, SUN_LEN(&sun_sa)) < 0) {
+ close(s);
+ return (-1);
+ }
+ return (s);
+
+}
+
+/*
+ * unix_listen()
+ * Create a unix domain socket, and listen on it.
+ */
+int
+unix_listen(char *path)
+{
+ int s;
+ if ((s = unix_bind(path)) < 0)
+ return (-1);
+
+ if (listen(s, 5) < 0) {
+ close(s);
+ return (-1);
+ }
+ return (s);
+}
+
+/*
+ * remote_connect()
+ * Returns a socket connected to a remote host. Properly binds to a local
+ * port or source address if needed. Returns -1 on failure.
+ */
+int
+remote_connect(const char *host, const char *port, struct addrinfo hints)
+{
+ struct addrinfo *res, *res0;
+ int s, error;
+#if defined(SO_RTABLE) || defined(SO_BINDANY)
+ int on = 1;
+#endif
+
+ if ((error = getaddrinfo(host, port, &hints, &res)))
+ errx(1, "getaddrinfo: %s", gai_strerror(error));
+
+ res0 = res;
+ do {
+ if ((s = socket(res0->ai_family, res0->ai_socktype,
+ res0->ai_protocol)) < 0)
+ continue;
+
+#ifdef SO_RTABLE
+ if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
+ &rtableid, sizeof(rtableid)) == -1))
+ err(1, "setsockopt SO_RTABLE");
+#endif
+ /* Bind to a local port or source address if specified. */
+ if (sflag || pflag) {
+ struct addrinfo ahints, *ares;
+
+#ifdef SO_BINDANY
+ /* try SO_BINDANY, but don't insist */
+ setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
+#endif
+ memset(&ahints, 0, sizeof(struct addrinfo));
+ ahints.ai_family = res0->ai_family;
+ ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
+ ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
+ ahints.ai_flags = AI_PASSIVE;
+ if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
+ errx(1, "getaddrinfo: %s", gai_strerror(error));
+
+ if (bind(s, (struct sockaddr *)ares->ai_addr,
+ ares->ai_addrlen) < 0)
+ err(1, "bind failed");
+ freeaddrinfo(ares);
+ }
+
+ set_common_sockopts(s);
+
+ if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
+ break;
+ else if (vflag)
+ warn("connect to %s port %s (%s) failed", host, port,
+ uflag ? "udp" : "tcp");
+
+ close(s);
+ s = -1;
+ } while ((res0 = res0->ai_next) != NULL);
+
+ freeaddrinfo(res);
+
+ return (s);
+}
+
+int
+timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+ struct pollfd pfd;
+ socklen_t optlen;
+ int flags = 0, optval;
+ int ret;
+
+ if (timeout != -1) {
+ flags = fcntl(s, F_GETFL, 0);
+ if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
+ err(1, "set non-blocking mode");
+ }
+
+ if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
+ pfd.fd = s;
+ pfd.events = POLLOUT;
+ if ((ret = poll(&pfd, 1, timeout)) == 1) {
+ optlen = sizeof(optval);
+ if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
+ &optval, &optlen)) == 0) {
+ errno = optval;
+ ret = optval == 0 ? 0 : -1;
+ }
+ } else if (ret == 0) {
+ errno = ETIMEDOUT;
+ ret = -1;
+ } else
+ err(1, "poll failed");
+ }
+
+ if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
+ err(1, "restoring flags");
+
+ return (ret);
+}
+
+/*
+ * local_listen()
+ * Returns a socket listening on a local port, binds to specified source
+ * address. Returns -1 on failure.
+ */
+int
+local_listen(char *host, char *port, struct addrinfo hints)
+{
+ struct addrinfo *res, *res0;
+ int s, ret, x = 1;
+ int error;
+
+ /* Allow nodename to be null. */
+ hints.ai_flags |= AI_PASSIVE;
+
+ /*
+ * In the case of binding to a wildcard address
+ * default to binding to an ipv4 address.
+ */
+ if (host == NULL && hints.ai_family == AF_UNSPEC)
+ hints.ai_family = AF_INET;
+
+ if ((error = getaddrinfo(host, port, &hints, &res)))
+ errx(1, "getaddrinfo: %s", gai_strerror(error));
+
+ res0 = res;
+ do {
+ if ((s = socket(res0->ai_family, res0->ai_socktype,
+ res0->ai_protocol)) < 0)
+ continue;
+
+#ifdef SO_RTABLE
+ if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
+ &rtableid, sizeof(rtableid)) == -1))
+ err(1, "setsockopt SO_RTABLE");
+#endif
+#ifdef SO_REUSEPORT
+ ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
+ if (ret == -1)
+ err(1, "setsockopt SO_REUSEPORT");
+#endif
+#ifdef SO_REUSEADDR
+ ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
+ if (ret == -1)
+ err(1, "setsockopt SO_REUSEADDR");
+#endif
+ set_common_sockopts(s);
+
+ if (bind(s, (struct sockaddr *)res0->ai_addr,
+ res0->ai_addrlen) == 0)
+ break;
+
+ close(s);
+ s = -1;
+ } while ((res0 = res0->ai_next) != NULL);
+
+ if (!uflag && s != -1) {
+ if (listen(s, 1) < 0)
+ err(1, "listen");
+ }
+
+ freeaddrinfo(res);
+
+ return (s);
+}
+
+/*
+ * readwrite()
+ * Loop that polls on the network file descriptor and stdin.
+ */
+void
+readwrite(int net_fd)
+{
+ struct pollfd pfd[4];
+ int stdin_fd = STDIN_FILENO;
+ int stdout_fd = STDOUT_FILENO;
+ unsigned char netinbuf[BUFSIZE];
+ size_t netinbufpos = 0;
+ unsigned char stdinbuf[BUFSIZE];
+ size_t stdinbufpos = 0;
+ int n, num_fds;
+ ssize_t ret;
+
+ /* don't read from stdin if requested */
+ if (dflag)
+ stdin_fd = -1;
+
+ /* stdin */
+ pfd[POLL_STDIN].fd = stdin_fd;
+ pfd[POLL_STDIN].events = POLLIN;
+
+ /* network out */
+ pfd[POLL_NETOUT].fd = net_fd;
+ pfd[POLL_NETOUT].events = 0;
+
+ /* network in */
+ pfd[POLL_NETIN].fd = net_fd;
+ pfd[POLL_NETIN].events = POLLIN;
+
+ /* stdout */
+ pfd[POLL_STDOUT].fd = stdout_fd;
+ pfd[POLL_STDOUT].events = 0;
+
+ while (1) {
+ /* both inputs are gone, buffers are empty, we are done */
+ if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1
+ && stdinbufpos == 0 && netinbufpos == 0) {
+ close(net_fd);
+ return;
+ }
+ /* both outputs are gone, we can't continue */
+ if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) {
+ close(net_fd);
+ return;
+ }
+ /* listen and net in gone, queues empty, done */
+ if (lflag && pfd[POLL_NETIN].fd == -1
+ && stdinbufpos == 0 && netinbufpos == 0) {
+ close(net_fd);
+ return;
+ }
+
+ /* help says -i is for "wait between lines sent". We read and
+ * write arbitrary amounts of data, and we don't want to start
+ * scanning for newlines, so this is as good as it gets */
+ if (iflag)
+ sleep(iflag);
+
+ /* poll */
+ num_fds = poll(pfd, 4, timeout);
+
+ /* treat poll errors */
+ if (num_fds == -1) {
+ close(net_fd);
+ err(1, "polling error");
+ }
+
+ /* timeout happened */
+ if (num_fds == 0)
+ return;
+
+ /* treat socket error conditions */
+ for (n = 0; n < 4; n++) {
+ if (pfd[n].revents & (POLLERR|POLLNVAL)) {
+ pfd[n].fd = -1;
+ }
+ }
+ /* reading is possible after HUP */
+ if (pfd[POLL_STDIN].events & POLLIN &&
+ pfd[POLL_STDIN].revents & POLLHUP &&
+ ! (pfd[POLL_STDIN].revents & POLLIN))
+ pfd[POLL_STDIN].fd = -1;
+
+ if (pfd[POLL_NETIN].events & POLLIN &&
+ pfd[POLL_NETIN].revents & POLLHUP &&
+ ! (pfd[POLL_NETIN].revents & POLLIN))
+ pfd[POLL_NETIN].fd = -1;
+
+ if (pfd[POLL_NETOUT].revents & POLLHUP) {
+ if (Nflag)
+ shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
+ pfd[POLL_NETOUT].fd = -1;
+ }
+ /* if HUP, stop watching stdout */
+ if (pfd[POLL_STDOUT].revents & POLLHUP)
+ pfd[POLL_STDOUT].fd = -1;
+ /* if no net out, stop watching stdin */
+ if (pfd[POLL_NETOUT].fd == -1)
+ pfd[POLL_STDIN].fd = -1;
+ /* if no stdout, stop watching net in */
+ if (pfd[POLL_STDOUT].fd == -1) {
+ if (pfd[POLL_NETIN].fd != -1)
+ shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
+ pfd[POLL_NETIN].fd = -1;
+ }
+
+ /* try to read from stdin */
+ if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) {
+ ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf,
+ &stdinbufpos);
+ /* error or eof on stdin - remove from pfd */
+ if (ret == 0 || ret == -1)
+ pfd[POLL_STDIN].fd = -1;
+ /* read something - poll net out */
+ if (stdinbufpos > 0)
+ pfd[POLL_NETOUT].events = POLLOUT;
+ /* filled buffer - remove self from polling */
+ if (stdinbufpos == BUFSIZE)
+ pfd[POLL_STDIN].events = 0;
+ }
+ /* try to write to network */
+ if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) {
+ ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf,
+ &stdinbufpos);
+ if (ret == -1)
+ pfd[POLL_NETOUT].fd = -1;
+ /* buffer empty - remove self from polling */
+ if (stdinbufpos == 0)
+ pfd[POLL_NETOUT].events = 0;
+ /* buffer no longer full - poll stdin again */
+ if (stdinbufpos < BUFSIZE)
+ pfd[POLL_STDIN].events = POLLIN;
+ }
+ /* try to read from network */
+ if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) {
+ ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf,
+ &netinbufpos);
+ if (ret == -1)
+ pfd[POLL_NETIN].fd = -1;
+ /* eof on net in - remove from pfd */
+ if (ret == 0) {
+ shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
+ pfd[POLL_NETIN].fd = -1;
+ }
+ /* read something - poll stdout */
+ if (netinbufpos > 0)
+ pfd[POLL_STDOUT].events = POLLOUT;
+ /* filled buffer - remove self from polling */
+ if (netinbufpos == BUFSIZE)
+ pfd[POLL_NETIN].events = 0;
+ /* handle telnet */
+ if (tflag)
+ atelnet(pfd[POLL_NETIN].fd, netinbuf,
+ netinbufpos);
+ }
+ /* try to write to stdout */
+ if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) {
+ ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf,
+ &netinbufpos);
+ if (ret == -1)
+ pfd[POLL_STDOUT].fd = -1;
+ /* buffer empty - remove self from polling */
+ if (netinbufpos == 0)
+ pfd[POLL_STDOUT].events = 0;
+ /* buffer no longer full - poll net in again */
+ if (netinbufpos < BUFSIZE)
+ pfd[POLL_NETIN].events = POLLIN;
+ }
+
+ /* stdin gone and queue empty? */
+ if (pfd[POLL_STDIN].fd == -1 && stdinbufpos == 0) {
+ if (pfd[POLL_NETOUT].fd != -1 && Nflag)
+ shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
+ pfd[POLL_NETOUT].fd = -1;
+ }
+ /* net in gone and queue empty? */
+ if (pfd[POLL_NETIN].fd == -1 && netinbufpos == 0) {
+ pfd[POLL_STDOUT].fd = -1;
+ }
+ }
+}
+
+ssize_t
+drainbuf(int fd, unsigned char *buf, size_t *bufpos)
+{
+ ssize_t n;
+ ssize_t adjust;
+
+ n = write(fd, buf, *bufpos);
+ /* don't treat EAGAIN, EINTR as error */
+ if (n == -1 && (errno == EAGAIN || errno == EINTR))
+ n = -2;
+ if (n <= 0)
+ return n;
+ /* adjust buffer */
+ adjust = *bufpos - n;
+ if (adjust > 0)
+ memmove(buf, buf + n, adjust);
+ *bufpos -= n;
+ return n;
+}
+
+
+ssize_t
+fillbuf(int fd, unsigned char *buf, size_t *bufpos)
+{
+ size_t num = BUFSIZE - *bufpos;
+ ssize_t n;
+
+ n = read(fd, buf + *bufpos, num);
+ /* don't treat EAGAIN, EINTR as error */
+ if (n == -1 && (errno == EAGAIN || errno == EINTR))
+ n = -2;
+ if (n <= 0)
+ return n;
+ *bufpos += n;
+ return n;
+}
+
+/*
+ * fdpass()
+ * Pass the connected file descriptor to stdout and exit.
+ */
+void
+fdpass(int nfd)
+{
+#if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR))
+ struct msghdr msg;
+#ifndef HAVE_ACCRIGHTS_IN_MSGHDR
+ union {
+ struct cmsghdr hdr;
+ char buf[CMSG_SPACE(sizeof(int))];
+ } cmsgbuf;
+ struct cmsghdr *cmsg;
+#endif
+ struct iovec vec;
+ char ch = '\0';
+ struct pollfd pfd;
+ ssize_t r;
+
+ memset(&msg, 0, sizeof(msg));
+#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
+ msg.msg_accrights = (caddr_t)&nfd;
+ msg.msg_accrightslen = sizeof(nfd);
+#else
+ memset(&cmsgbuf, 0, sizeof(cmsgbuf));
+ msg.msg_control = (caddr_t)&cmsgbuf.buf;
+ msg.msg_controllen = sizeof(cmsgbuf.buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ *(int *)CMSG_DATA(cmsg) = nfd;
+#endif
+
+ vec.iov_base = &ch;
+ vec.iov_len = 1;
+ msg.msg_iov = &vec;
+ msg.msg_iovlen = 1;
+
+ bzero(&pfd, sizeof(pfd));
+ pfd.fd = STDOUT_FILENO;
+ 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)
+ errx(1, "sendmsg: unexpected return value %zd", r);
+ else
+ break;
+ }
+ exit(0);
+#else
+ errx(1, "%s: file descriptor passing not supported", __func__);
+#endif
+}
+
+/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
+void
+atelnet(int nfd, unsigned char *buf, unsigned int size)
+{
+ unsigned char *p, *end;
+ unsigned char obuf[4];
+
+ if (size < 3)
+ return;
+ end = buf + size - 2;
+
+ for (p = buf; p < end; p++) {
+ if (*p != IAC)
+ continue;
+
+ obuf[0] = IAC;
+ p++;
+ if ((*p == WILL) || (*p == WONT))
+ obuf[1] = DONT;
+ else if ((*p == DO) || (*p == DONT))
+ obuf[1] = WONT;
+ else
+ continue;
+
+ p++;
+ obuf[2] = *p;
+ if (atomicio(vwrite, nfd, obuf, 3) != 3)
+ warn("Write Error!");
+ }
+}
+
+/*
+ * build_ports()
+ * Build an array of ports in portlist[], listing each port
+ * that we should try to connect to.
+ */
+void
+build_ports(char *p)
+{
+ const char *errstr;
+ char *n;
+ int hi, lo, cp;
+ int x = 0;
+
+ if ((n = strchr(p, '-')) != NULL) {
+ *n = '\0';
+ n++;
+
+ /* Make sure the ports are in order: lowest->highest. */
+ hi = strtonum(n, 1, PORT_MAX, &errstr);
+ if (errstr)
+ errx(1, "port number %s: %s", errstr, n);
+ lo = strtonum(p, 1, PORT_MAX, &errstr);
+ if (errstr)
+ errx(1, "port number %s: %s", errstr, p);
+
+ if (lo > hi) {
+ cp = hi;
+ hi = lo;
+ lo = cp;
+ }
+
+ /* Load ports sequentially. */
+ for (cp = lo; cp <= hi; cp++) {
+ portlist[x] = calloc(1, PORT_MAX_LEN);
+ if (portlist[x] == NULL)
+ errx(1, "calloc");
+ snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
+ x++;
+ }
+
+ /* Randomly swap ports. */
+ if (rflag) {
+ int y;
+ char *c;
+
+ for (x = 0; x <= (hi - lo); x++) {
+ y = (arc4random() & 0xFFFF) % (hi - lo);
+ c = portlist[x];
+ portlist[x] = portlist[y];
+ portlist[y] = c;
+ }
+ }
+ } else {
+ hi = strtonum(p, 1, PORT_MAX, &errstr);
+ if (errstr)
+ errx(1, "port number %s: %s", errstr, p);
+ portlist[0] = strdup(p);
+ if (portlist[0] == NULL)
+ errx(1, "strdup");
+ }
+}
+
+/*
+ * udptest()
+ * Do a few writes to see if the UDP port is there.
+ * Fails once PF state table is full.
+ */
+int
+udptest(int s)
+{
+ int i, ret;
+
+ for (i = 0; i <= 3; i++) {
+ if (write(s, "X", 1) == 1)
+ ret = 1;
+ else
+ ret = -1;
+ }
+ return (ret);
+}
+
+void
+set_common_sockopts(int s)
+{
+ int x = 1;
+
+#ifdef TCP_MD5SIG
+ if (Sflag) {
+ if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
+ &x, sizeof(x)) == -1)
+ err(1, "setsockopt");
+ }
+#endif
+ if (Dflag) {
+ if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
+ &x, sizeof(x)) == -1)
+ err(1, "setsockopt");
+ }
+#ifdef IP_TOS
+ if (Tflag != -1) {
+ if (setsockopt(s, IPPROTO_IP, IP_TOS,
+ &Tflag, sizeof(Tflag)) == -1)
+ err(1, "set IP ToS");
+ }
+#endif
+ if (Iflag) {
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
+ &Iflag, sizeof(Iflag)) == -1)
+ err(1, "set TCP receive buffer size");
+ }
+ if (Oflag) {
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
+ &Oflag, sizeof(Oflag)) == -1)
+ err(1, "set TCP send buffer size");
+ }
+}
+
+int
+map_tos(char *s, int *val)
+{
+#ifdef IP_TOS
+ /* DiffServ Codepoints and other TOS mappings */
+ const struct toskeywords {
+ const char *keyword;
+ int val;
+ } *t, toskeywords[] = {
+ { "af11", IPTOS_DSCP_AF11 },
+ { "af12", IPTOS_DSCP_AF12 },
+ { "af13", IPTOS_DSCP_AF13 },
+ { "af21", IPTOS_DSCP_AF21 },
+ { "af22", IPTOS_DSCP_AF22 },
+ { "af23", IPTOS_DSCP_AF23 },
+ { "af31", IPTOS_DSCP_AF31 },
+ { "af32", IPTOS_DSCP_AF32 },
+ { "af33", IPTOS_DSCP_AF33 },
+ { "af41", IPTOS_DSCP_AF41 },
+ { "af42", IPTOS_DSCP_AF42 },
+ { "af43", IPTOS_DSCP_AF43 },
+ { "critical", IPTOS_PREC_CRITIC_ECP },
+ { "cs0", IPTOS_DSCP_CS0 },
+ { "cs1", IPTOS_DSCP_CS1 },
+ { "cs2", IPTOS_DSCP_CS2 },
+ { "cs3", IPTOS_DSCP_CS3 },
+ { "cs4", IPTOS_DSCP_CS4 },
+ { "cs5", IPTOS_DSCP_CS5 },
+ { "cs6", IPTOS_DSCP_CS6 },
+ { "cs7", IPTOS_DSCP_CS7 },
+ { "ef", IPTOS_DSCP_EF },
+ { "inetcontrol", IPTOS_PREC_INTERNETCONTROL },
+ { "lowdelay", IPTOS_LOWDELAY },
+ { "netcontrol", IPTOS_PREC_NETCONTROL },
+ { "reliability", IPTOS_RELIABILITY },
+ { "throughput", IPTOS_THROUGHPUT },
+ { NULL, -1 },
+ };
+
+ for (t = toskeywords; t->keyword != NULL; t++) {
+ if (strcmp(s, t->keyword) == 0) {
+ *val = t->val;
+ return (1);
+ }
+ }
+#endif
+
+ return (0);
+}
+
+void
+report_connect(const struct sockaddr *sa, socklen_t salen)
+{
+ char remote_host[NI_MAXHOST];
+ char remote_port[NI_MAXSERV];
+ int herr;
+ int flags = NI_NUMERICSERV;
+
+ if (nflag)
+ flags |= NI_NUMERICHOST;
+
+ if ((herr = getnameinfo(sa, salen,
+ remote_host, sizeof(remote_host),
+ remote_port, sizeof(remote_port),
+ flags)) != 0) {
+ if (herr == EAI_SYSTEM)
+ err(1, "getnameinfo");
+ else
+ errx(1, "getnameinfo: %s", gai_strerror(herr));
+ }
+
+ fprintf(stderr,
+ "Connection from %s %s "
+ "received!\n", remote_host, remote_port);
+}
+
+void
+help(void)
+{
+ usage(0);
+ fprintf(stderr, "\tCommand Summary:\n\
+ \t-4 Use IPv4\n\
+ \t-6 Use IPv6\n\
+ \t-D Enable the debug socket option\n\
+ \t-d Detach from stdin\n\
+ \t-F Pass socket fd\n\
+ \t-h This help text\n\
+ \t-I length TCP receive buffer length\n\
+ \t-i secs\t Delay interval for lines sent, ports scanned\n\
+ \t-k Keep inbound sockets open for multiple connects\n\
+ \t-l Listen mode, for inbound connects\n\
+ \t-N Shutdown the network socket after EOF on stdin\n\
+ \t-n Suppress name/port resolutions\n\
+ \t-O length TCP send buffer length\n\
+ \t-P proxyuser\tUsername for proxy authentication\n\
+ \t-p port\t Specify local port for remote connects\n\
+ \t-r Randomize remote ports\n\
+ \t-S Enable the TCP MD5 signature option\n\
+ \t-s addr\t Local source address\n\
+ \t-T toskeyword\tSet IP Type of Service\n\
+ \t-t Answer TELNET negotiation\n\
+ \t-U Use UNIX domain socket\n\
+ \t-u UDP mode\n\
+ \t-V rtable Specify alternate routing table\n\
+ \t-v Verbose\n\
+ \t-w secs\t Timeout for connects and final net reads\n\
+ \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
+ \t-x addr[:port]\tSpecify proxy address and port\n\
+ \t-z Zero-I/O mode [used for scanning]\n\
+ Port numbers can be individual or ranges: lo-hi [inclusive]\n");
+ exit(1);
+}
+
+void
+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 [-V rtable] [-w timeout] [-X proxy_protocol]\n"
+ "\t [-x proxy_address[:port]] [destination] [port]\n");
+ if (ret)
+ exit(1);
+}
+
+/* *** src/usr.bin/nc/socks.c *** */
+
+
+/* $OpenBSD: socks.c,v 1.20 2012/03/08 09:56:28 espie Exp $ */
+
+/*
+ * Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
+ * Copyright (c) 2004, 2005 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 <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <resolv.h>
+
+#define SOCKS_PORT "1080"
+#define HTTP_PROXY_PORT "3128"
+#define HTTP_MAXHDRS 64
+#define SOCKS_V5 5
+#define SOCKS_V4 4
+#define SOCKS_NOAUTH 0
+#define SOCKS_NOMETHOD 0xff
+#define SOCKS_CONNECT 1
+#define SOCKS_IPV4 1
+#define SOCKS_DOMAIN 3
+#define SOCKS_IPV6 4
+
+int remote_connect(const char *, const char *, struct addrinfo);
+int socks_connect(const char *, const char *, struct addrinfo,
+ const char *, const char *, struct addrinfo, int,
+ const char *);
+
+static int
+decode_addrport(const char *h, const char *p, struct sockaddr *addr,
+ socklen_t addrlen, int v4only, int numeric)
+{
+ int r;
+ struct addrinfo hints, *res;
+
+ bzero(&hints, sizeof(hints));
+ hints.ai_family = v4only ? PF_INET : PF_UNSPEC;
+ hints.ai_flags = numeric ? AI_NUMERICHOST : 0;
+ hints.ai_socktype = SOCK_STREAM;
+ r = getaddrinfo(h, p, &hints, &res);
+ /* Don't fatal when attempting to convert a numeric address */
+ if (r != 0) {
+ if (!numeric) {
+ errx(1, "getaddrinfo(\"%.64s\", \"%.64s\"): %s", h, p,
+ gai_strerror(r));
+ }
+ return (-1);
+ }
+ if (addrlen < res->ai_addrlen) {
+ freeaddrinfo(res);
+ errx(1, "internal error: addrlen < res->ai_addrlen");
+ }
+ memcpy(addr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ return (0);
+}
+
+static int
+proxy_read_line(int fd, char *buf, size_t bufsz)
+{
+ size_t off;
+
+ for(off = 0;;) {
+ if (off >= bufsz)
+ errx(1, "proxy read too long");
+ if (atomicio(read, fd, buf + off, 1) != 1)
+ err(1, "proxy read");
+ /* Skip CR */
+ if (buf[off] == '\r')
+ continue;
+ if (buf[off] == '\n') {
+ buf[off] = '\0';
+ break;
+ }
+ off++;
+ }
+ return (off);
+}
+
+static const char *
+getproxypass(const char *proxyuser, const char *proxyhost)
+{
+ char prompt[512];
+ static char pw[256];
+
+ snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ",
+ proxyuser, proxyhost);
+ if (readpassphrase(prompt, pw, sizeof(pw), RPP_REQUIRE_TTY) == NULL)
+ errx(1, "Unable to read proxy passphrase");
+ return (pw);
+}
+
+int
+socks_connect(const char *host, const char *port,
+ struct addrinfo hints __attribute__ ((__unused__)),
+ const char *proxyhost, const char *proxyport, struct addrinfo proxyhints,
+ int socksv, const char *proxyuser)
+{
+ int proxyfd, r, authretry = 0;
+ size_t hlen, wlen = 0;
+ unsigned char buf[1024];
+ size_t cnt;
+ struct sockaddr_storage addr;
+ struct sockaddr_in *in4 = (struct sockaddr_in *)&addr;
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr;
+ in_port_t serverport;
+ const char *proxypass = NULL;
+
+ if (proxyport == NULL)
+ proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT;
+
+ /* Abuse API to lookup port */
+ if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr,
+ sizeof(addr), 1, 1) == -1)
+ errx(1, "unknown port \"%.64s\"", port);
+ serverport = in4->sin_port;
+
+ again:
+ if (authretry++ > 3)
+ errx(1, "Too many authentication failures");
+
+ proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
+
+ if (proxyfd < 0)
+ return (-1);
+
+ if (socksv == 5) {
+ if (decode_addrport(host, port, (struct sockaddr *)&addr,
+ sizeof(addr), 0, 1) == -1)
+ addr.ss_family = 0; /* used in switch below */
+
+ /* Version 5, one method: no authentication */
+ buf[0] = SOCKS_V5;
+ buf[1] = 1;
+ buf[2] = SOCKS_NOAUTH;
+ cnt = atomicio(vwrite, proxyfd, buf, 3);
+ if (cnt != 3)
+ err(1, "write failed (%zu/3)", cnt);
+
+ cnt = atomicio(read, proxyfd, buf, 2);
+ if (cnt != 2)
+ err(1, "read failed (%zu/3)", cnt);
+
+ if (buf[1] == SOCKS_NOMETHOD)
+ errx(1, "authentication method negotiation failed");
+
+ switch (addr.ss_family) {
+ case 0:
+ /* Version 5, connect: domain name */
+
+ /* Max domain name length is 255 bytes */
+ hlen = strlen(host);
+ if (hlen > 255)
+ errx(1, "host name too long for SOCKS5");
+ buf[0] = SOCKS_V5;
+ buf[1] = SOCKS_CONNECT;
+ buf[2] = 0;
+ buf[3] = SOCKS_DOMAIN;
+ buf[4] = hlen;
+ memcpy(buf + 5, host, hlen);
+ memcpy(buf + 5 + hlen, &serverport, sizeof serverport);
+ wlen = 7 + hlen;
+ break;
+ case AF_INET:
+ /* Version 5, connect: IPv4 address */
+ buf[0] = SOCKS_V5;
+ buf[1] = SOCKS_CONNECT;
+ buf[2] = 0;
+ buf[3] = SOCKS_IPV4;
+ memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
+ memcpy(buf + 8, &in4->sin_port, sizeof in4->sin_port);
+ wlen = 10;
+ break;
+ case AF_INET6:
+ /* Version 5, connect: IPv6 address */
+ buf[0] = SOCKS_V5;
+ buf[1] = SOCKS_CONNECT;
+ buf[2] = 0;
+ buf[3] = SOCKS_IPV6;
+ memcpy(buf + 4, &in6->sin6_addr, sizeof in6->sin6_addr);
+ memcpy(buf + 20, &in6->sin6_port,
+ sizeof in6->sin6_port);
+ wlen = 22;
+ break;
+ default:
+ errx(1, "internal error: silly AF");
+ }
+
+ cnt = atomicio(vwrite, proxyfd, buf, wlen);
+ if (cnt != wlen)
+ err(1, "write failed (%zu/%zu)", cnt, wlen);
+
+ cnt = atomicio(read, proxyfd, buf, 4);
+ if (cnt != 4)
+ err(1, "read failed (%zu/4)", cnt);
+ if (buf[1] != 0)
+ errx(1, "connection failed, SOCKS error %d", buf[1]);
+ switch (buf[3]) {
+ case SOCKS_IPV4:
+ cnt = atomicio(read, proxyfd, buf + 4, 6);
+ if (cnt != 6)
+ err(1, "read failed (%zu/6)", cnt);
+ break;
+ case SOCKS_IPV6:
+ cnt = atomicio(read, proxyfd, buf + 4, 18);
+ if (cnt != 18)
+ err(1, "read failed (%zu/18)", cnt);
+ break;
+ default:
+ errx(1, "connection failed, unsupported address type");
+ }
+ } else if (socksv == 4) {
+ /* This will exit on lookup failure */
+ decode_addrport(host, port, (struct sockaddr *)&addr,
+ sizeof(addr), 1, 0);
+
+ /* Version 4 */
+ buf[0] = SOCKS_V4;
+ buf[1] = SOCKS_CONNECT; /* connect */
+ memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port);
+ memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
+ buf[8] = 0; /* empty username */
+ wlen = 9;
+
+ cnt = atomicio(vwrite, proxyfd, buf, wlen);
+ if (cnt != wlen)
+ err(1, "write failed (%zu/%zu)", cnt, wlen);
+
+ cnt = atomicio(read, proxyfd, buf, 8);
+ if (cnt != 8)
+ err(1, "read failed (%zu/8)", cnt);
+ if (buf[1] != 90)
+ errx(1, "connection failed, SOCKS error %d", buf[1]);
+ } else if (socksv == -1) {
+ /* HTTP proxy CONNECT */
+
+ /* Disallow bad chars in hostname */
+ if (strcspn(host, "\r\n\t []:") != strlen(host))
+ errx(1, "Invalid hostname");
+
+ /* Try to be sane about numeric IPv6 addresses */
+ if (strchr(host, ':') != NULL) {
+ r = snprintf(buf, sizeof(buf),
+ "CONNECT [%s]:%d HTTP/1.0\r\n",
+ host, ntohs(serverport));
+ } else {
+ r = snprintf(buf, sizeof(buf),
+ "CONNECT %s:%d HTTP/1.0\r\n",
+ host, ntohs(serverport));
+ }
+ if (r == -1 || (size_t)r >= sizeof(buf))
+ errx(1, "hostname too long");
+ r = strlen(buf);
+
+ cnt = atomicio(vwrite, proxyfd, buf, r);
+ if (cnt != (size_t)r)
+ err(1, "write failed (%zu/%d)", cnt, r);
+
+ if (authretry > 1) {
+ char resp[1024];
+
+ proxypass = getproxypass(proxyuser, proxyhost);
+ r = snprintf(buf, sizeof(buf), "%s:%s",
+ proxyuser, proxypass);
+ if (r == -1 || (size_t)r >= sizeof(buf) ||
+ b64_ntop(buf, strlen(buf), resp,
+ sizeof(resp)) == -1)
+ errx(1, "Proxy username/password too long");
+ r = snprintf(buf, sizeof(buf), "Proxy-Authorization: "
+ "Basic %s\r\n", resp);
+ if (r == -1 || (size_t)r >= sizeof(buf))
+ errx(1, "Proxy auth response too long");
+ r = strlen(buf);
+ if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != (size_t)r)
+ err(1, "write failed (%zu/%d)", cnt, r);
+ }
+
+ /* Terminate headers */
+ if ((r = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2)
+ err(1, "write failed (2/%d)", r);
+
+ /* Read status reply */
+ proxy_read_line(proxyfd, buf, sizeof(buf));
+ if (proxyuser != NULL &&
+ strncmp(buf, "HTTP/1.0 407 ", 12) == 0) {
+ if (authretry > 1) {
+ fprintf(stderr, "Proxy authentication "
+ "failed\n");
+ }
+ close(proxyfd);
+ goto again;
+ } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0 &&
+ strncmp(buf, "HTTP/1.1 200 ", 12) != 0)
+ errx(1, "Proxy error: \"%s\"", buf);
+
+ /* Headers continue until we hit an empty line */
+ for (r = 0; r < HTTP_MAXHDRS; r++) {
+ proxy_read_line(proxyfd, buf, sizeof(buf));
+ if (*buf == '\0')
+ break;
+ }
+ if (*buf != '\0')
+ errx(1, "Too many proxy headers received");
+ } else
+ errx(1, "Unknown proxy protocol %d", socksv);
+
+ return (proxyfd);
+}
+
diff --git a/regress/percent.sh b/regress/percent.sh
new file mode 100644
index 00000000..2e891f69
--- /dev/null
+++ b/regress/percent.sh
@@ -0,0 +1,88 @@
+# $OpenBSD: percent.sh,v 1.6 2020/04/10 00:54:03 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="percent expansions"
+
+if [ -x "/usr/xpg4/bin/id" ]; then
+ PATH=/usr/xpg4/bin:$PATH
+ export PATH
+fi
+
+USER=`id -u -n`
+USERID=`id -u`
+HOST=`hostname | cut -f1 -d.`
+HOSTNAME=`hostname`
+
+# Localcommand is evaluated after connection because %T is not available
+# until then. Because of this we use a different method of exercising it,
+# and we can't override the remote user otherwise authentication will fail.
+# We also have to explicitly enable it.
+echo "permitlocalcommand yes" >> $OBJ/ssh_proxy
+
+trial()
+{
+ opt="$1"; arg="$2"; expect="$3"
+
+ trace "test $opt=$arg $expect"
+ rm -f $OBJ/actual
+ case "$opt" in
+ localcommand)
+ ${SSH} -F $OBJ/ssh_proxy -o $opt="echo '$arg' >$OBJ/actual" \
+ somehost true
+ got=`cat $OBJ/actual`
+ ;;
+ matchexec)
+ (cat $OBJ/ssh_proxy && \
+ echo "Match Exec \"echo '$arg' >$OBJ/actual\"") \
+ >$OBJ/ssh_proxy_match
+ ${SSH} -F $OBJ/ssh_proxy_match remuser@somehost true || true
+ got=`cat $OBJ/actual`
+ ;;
+ *forward)
+ # LocalForward and RemoteForward take two args and only
+ # operate on Unix domain socket paths
+ got=`${SSH} -F $OBJ/ssh_proxy -o $opt="/$arg /$arg" -G \
+ remuser@somehost | awk '$1=="'$opt'"{print $2" "$3}'`
+ expect="/$expect /$expect"
+ ;;
+ *)
+ got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg" -G \
+ remuser@somehost | awk '$1=="'$opt'"{print $2}'`
+ esac
+ if [ "$got" != "$expect" ]; then
+ fail "$opt=$arg expect $expect got $got"
+ fi
+}
+
+for i in matchexec localcommand remotecommand controlpath identityagent \
+ forwardagent localforward remoteforward; do
+ verbose $tid $i
+ if [ "$i" = "localcommand" ]; then
+ REMUSER=$USER
+ 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' '`
+ 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 '%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"
+done
+
+# A subset of options support tilde expansion
+for i in controlpath identityagent forwardagent; do
+ trial $i '~' $HOME/
+ trial $i '~/.ssh' $HOME/.ssh
+done
diff --git a/regress/portnum.sh b/regress/portnum.sh
new file mode 100644
index 00000000..c56b869a
--- /dev/null
+++ b/regress/portnum.sh
@@ -0,0 +1,34 @@
+# $OpenBSD: portnum.sh,v 1.2 2013/05/17 10:34:30 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="port number parsing"
+
+badport() {
+ port=$1
+ verbose "$tid: invalid port $port"
+ if ${SSH} -F $OBJ/ssh_proxy -p $port somehost true 2>/dev/null ; then
+ fail "$tid accepted invalid port $port"
+ fi
+}
+goodport() {
+ port=$1
+ verbose "$tid: valid port $port"
+ if ${SSH} -F $OBJ/ssh_proxy -p $port somehost true 2>/dev/null ; then
+ :
+ else
+ fail "$tid rejected valid port $port"
+ fi
+}
+
+badport 0
+badport 65536
+badport 131073
+badport 2000blah
+badport blah2000
+
+goodport 1
+goodport 22
+goodport 2222
+goodport 22222
+goodport 65535
+
diff --git a/regress/principals-command.sh b/regress/principals-command.sh
new file mode 100644
index 00000000..5e535c13
--- /dev/null
+++ b/regress/principals-command.sh
@@ -0,0 +1,174 @@
+# $OpenBSD: principals-command.sh,v 1.11 2019/12/16 02:39:05 djm Exp $
+# Placed in the Public Domain.
+
+tid="authorized principals command"
+
+rm -f $OBJ/user_ca_key* $OBJ/cert_user_key*
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+
+if [ -z "$SUDO" -a ! -w /var/run ]; then
+ echo "skipped (SUDO not set)"
+ echo "need SUDO to create file in /var/run, test won't work without"
+ exit 0
+fi
+
+case "$SSH_KEYTYPES" in
+ *ssh-rsa*) userkeytype=rsa ;;
+ *) userkeytype=ed25519 ;;
+esac
+
+SERIAL=$$
+
+# Create a CA key and a user certificate.
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key || \
+ fatal "ssh-keygen of user_ca_key failed"
+${SSHKEYGEN} -q -N '' -t ${userkeytype} -f $OBJ/cert_user_key || \
+ fatal "ssh-keygen of cert_user_key failed"
+${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "Joanne User" \
+ -z $$ -n ${USER},mekmitasdigoat $OBJ/cert_user_key || \
+ fatal "couldn't sign cert_user_key"
+
+CERT_BODY=`cat $OBJ/cert_user_key-cert.pub | awk '{ print $2 }'`
+CA_BODY=`cat $OBJ/user_ca_key.pub | awk '{ print $2 }'`
+CERT_FP=`${SSHKEYGEN} -lf $OBJ/cert_user_key-cert.pub | awk '{ print $2 }'`
+CA_FP=`${SSHKEYGEN} -lf $OBJ/user_ca_key.pub | awk '{ print $2 }'`
+
+# Establish a AuthorizedPrincipalsCommand in /var/run where it will have
+# acceptable directory permissions.
+PRINCIPALS_COMMAND="/var/run/principals_command_${LOGNAME}.$$"
+trap "$SUDO rm -f ${PRINCIPALS_COMMAND}" 0
+cat << _EOF | $SUDO sh -c "cat > '$PRINCIPALS_COMMAND'"
+#!/bin/sh
+test "x\$1" != "x${LOGNAME}" && exit 1
+test "x\$2" != "xssh-${userkeytype}-cert-v01@openssh.com" && exit 1
+test "x\$3" != "xssh-ed25519" && exit 1
+test "x\$4" != "xJoanne User" && exit 1
+test "x\$5" != "x${SERIAL}" && exit 1
+test "x\$6" != "x${CA_FP}" && exit 1
+test "x\$7" != "x${CERT_FP}" && exit 1
+test "x\$8" != "x${CERT_BODY}" && exit 1
+test "x\$9" != "x${CA_BODY}" && exit 1
+test -f "$OBJ/authorized_principals_${LOGNAME}" &&
+ exec cat "$OBJ/authorized_principals_${LOGNAME}"
+_EOF
+test $? -eq 0 || fatal "couldn't prepare principals command"
+$SUDO chmod 0755 "$PRINCIPALS_COMMAND"
+
+if ! $OBJ/check-perm -m keys-command $PRINCIPALS_COMMAND ; then
+ echo "skipping: $PRINCIPALS_COMMAND is unsuitable as " \
+ "AuthorizedPrincipalsCommand"
+ $SUDO rm -f $PRINCIPALS_COMMAND
+ exit 0
+fi
+
+if [ -x $PRINCIPALS_COMMAND ]; then
+ # Test explicitly-specified principals
+ for privsep in yes ; do
+ _prefix="privsep $privsep"
+
+ # Setup for AuthorizedPrincipalsCommand
+ rm -f $OBJ/authorized_keys_$USER
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo "UsePrivilegeSeparation $privsep"
+ echo "AuthorizedKeysFile none"
+ echo "AuthorizedPrincipalsCommand $PRINCIPALS_COMMAND" \
+ "%u %t %T %i %s %F %f %k %K"
+ echo "AuthorizedPrincipalsCommandUser ${LOGNAME}"
+ echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
+ ) > $OBJ/sshd_proxy
+
+ # XXX test missing command
+ # XXX test failing command
+
+ # Empty authorized_principals
+ verbose "$tid: ${_prefix} empty authorized_principals"
+ echo > $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+
+ # Wrong authorized_principals
+ verbose "$tid: ${_prefix} wrong authorized_principals"
+ echo gregorsamsa > $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+
+ # Correct authorized_principals
+ verbose "$tid: ${_prefix} correct authorized_principals"
+ echo mekmitasdigoat > $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ fail "ssh cert connect failed"
+ fi
+
+ # authorized_principals with bad key option
+ verbose "$tid: ${_prefix} authorized_principals bad key opt"
+ echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+
+ # authorized_principals with command=false
+ verbose "$tid: ${_prefix} authorized_principals command=false"
+ echo 'command="false" mekmitasdigoat' > \
+ $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+
+ # authorized_principals with command=true
+ verbose "$tid: ${_prefix} authorized_principals command=true"
+ echo 'command="true" mekmitasdigoat' > \
+ $OBJ/authorized_principals_$USER
+ ${SSH} -i $OBJ/cert_user_key \
+ -F $OBJ/ssh_proxy somehost false >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ fail "ssh cert connect failed"
+ fi
+
+ # Setup for principals= key option
+ rm -f $OBJ/authorized_principals_$USER
+ (
+ cat $OBJ/sshd_proxy_bak
+ echo "UsePrivilegeSeparation $privsep"
+ ) > $OBJ/sshd_proxy
+
+ # Wrong principals list
+ verbose "$tid: ${_prefix} wrong principals key option"
+ (
+ printf 'cert-authority,principals="gregorsamsa" '
+ cat $OBJ/user_ca_key.pub
+ ) > $OBJ/authorized_keys_$USER
+ ${SSH} -i $OBJ/cert_user_key \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "ssh cert connect succeeded unexpectedly"
+ fi
+
+ # Correct principals list
+ verbose "$tid: ${_prefix} correct principals key option"
+ (
+ printf 'cert-authority,principals="mekmitasdigoat" '
+ cat $OBJ/user_ca_key.pub
+ ) > $OBJ/authorized_keys_$USER
+ ${SSH} -i $OBJ/cert_user_key \
+ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ fail "ssh cert connect failed"
+ fi
+ done
+else
+ echo "SKIPPED: $PRINCIPALS_COMMAND not executable " \
+ "(/var/run mounted noexec?)"
+fi
diff --git a/regress/proto-mismatch.sh b/regress/proto-mismatch.sh
new file mode 100644
index 00000000..6ab28c9a
--- /dev/null
+++ b/regress/proto-mismatch.sh
@@ -0,0 +1,17 @@
+# $OpenBSD: proto-mismatch.sh,v 1.5 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="protocol version mismatch"
+
+mismatch ()
+{
+ client=$2
+ banner=`echo ${client} | ${SSHD} -i -f ${OBJ}/sshd_proxy`
+ r=$?
+ trace "sshd prints ${banner}"
+ if [ $r -ne 255 ]; then
+ fail "sshd prints ${banner} but accepts version ${client}"
+ fi
+}
+
+mismatch SSH-1.5-HALLO
diff --git a/regress/proto-version.sh b/regress/proto-version.sh
new file mode 100644
index 00000000..1f33b1f0
--- /dev/null
+++ b/regress/proto-version.sh
@@ -0,0 +1,30 @@
+# $OpenBSD: proto-version.sh,v 1.7 2017/06/07 01:48:15 djm Exp $
+# Placed in the Public Domain.
+
+tid="sshd version with different protocol combinations"
+
+# we just start sshd in inetd mode and check the banner
+check_version ()
+{
+ expect=$1
+ banner=`printf '' | ${SSHD} -i -f ${OBJ}/sshd_proxy`
+ case ${banner} in
+ SSH-1.99-*)
+ proto=199
+ ;;
+ SSH-2.0-*)
+ proto=20
+ ;;
+ SSH-1.5-*)
+ proto=15
+ ;;
+ *)
+ proto=0
+ ;;
+ esac
+ if [ ${expect} -ne ${proto} ]; then
+ fail "wrong protocol version ${banner}"
+ fi
+}
+
+check_version 20
diff --git a/regress/proxy-connect.sh b/regress/proxy-connect.sh
new file mode 100644
index 00000000..8847fe0c
--- /dev/null
+++ b/regress/proxy-connect.sh
@@ -0,0 +1,27 @@
+# $OpenBSD: proxy-connect.sh,v 1.12 2020/01/23 11:19:12 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="proxy connect"
+
+if [ "`${SSH} -Q compression`" = "none" ]; then
+ comp="no"
+else
+ comp="no yes"
+fi
+
+for c in $comp; do
+ verbose "plain username comp=$c"
+ opts="-oCompression=$c -F $OBJ/ssh_proxy"
+ SSH_CONNECTION=`${SSH} $opts 999.999.999.999 'echo $SSH_CONNECTION'`
+ if [ $? -ne 0 ]; then
+ fail "ssh proxyconnect comp=$c failed"
+ fi
+ if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then
+ fail "bad SSH_CONNECTION comp=$c: " \
+ "$SSH_CONNECTION"
+ fi
+done
+
+verbose "username with style"
+${SSH} -F $OBJ/ssh_proxy ${USER}:style@999.999.999.999 true || \
+ fail "ssh proxyconnect failed"
diff --git a/regress/putty-ciphers.sh b/regress/putty-ciphers.sh
new file mode 100644
index 00000000..708c288d
--- /dev/null
+++ b/regress/putty-ciphers.sh
@@ -0,0 +1,26 @@
+# $OpenBSD: putty-ciphers.sh,v 1.7 2020/01/23 03:35:07 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
+fi
+
+for c in aes 3des aes128-ctr aes192-ctr aes256-ctr chacha20 ; do
+ verbose "$tid: cipher $c"
+ cp ${OBJ}/.putty/sessions/localhost_proxy \
+ ${OBJ}/.putty/sessions/cipher_$c
+ echo "Cipher=$c" >> ${OBJ}/.putty/sessions/cipher_$c
+
+ rm -f ${COPY}
+ env HOME=$PWD ${PLINK} -load cipher_$c -batch -i ${OBJ}/putty.rsa2 \
+ cat ${DATA} > ${COPY}
+ if [ $? -ne 0 ]; then
+ fail "ssh cat $DATA failed"
+ fi
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
+done
+rm -f ${COPY}
+
diff --git a/regress/putty-kex.sh b/regress/putty-kex.sh
new file mode 100644
index 00000000..686d0e1a
--- /dev/null
+++ b/regress/putty-kex.sh
@@ -0,0 +1,22 @@
+# $OpenBSD: putty-kex.sh,v 1.5 2020/01/23 03:24:38 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
+fi
+
+for k in dh-gex-sha1 dh-group1-sha1 dh-group14-sha1 ecdh ; do
+ verbose "$tid: kex $k"
+ cp ${OBJ}/.putty/sessions/localhost_proxy \
+ ${OBJ}/.putty/sessions/kex_$k
+ echo "KEX=$k" >> ${OBJ}/.putty/sessions/kex_$k
+
+ env HOME=$PWD ${PLINK} -load kex_$k -batch -i ${OBJ}/putty.rsa2 true
+ if [ $? -ne 0 ]; then
+ fail "KEX $k failed"
+ fi
+done
+
diff --git a/regress/putty-transfer.sh b/regress/putty-transfer.sh
new file mode 100644
index 00000000..14b41022
--- /dev/null
+++ b/regress/putty-transfer.sh
@@ -0,0 +1,44 @@
+# $OpenBSD: putty-transfer.sh,v 1.7 2020/01/23 11:19:12 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
+fi
+
+if [ "`${SSH} -Q compression`" = "none" ]; then
+ comp="0"
+else
+ comp="0 1"
+fi
+
+for c in $comp; do
+ verbose "$tid: compression $c"
+ rm -f ${COPY}
+ cp ${OBJ}/.putty/sessions/localhost_proxy \
+ ${OBJ}/.putty/sessions/compression_$c
+ echo "Compression=$c" >> ${OBJ}/.putty/sessions/kex_$k
+ env HOME=$PWD ${PLINK} -load compression_$c -batch \
+ -i ${OBJ}/putty.rsa2 cat ${DATA} > ${COPY}
+ if [ $? -ne 0 ]; then
+ fail "ssh cat $DATA failed"
+ fi
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
+
+ for s in 10 100 1k 32k 64k 128k 256k; do
+ trace "compression $c dd-size ${s}"
+ rm -f ${COPY}
+ dd if=$DATA obs=${s} 2> /dev/null | \
+ env HOME=$PWD ${PLINK} -load compression_$c \
+ -batch -i ${OBJ}/putty.rsa2 \
+ "cat > ${COPY}"
+ if [ $? -ne 0 ]; then
+ fail "ssh cat $DATA failed"
+ fi
+ cmp $DATA ${COPY} || fail "corrupted copy"
+ done
+done
+rm -f ${COPY}
+
diff --git a/regress/reconfigure.sh b/regress/reconfigure.sh
new file mode 100644
index 00000000..dd15eddb
--- /dev/null
+++ b/regress/reconfigure.sh
@@ -0,0 +1,43 @@
+# $OpenBSD: reconfigure.sh,v 1.6 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="simple connect after reconfigure"
+
+# we need the full path to sshd for -HUP
+if test "x$USE_VALGRIND" = "x" ; then
+ case $SSHD in
+ /*)
+ # full path is OK
+ ;;
+ *)
+ # otherwise make fully qualified
+ SSHD=$OBJ/$SSHD
+ esac
+fi
+
+start_sshd
+
+trace "connect before restart"
+${SSH} -F $OBJ/ssh_config somehost true
+if [ $? -ne 0 ]; then
+ fail "ssh connect with failed before reconfigure"
+fi
+
+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"
+${SSH} -F $OBJ/ssh_config somehost true
+if [ $? -ne 0 ]; then
+ fail "ssh connect with failed after reconfigure"
+fi
diff --git a/regress/reexec.sh b/regress/reexec.sh
new file mode 100644
index 00000000..8966ba52
--- /dev/null
+++ b/regress/reexec.sh
@@ -0,0 +1,57 @@
+# $OpenBSD: reexec.sh,v 1.12 2017/08/07 03:52:55 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="reexec tests"
+
+SSHD_ORIG=$SSHD
+SSHD_COPY=$OBJ/sshd
+
+# Start a sshd and then delete it
+start_sshd_copy ()
+{
+ # NB. prefer ln to cp here. On some OSX 19.4 configurations,
+ # djm has seen failure after fork() when the executable image
+ # has been removed from the filesystem.
+ ln $SSHD_ORIG $SSHD_COPY || cp $SSHD_ORIG $SSHD_COPY
+ SSHD=$SSHD_COPY
+ start_sshd
+ SSHD=$SSHD_ORIG
+}
+
+# Do basic copy tests
+copy_tests ()
+{
+ rm -f ${COPY}
+ ${SSH} -nq -F $OBJ/ssh_config somehost \
+ cat ${DATA} > ${COPY}
+ if [ $? -ne 0 ]; then
+ fail "ssh cat $DATA failed"
+ fi
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
+ rm -f ${COPY}
+}
+
+verbose "test config passing"
+
+cp $OBJ/sshd_config $OBJ/sshd_config.orig
+start_sshd
+echo "InvalidXXX=no" >> $OBJ/sshd_config
+
+copy_tests
+
+stop_sshd
+
+cp $OBJ/sshd_config.orig $OBJ/sshd_config
+
+# cygwin can't fork a deleted binary
+if [ "$os" != "cygwin" ]; then
+
+verbose "test reexec fallback"
+
+start_sshd_copy
+rm -f $SSHD_COPY
+
+copy_tests
+
+stop_sshd
+fi
diff --git a/regress/rekey.sh b/regress/rekey.sh
new file mode 100644
index 00000000..fd6a02cc
--- /dev/null
+++ b/regress/rekey.sh
@@ -0,0 +1,172 @@
+# $OpenBSD: rekey.sh,v 1.18 2018/04/10 00:14:10 djm Exp $
+# Placed in the Public Domain.
+
+tid="rekey"
+
+LOG=${TEST_SSH_LOGFILE}
+
+rm -f ${LOG}
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+
+# Test rekeying based on data volume only.
+# Arguments will be passed to ssh.
+ssh_data_rekeying()
+{
+ _kexopt=$1 ; shift
+ _opts="$@"
+ if ! test -z "$_kexopts" ; then
+ cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+ echo "$_kexopt" >> $OBJ/sshd_proxy
+ _opts="$_opts -o$_kexopt"
+ fi
+ rm -f ${COPY} ${LOG}
+ _opts="$_opts -oCompression=no"
+ ${SSH} <${DATA} $_opts -v -F $OBJ/ssh_proxy somehost "cat > ${COPY}"
+ if [ $? -ne 0 ]; then
+ fail "ssh failed ($@)"
+ fi
+ cmp ${DATA} ${COPY} || fail "corrupted copy ($@)"
+ n=`grep 'NEWKEYS sent' ${LOG} | wc -l`
+ n=`expr $n - 1`
+ trace "$n rekeying(s)"
+ if [ $n -lt 1 ]; then
+ fail "no rekeying occurred ($@)"
+ fi
+}
+
+increase_datafile_size 300
+
+opts=""
+for i in `${SSH} -Q kex`; do
+ opts="$opts KexAlgorithms=$i"
+done
+for i in `${SSH} -Q cipher`; do
+ opts="$opts Ciphers=$i"
+done
+for i in `${SSH} -Q mac`; do
+ opts="$opts MACs=$i"
+done
+
+for opt in $opts; do
+ verbose "client rekey $opt"
+ ssh_data_rekeying "$opt" -oRekeyLimit=256k
+done
+
+# AEAD ciphers are magical so test with all KexAlgorithms
+if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then
+ for c in `${SSH} -Q cipher-auth`; do
+ for kex in `${SSH} -Q kex`; do
+ verbose "client rekey $c $kex"
+ ssh_data_rekeying "KexAlgorithms=$kex" -oRekeyLimit=256k -oCiphers=$c
+ done
+ done
+fi
+
+for s in 16 1k 128k 256k; do
+ verbose "client rekeylimit ${s}"
+ ssh_data_rekeying "" -oCompression=no -oRekeyLimit=$s
+done
+
+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"
+ if [ $? -ne 0 ]; then
+ fail "ssh failed"
+ fi
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
+ n=`grep 'NEWKEYS sent' ${LOG} | wc -l`
+ n=`expr $n - 1`
+ trace "$n rekeying(s)"
+ if [ $n -lt 1 ]; then
+ fail "no rekeying occurred"
+ fi
+done
+
+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"
+ if [ $? -ne 0 ]; then
+ fail "ssh failed"
+ fi
+ n=`grep 'NEWKEYS sent' ${LOG} | wc -l`
+ n=`expr $n - 1`
+ trace "$n rekeying(s)"
+ if [ $n -lt 1 ]; then
+ fail "no rekeying occurred"
+ fi
+done
+
+for s in 16 1k 128k 256k; do
+ verbose "server rekeylimit ${s}"
+ cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+ echo "rekeylimit ${s}" >>$OBJ/sshd_proxy
+ rm -f ${COPY} ${LOG}
+ ${SSH} -oCompression=no -F $OBJ/ssh_proxy somehost "cat ${DATA}" \
+ > ${COPY}
+ if [ $? -ne 0 ]; then
+ fail "ssh failed"
+ fi
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
+ n=`grep 'NEWKEYS sent' ${LOG} | wc -l`
+ n=`expr $n - 1`
+ trace "$n rekeying(s)"
+ if [ $n -lt 1 ]; then
+ fail "no rekeying occurred"
+ fi
+done
+
+for s in 5 10; do
+ verbose "server rekeylimit default ${s} no data"
+ 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"
+ if [ $? -ne 0 ]; then
+ fail "ssh failed"
+ fi
+ n=`grep 'NEWKEYS sent' ${LOG} | wc -l`
+ n=`expr $n - 1`
+ trace "$n rekeying(s)"
+ if [ $n -lt 1 ]; then
+ fail "no rekeying occurred"
+ fi
+done
+
+verbose "rekeylimit parsing"
+for size in 16 1k 1K 1m 1M 1g 1G 4G 8G; do
+ for time in 1 1m 1M 1h 1H 1d 1D 1w 1W; do
+ case $size in
+ 16) bytes=16 ;;
+ 1k|1K) bytes=1024 ;;
+ 1m|1M) bytes=1048576 ;;
+ 1g|1G) bytes=1073741824 ;;
+ 4g|4G) bytes=4294967296 ;;
+ 8g|8G) bytes=8589934592 ;;
+ esac
+ case $time in
+ 1) seconds=1 ;;
+ 1m|1M) seconds=60 ;;
+ 1h|1H) seconds=3600 ;;
+ 1d|1D) seconds=86400 ;;
+ 1w|1W) seconds=604800 ;;
+ esac
+
+ b=`$SUDO ${SSHD} -T -o "rekeylimit $size $time" -f $OBJ/sshd_proxy | \
+ awk '/rekeylimit/{print $2}'`
+ s=`$SUDO ${SSHD} -T -o "rekeylimit $size $time" -f $OBJ/sshd_proxy | \
+ awk '/rekeylimit/{print $3}'`
+
+ if [ "$bytes" != "$b" ]; then
+ fatal "rekeylimit size: expected $bytes bytes got $b"
+ fi
+ if [ "$seconds" != "$s" ]; then
+ fatal "rekeylimit time: expected $time seconds got $s"
+ fi
+ done
+done
+
+rm -f ${COPY} ${DATA}
diff --git a/regress/rsa_openssh.prv b/regress/rsa_openssh.prv
new file mode 100644
index 00000000..26755557
--- /dev/null
+++ b/regress/rsa_openssh.prv
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICWgIBAAKBgQDsilwKcaKN6wSMNd1WgQ9+HRqQEkD0kCTVttrazGu0OhBU3Uko
++dFD1Ip0CxdXmN25JQWxOYF7h/Ocu8P3jzv3RTX87xKR0YzlXTLX+SLtF/ySebS3
+xWPrlfRUDhh03hR5V+8xxvvy9widPYKw/oItwGSueOsEq1LTczCDv2dAjQIDAQAB
+An8nH5VzvHkMbSqJ6eOYDsVwomRvYbH5IEaYl1x6VATITNvAu9kUdQ4NsSpuMc+7
+Jj9gKZvmO1y2YCKc0P/iO+i/eV0L+yQh1Rw18jQZll+12T+LZrKRav03YNvMx0gN
+wqWY48Kt6hv2/N/ebQzKRe79+D0t2cTh92hT7xENFLIBAkEBGnoGKFjAUkJCwO1V
+mzpUqMHpRZVOrqP9hUmPjzNJ5oBPFGe4+h1hoSRFOAzaNuZt8ssbqaLCkzB8bfzj
+qhZqAQJBANZekuUpp8iBLeLSagw5FkcPwPzq6zfExbhvsZXb8Bo/4SflNs4JHXwI
+7SD9Z8aJLvM4uQ/5M70lblDMQ40i3o0CQQDIJvBYBFL5tlOgakq/O7yi+wt0L5BZ
+9H79w5rCSAA0IHRoK/qI1urHiHC3f3vbbLk5UStfrqEaND/mm0shyNIBAkBLsYdC
+/ctt5Bc0wUGK4Vl5bBmj9LtrrMJ4FpBpLwj/69BwCuKoK9XKZ0h73p6XHveCEGRg
+PIlFX4MtaoLrwgU9AkBV2k4dgIws+X8YX65EsyyFjnlDqX4x0nSOjQB1msIKfHBr
+dh5XLDBTTCxnKhMJ0Yx/opgOvf09XHBFwaQntR5i
+-----END RSA PRIVATE KEY-----
diff --git a/regress/rsa_openssh.pub b/regress/rsa_openssh.pub
new file mode 100644
index 00000000..b504730f
--- /dev/null
+++ b/regress/rsa_openssh.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDsilwKcaKN6wSMNd1WgQ9+HRqQEkD0kCTVttrazGu0OhBU3Uko+dFD1Ip0CxdXmN25JQWxOYF7h/Ocu8P3jzv3RTX87xKR0YzlXTLX+SLtF/ySebS3xWPrlfRUDhh03hR5V+8xxvvy9widPYKw/oItwGSueOsEq1LTczCDv2dAjQ==
diff --git a/regress/rsa_ssh2.prv b/regress/rsa_ssh2.prv
new file mode 100644
index 00000000..1ece3d7d
--- /dev/null
+++ b/regress/rsa_ssh2.prv
@@ -0,0 +1,16 @@
+---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----
+Subject: ssh-keygen test
+Comment: "1024-bit rsa, Sat Jun 23 2001 12:21:26 -0400"
+P2/56wAAAi4AAAA3aWYtbW9kbntzaWdue3JzYS1wa2NzMS1zaGExfSxlbmNyeXB0e3JzYS
+1wa2NzMXYyLW9hZXB9fQAAAARub25lAAAB3wAAAdsAAAARAQABAAAD9icflXO8eQxtKonp
+45gOxXCiZG9hsfkgRpiXXHpUBMhM28C72RR1Dg2xKm4xz7smP2Apm+Y7XLZgIpzQ/+I76L
+95XQv7JCHVHDXyNBmWX7XZP4tmspFq/Tdg28zHSA3CpZjjwq3qG/b8395tDMpF7v34PS3Z
+xOH3aFPvEQ0UsgEAAAQA7IpcCnGijesEjDXdVoEPfh0akBJA9JAk1bba2sxrtDoQVN1JKP
+nRQ9SKdAsXV5jduSUFsTmBe4fznLvD948790U1/O8SkdGM5V0y1/ki7Rf8knm0t8Vj65X0
+VA4YdN4UeVfvMcb78vcInT2CsP6CLcBkrnjrBKtS03Mwg79nQI0AAAH/VdpOHYCMLPl/GF
++uRLMshY55Q6l+MdJ0jo0AdZrCCnxwa3YeVywwU0wsZyoTCdGMf6KYDr39PVxwRcGkJ7Ue
+YgAAAgDWXpLlKafIgS3i0moMORZHD8D86us3xMW4b7GV2/AaP+En5TbOCR18CO0g/WfGiS
+7zOLkP+TO9JW5QzEONIt6NAAACAQEaegYoWMBSQkLA7VWbOlSowelFlU6uo/2FSY+PM0nm
+gE8UZ7j6HWGhJEU4DNo25m3yyxuposKTMHxt/OOqFmoB
+---- END SSH2 ENCRYPTED PRIVATE KEY ----
+---
diff --git a/regress/scp-ssh-wrapper.sh b/regress/scp-ssh-wrapper.sh
new file mode 100644
index 00000000..7fb21f42
--- /dev/null
+++ b/regress/scp-ssh-wrapper.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+# $OpenBSD: scp-ssh-wrapper.sh,v 1.4 2019/07/19 03:45:44 djm Exp $
+# Placed in the Public Domain.
+
+printname () {
+ NAME=$1
+ save_IFS=$IFS
+ IFS=/
+ set -- `echo "$NAME"`
+ IFS="$save_IFS"
+ while [ $# -ge 1 ] ; do
+ if [ "x$1" != "x" ]; then
+ echo "D0755 0 $1"
+ fi
+ shift;
+ done
+}
+
+# Discard all but last argument. We use arg later.
+while test "x$1" != "x"; do
+ arg="$1"
+ shift
+done
+
+BAD="../../../../../../../../../../../../../${DIR}/dotpathdir"
+
+case "$SCPTESTMODE" in
+badserver_0)
+ echo "D0755 0 /${DIR}/rootpathdir"
+ echo "C755 2 rootpathfile"
+ echo "X"
+ ;;
+badserver_1)
+ echo "D0755 0 $BAD"
+ echo "C755 2 file"
+ echo "X"
+ ;;
+badserver_2)
+ echo "D0755 0 $BAD"
+ echo "C755 2 file"
+ echo "X"
+ ;;
+badserver_3)
+ printname $BAD
+ echo "C755 2 file"
+ echo "X"
+ ;;
+badserver_4)
+ printname $BAD
+ echo "D0755 0 .."
+ echo "C755 2 file"
+ echo "X"
+ ;;
+badserver_5)
+ echo "D0555 0 "
+ echo "X"
+ ;;
+badserver_6)
+ echo "D0555 0 ."
+ echo "X"
+ ;;
+badserver_7)
+ echo "C0755 2 extrafile"
+ echo "X"
+ ;;
+*)
+ set -- $arg
+ shift
+ exec $SCP "$@"
+ ;;
+esac
diff --git a/regress/scp-uri.sh b/regress/scp-uri.sh
new file mode 100644
index 00000000..c03d8bbe
--- /dev/null
+++ b/regress/scp-uri.sh
@@ -0,0 +1,70 @@
+# $OpenBSD: scp-uri.sh,v 1.2 2017/12/11 11:41:56 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="scp-uri"
+
+#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
+scpopts="-q -S ${OBJ}/scp-ssh-wrapper.scp"
+export SCP # used in scp-ssh-wrapper.scp
+
+scpclean() {
+ rm -rf ${COPY} ${COPY2} ${DIR} ${DIR2}
+ mkdir ${DIR} ${DIR2}
+}
+
+# Remove Port and User from ssh_config, we want to rely on the URI
+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"
+
+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 "$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 "$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 "$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 "$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
+
+# TODO: scp -3
+
+scpclean
+rm -f ${OBJ}/scp-ssh-wrapper.exe
diff --git a/regress/scp.sh b/regress/scp.sh
new file mode 100644
index 00000000..62400efa
--- /dev/null
+++ b/regress/scp.sh
@@ -0,0 +1,136 @@
+# $OpenBSD: scp.sh,v 1.11 2019/07/19 03:45:44 djm Exp $
+# Placed in the Public Domain.
+
+tid="scp"
+
+#set -x
+
+# Figure out if diff understands "-N"
+if diff -N ${SRC}/scp.sh ${SRC}/scp.sh 2>/dev/null; then
+ DIFFOPT="-rN"
+else
+ DIFFOPT="-r"
+fi
+
+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
+scpopts="-q -S ${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}
+}
+
+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"
+
+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 "$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 "$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 "$tid: shell metacharacters"
+scpclean
+(cd ${DIR} && \
+touch '`touch metachartest`' && \
+$SCP $scpopts *metachar* ${DIR2} 2>/dev/null; \
+[ ! -f metachartest ] ) || fail "shell metacharacters"
+
+if [ ! -z "$SUDO" ]; then
+ verbose "$tid: 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 "$tid: 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 "$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/servcfginclude.sh b/regress/servcfginclude.sh
new file mode 100644
index 00000000..b25c8faa
--- /dev/null
+++ b/regress/servcfginclude.sh
@@ -0,0 +1,154 @@
+# Placed in the Public Domain.
+
+tid="server config include"
+
+cat > $OBJ/sshd_config.i << _EOF
+HostKey $OBJ/host.ssh-ed25519
+Match host a
+ Banner /aa
+
+Match host b
+ Banner /bb
+ Include $OBJ/sshd_config.i.*
+
+Match host c
+ Include $OBJ/sshd_config.i.*
+ Banner /cc
+
+Match host m
+ Include $OBJ/sshd_config.i.*
+
+Match Host d
+ Banner /dd
+
+Match Host e
+ Banner /ee
+ Include $OBJ/sshd_config.i.*
+
+Match Host f
+ Include $OBJ/sshd_config.i.*
+ Banner /ff
+
+Match Host n
+ Include $OBJ/sshd_config.i.*
+_EOF
+
+cat > $OBJ/sshd_config.i.0 << _EOF
+Match host xxxxxx
+_EOF
+
+cat > $OBJ/sshd_config.i.1 << _EOF
+Match host a
+ Banner /aaa
+
+Match host b
+ Banner /bbb
+
+Match host c
+ Banner /ccc
+
+Match Host d
+ Banner /ddd
+
+Match Host e
+ Banner /eee
+
+Match Host f
+ Banner /fff
+_EOF
+
+cat > $OBJ/sshd_config.i.2 << _EOF
+Match host a
+ Banner /aaaa
+
+Match host b
+ Banner /bbbb
+
+Match host c
+ Banner /cccc
+
+Match Host d
+ Banner /dddd
+
+Match Host e
+ Banner /eeee
+
+Match Host f
+ Banner /ffff
+
+Match all
+ Banner /xxxx
+_EOF
+
+trial() {
+ _host="$1"
+ _exp="$2"
+ _desc="$3"
+ test -z "$_desc" && _desc="test match"
+ trace "$_desc host=$_host expect=$_exp"
+ ${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i -T \
+ -C "host=$_host,user=test,addr=127.0.0.1" > $OBJ/sshd_config.out ||
+ fatal "ssh config parse failed: $_desc host=$_host expect=$_exp"
+ _got=`grep -i '^banner ' $OBJ/sshd_config.out | awk '{print $2}'`
+ if test "x$_exp" != "x$_got" ; then
+ fail "$desc_ host $_host include fail: expected $_exp got $_got"
+ fi
+}
+
+trial a /aa
+trial b /bb
+trial c /ccc
+trial d /dd
+trial e /ee
+trial f /fff
+trial m /xxxx
+trial n /xxxx
+trial x none
+
+# Prepare an included config with an error.
+
+cat > $OBJ/sshd_config.i.3 << _EOF
+Banner xxxx
+ Junk
+_EOF
+
+trace "disallow invalid config host=a"
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i \
+ -C "host=a,user=test,addr=127.0.0.1" 2>/dev/null && \
+ fail "sshd include allowed invalid config"
+
+trace "disallow invalid config host=x"
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i \
+ -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \
+ fail "sshd include allowed invalid config"
+
+rm -f $OBJ/sshd_config.i.*
+
+# Ensure that a missing include is not fatal.
+cat > $OBJ/sshd_config.i << _EOF
+HostKey $OBJ/host.ssh-ed25519
+Include $OBJ/sshd_config.i.*
+Banner /aa
+_EOF
+
+trial a /aa "missing include non-fatal"
+
+# Ensure that Match/Host in an included config does not affect parent.
+cat > $OBJ/sshd_config.i.x << _EOF
+Match host x
+_EOF
+
+trial a /aa "included file does not affect match state"
+
+# Ensure the empty include directive is not accepted
+cat > $OBJ/sshd_config.i.x << _EOF
+Include
+_EOF
+
+trace "disallow invalid with no argument"
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i.x \
+ -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \
+ fail "sshd allowed Include with no argument"
+
+# cleanup
+rm -f $OBJ/sshd_config.i $OBJ/sshd_config.i.* $OBJ/sshd_config.out
diff --git a/roaming_dummy.c b/regress/setuid-allowed.c
index 837de695..d91d9f19 100644
--- a/roaming_dummy.c
+++ b/regress/setuid-allowed.c
@@ -1,6 +1,5 @@
-/* $OpenBSD: roaming_dummy.c,v 1.4 2015/01/19 19:52:16 markus Exp $ */
/*
- * Copyright (c) 2004-2009 AppGate Network Security AB
+ * Copyright (c) 2013 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
@@ -15,58 +14,45 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/*
- * This file is included in the client programs which should not
- * support roaming.
- */
+/* $OpenBSD$ */
#include "includes.h"
#include <sys/types.h>
-#include <unistd.h>
-
-#include "roaming.h"
-
-int resume_in_progress = 0;
-
-u_int64_t
-get_recv_bytes(void)
-{
- return 0;
-}
-
-u_int64_t
-get_sent_bytes(void)
-{
- return 0;
-}
-
-void
-roam_set_bytes(u_int64_t sent, u_int64_t recvd)
+#ifdef HAVE_SYS_STATVFS_H
+# include <sys/statvfs.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+static void
+usage(void)
{
+ fprintf(stderr, "check-setuid [path]\n");
+ exit(1);
}
-ssize_t
-roaming_write(int fd, const void *buf, size_t count, int *cont)
-{
- return write(fd, buf, count);
-}
-
-ssize_t
-roaming_read(int fd, void *buf, size_t count, int *cont)
+int
+main(int argc, char **argv)
{
- if (cont)
- *cont = 0;
- return read(fd, buf, count);
+ const char *path = ".";
+ struct statvfs sb;
+
+ if (argc > 2)
+ usage();
+ else if (argc == 2)
+ path = argv[1];
+
+ if (statvfs(path, &sb) != 0) {
+ /* Don't return an error if the host doesn't support statvfs */
+ if (errno == ENOSYS)
+ return 0;
+ fprintf(stderr, "statvfs for \"%s\" failed: %s\n",
+ path, strerror(errno));
+ }
+ return (sb.f_flag & ST_NOSUID) ? 1 : 0;
}
-void
-add_recv_bytes(u_int64_t num)
-{
-}
-int
-resume_kex(void)
-{
- return 1;
-}
diff --git a/regress/sftp-badcmds.sh b/regress/sftp-badcmds.sh
new file mode 100644
index 00000000..5b016d55
--- /dev/null
+++ b/regress/sftp-badcmds.sh
@@ -0,0 +1,65 @@
+# $OpenBSD: sftp-badcmds.sh,v 1.7 2020/03/13 03:18:45 djm Exp $
+# Placed in the Public Domain.
+
+tid="sftp invalid commands"
+
+DATA2=/bin/sh${EXEEXT}
+NONEXIST=/NONEXIST.$$
+GLOBFILES=`(cd /bin;echo l*)`
+
+rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd
+
+rm -f ${COPY}
+verbose "$tid: get nonexistent"
+echo "get $NONEXIST $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "get nonexistent failed"
+test -f ${COPY} && fail "existing copy after get nonexistent"
+
+rm -f ${COPY}.dd/*
+verbose "$tid: glob get to nonexistent directory"
+echo "get /bin/l* $NONEXIST" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "get nonexistent failed"
+for x in $GLOBFILES; do
+ test -f ${COPY}.dd/$x && fail "existing copy after get nonexistent"
+done
+
+rm -f ${COPY}
+verbose "$tid: put nonexistent"
+echo "put $NONEXIST $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "put nonexistent failed"
+test -f ${COPY} && fail "existing copy after put nonexistent"
+
+rm -f ${COPY}.dd/*
+verbose "$tid: glob put to nonexistent directory"
+echo "put /bin/l* ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "put nonexistent failed"
+for x in $GLOBFILES; do
+ test -f ${COPY}.dd/$x && fail "existing copy after nonexistent"
+done
+
+rm -f ${COPY}
+verbose "$tid: rename nonexistent"
+echo "rename $NONEXIST ${COPY}.1" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "rename nonexist failed"
+test -f ${COPY}.1 && fail "file exists after rename nonexistent"
+
+rm -rf ${COPY} ${COPY}.dd
+cp $DATA $COPY
+mkdir ${COPY}.dd
+verbose "$tid: rename target exists (directory)"
+echo "rename $COPY ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "rename target exists (directory) failed"
+test -f ${COPY} || fail "oldname missing after rename target exists (directory)"
+test -d ${COPY}.dd || fail "newname missing after rename target exists (directory)"
+cmp $DATA ${COPY} >/dev/null 2>&1 || fail "corrupted oldname after rename target exists (directory)"
+
+rm -f ${COPY}.dd/*
+rm -rf ${COPY}
+cp ${DATA2} ${COPY}
+verbose "$tid: glob put files to local file"
+echo "put /bin/l* $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1
+cmp ${DATA2} ${COPY} || fail "put succeeded when it should have failed"
+
+rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd
+
+
diff --git a/regress/sftp-batch.sh b/regress/sftp-batch.sh
new file mode 100644
index 00000000..41011549
--- /dev/null
+++ b/regress/sftp-batch.sh
@@ -0,0 +1,55 @@
+# $OpenBSD: sftp-batch.sh,v 1.5 2013/05/17 04:29:14 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="sftp batchfile"
+
+BATCH=${OBJ}/sftp.bb
+
+rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${BATCH}.*
+
+cat << EOF > ${BATCH}.pass.1
+ get $DATA $COPY
+ put ${COPY} ${COPY}.1
+ rm ${COPY}
+ -put ${COPY} ${COPY}.2
+EOF
+
+cat << EOF > ${BATCH}.pass.2
+ # This is a comment
+
+ # That was a blank line
+ ls
+EOF
+
+cat << EOF > ${BATCH}.fail.1
+ get $DATA $COPY
+ put ${COPY} ${COPY}.3
+ rm ${COPY}.*
+ # The next command should fail
+ put ${COPY}.3 ${COPY}.4
+EOF
+
+cat << EOF > ${BATCH}.fail.2
+ # The next command should fail
+ jajajajaja
+EOF
+
+verbose "$tid: good commands"
+${SFTP} -b ${BATCH}.pass.1 -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "good commands failed"
+
+verbose "$tid: bad commands"
+${SFTP} -b ${BATCH}.fail.1 -D ${SFTPSERVER} >/dev/null 2>&1 \
+ && fail "bad commands succeeded"
+
+verbose "$tid: comments and blanks"
+${SFTP} -b ${BATCH}.pass.2 -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "comments & blanks failed"
+
+verbose "$tid: junk command"
+${SFTP} -b ${BATCH}.fail.2 -D ${SFTPSERVER} >/dev/null 2>&1 \
+ && fail "junk command succeeded"
+
+rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${BATCH}.*
+
+
diff --git a/regress/sftp-chroot.sh b/regress/sftp-chroot.sh
new file mode 100644
index 00000000..5acc4d2d
--- /dev/null
+++ b/regress/sftp-chroot.sh
@@ -0,0 +1,31 @@
+# $OpenBSD: sftp-chroot.sh,v 1.7 2018/11/22 08:48:32 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="sftp in chroot"
+
+CHROOT=/var/run
+FILENAME=testdata_${USER}.$$
+PRIVDATA=${CHROOT}/${FILENAME}
+trap "${SUDO} rm -f ${PRIVDATA}" 0
+
+if [ -z "$SUDO" -a ! -w /var/run ]; then
+ echo "need SUDO to create file in /var/run, test won't work without"
+ echo SKIPPED
+ exit 0
+fi
+
+if ! $OBJ/check-perm -m chroot "$CHROOT" ; then
+ echo "skipped: $CHROOT is unsuitable as ChrootDirectory"
+ exit 0
+fi
+
+$SUDO sh -c "echo mekmitastdigoat > $PRIVDATA" || \
+ fatal "create $PRIVDATA failed"
+
+start_sshd -oChrootDirectory=$CHROOT -oForceCommand="internal-sftp -d /"
+
+verbose "test $tid: get"
+${SFTP} -S "$SSH" -F $OBJ/ssh_config host:/${FILENAME} $COPY \
+ >>$TEST_REGRESS_LOGFILE 2>&1 || \
+ fatal "Fetch ${FILENAME} failed"
+cmp $PRIVDATA $COPY || fail "$PRIVDATA $COPY differ"
diff --git a/regress/sftp-cmds.sh b/regress/sftp-cmds.sh
new file mode 100644
index 00000000..1289c408
--- /dev/null
+++ b/regress/sftp-cmds.sh
@@ -0,0 +1,228 @@
+# $OpenBSD: sftp-cmds.sh,v 1.14 2013/06/21 02:26:26 djm Exp $
+# Placed in the Public Domain.
+
+# XXX - TODO:
+# - chmod / chown / chgrp
+# - -p flag for get & put
+
+tid="sftp commands"
+
+# test that these files are readable!
+for i in `(cd /bin;echo l*)`
+do
+ if [ -r $i ]; then
+ GLOBFILES="$GLOBFILES $i"
+ fi
+done
+
+# Path with embedded quote
+QUOTECOPY=${COPY}".\"blah\""
+QUOTECOPY_ARG=${COPY}'.\"blah\"'
+# File with spaces
+SPACECOPY="${COPY} this has spaces.txt"
+SPACECOPY_ARG="${COPY}\ this\ has\ spaces.txt"
+# File with glob metacharacters
+GLOBMETACOPY="${COPY} [metachar].txt"
+
+rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${COPY}.dd2
+mkdir ${COPY}.dd
+
+verbose "$tid: lls"
+(echo "lcd ${OBJ}" ; echo "lls") | ${SFTP} -D ${SFTPSERVER} 2>&1 | \
+ grep copy.dd >/dev/null 2>&1 || fail "lls failed"
+
+verbose "$tid: lls w/path"
+echo "lls ${OBJ}" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \
+ grep copy.dd >/dev/null 2>&1 || fail "lls w/path failed"
+
+verbose "$tid: ls"
+echo "ls ${OBJ}" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "ls failed"
+# XXX always successful
+
+verbose "$tid: shell"
+echo "!echo hi there" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "shell failed"
+# XXX always successful
+
+verbose "$tid: pwd"
+echo "pwd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "pwd failed"
+# XXX always successful
+
+verbose "$tid: lpwd"
+echo "lpwd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "lpwd failed"
+# XXX always successful
+
+verbose "$tid: quit"
+echo "quit" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "quit failed"
+# XXX always successful
+
+verbose "$tid: help"
+echo "help" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "help failed"
+# XXX always successful
+
+rm -f ${COPY}
+verbose "$tid: get"
+echo "get $DATA $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "get failed"
+cmp $DATA ${COPY} || fail "corrupted copy after get"
+
+rm -f ${COPY}
+verbose "$tid: get quoted"
+echo "get \"$DATA\" $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "get failed"
+cmp $DATA ${COPY} || fail "corrupted copy after get"
+
+rm -f ${QUOTECOPY}
+cp $DATA ${QUOTECOPY}
+verbose "$tid: get filename with quotes"
+echo "get \"$QUOTECOPY_ARG\" ${COPY}" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "get failed"
+cmp ${COPY} ${QUOTECOPY} || fail "corrupted copy after get with quotes"
+rm -f ${QUOTECOPY} ${COPY}
+
+rm -f "$SPACECOPY" ${COPY}
+cp $DATA "$SPACECOPY"
+verbose "$tid: get filename with spaces"
+echo "get ${SPACECOPY_ARG} ${COPY}" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "get failed"
+cmp ${COPY} "$SPACECOPY" || fail "corrupted copy after get with spaces"
+
+rm -f "$GLOBMETACOPY" ${COPY}
+cp $DATA "$GLOBMETACOPY"
+verbose "$tid: get filename with glob metacharacters"
+echo "get \"${GLOBMETACOPY}\" ${COPY}" | \
+ ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "get failed"
+cmp ${COPY} "$GLOBMETACOPY" || \
+ fail "corrupted copy after get with glob metacharacters"
+
+rm -f ${COPY}.dd/*
+verbose "$tid: get to directory"
+echo "get $DATA ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "get failed"
+cmp $DATA ${COPY}.dd/$DATANAME || fail "corrupted copy after get"
+
+rm -f ${COPY}.dd/*
+verbose "$tid: glob get to directory"
+echo "get /bin/l* ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "get failed"
+for x in $GLOBFILES; do
+ cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after get"
+done
+
+rm -f ${COPY}.dd/*
+verbose "$tid: get to local dir"
+(echo "lcd ${COPY}.dd"; echo "get $DATA" ) | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "get failed"
+cmp $DATA ${COPY}.dd/$DATANAME || fail "corrupted copy after get"
+
+rm -f ${COPY}.dd/*
+verbose "$tid: glob get to local dir"
+(echo "lcd ${COPY}.dd"; echo "get /bin/l*") | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "get failed"
+for x in $GLOBFILES; do
+ cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after get"
+done
+
+rm -f ${COPY}
+verbose "$tid: put"
+echo "put $DATA $COPY" | \
+ ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
+cmp $DATA ${COPY} || fail "corrupted copy after put"
+
+rm -f ${QUOTECOPY}
+verbose "$tid: put filename with quotes"
+echo "put $DATA \"$QUOTECOPY_ARG\"" | \
+ ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
+cmp $DATA ${QUOTECOPY} || fail "corrupted copy after put with quotes"
+
+rm -f "$SPACECOPY"
+verbose "$tid: put filename with spaces"
+echo "put $DATA ${SPACECOPY_ARG}" | \
+ ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
+cmp $DATA "$SPACECOPY" || fail "corrupted copy after put with spaces"
+
+rm -f ${COPY}.dd/*
+verbose "$tid: put to directory"
+echo "put $DATA ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "put failed"
+cmp $DATA ${COPY}.dd/$DATANAME || fail "corrupted copy after put"
+
+rm -f ${COPY}.dd/*
+verbose "$tid: glob put to directory"
+echo "put /bin/l? ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "put failed"
+for x in $GLOBFILES; do
+ cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after put"
+done
+
+rm -f ${COPY}.dd/*
+verbose "$tid: put to local dir"
+(echo "cd ${COPY}.dd"; echo "put $DATA") | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "put failed"
+cmp $DATA ${COPY}.dd/$DATANAME || fail "corrupted copy after put"
+
+rm -f ${COPY}.dd/*
+verbose "$tid: glob put to local dir"
+(echo "cd ${COPY}.dd"; echo "put /bin/l?") | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "put failed"
+for x in $GLOBFILES; do
+ cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after put"
+done
+
+verbose "$tid: rename"
+echo "rename $COPY ${COPY}.1" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "rename failed"
+test -f ${COPY}.1 || fail "missing file after rename"
+cmp $DATA ${COPY}.1 >/dev/null 2>&1 || fail "corrupted copy after rename"
+
+verbose "$tid: rename directory"
+echo "rename ${COPY}.dd ${COPY}.dd2" | \
+ ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || \
+ fail "rename directory failed"
+test -d ${COPY}.dd && fail "oldname exists after rename directory"
+test -d ${COPY}.dd2 || fail "missing newname after rename directory"
+
+verbose "$tid: ln"
+echo "ln ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "ln failed"
+test -f ${COPY}.2 || fail "missing file after ln"
+cmp ${COPY}.1 ${COPY}.2 || fail "created file is not equal after ln"
+
+verbose "$tid: ln -s"
+rm -f ${COPY}.2
+echo "ln -s ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "ln -s failed"
+test -h ${COPY}.2 || fail "missing file after ln -s"
+
+verbose "$tid: mkdir"
+echo "mkdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "mkdir failed"
+test -d ${COPY}.dd || fail "missing directory after mkdir"
+
+# XXX do more here
+verbose "$tid: chdir"
+echo "chdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "chdir failed"
+
+verbose "$tid: rmdir"
+echo "rmdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "rmdir failed"
+test -d ${COPY}.1 && fail "present directory after rmdir"
+
+verbose "$tid: lmkdir"
+echo "lmkdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "lmkdir failed"
+test -d ${COPY}.dd || fail "missing directory after lmkdir"
+
+# XXX do more here
+verbose "$tid: lchdir"
+echo "lchdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
+ || fail "lchdir failed"
+
+rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${COPY}.dd2
+rm -rf ${QUOTECOPY} "$SPACECOPY" "$GLOBMETACOPY"
+
+
diff --git a/regress/sftp-glob.sh b/regress/sftp-glob.sh
new file mode 100644
index 00000000..8d4df2c9
--- /dev/null
+++ b/regress/sftp-glob.sh
@@ -0,0 +1,75 @@
+# $OpenBSD: sftp-glob.sh,v 1.4 2009/08/13 01:11:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="sftp glob"
+
+config_defined FILESYSTEM_NO_BACKSLASH && nobs="not supported on this platform"
+
+sftp_ls() {
+ target=$1
+ errtag=$2
+ expected=$3
+ unexpected=$4
+ skip=$5
+ if test "x$skip" != "x" ; then
+ verbose "$tid: $errtag (skipped: $skip)"
+ return
+ fi
+ verbose "$tid: $errtag"
+ printf "ls -l %s" "${target}" | \
+ ${SFTP} -b - -D ${SFTPSERVER} 2>/dev/null | \
+ grep -v "^sftp>" > ${RESULTS}
+ if [ $? -ne 0 ]; then
+ fail "$errtag failed"
+ fi
+ if test "x$expected" != "x" ; then
+ if fgrep "$expected" ${RESULTS} >/dev/null 2>&1 ; then
+ :
+ else
+ fail "$expected missing from $errtag results"
+ fi
+ fi
+ if test "x$unexpected" != "x" && \
+ fgrep "$unexpected" ${RESULTS} >/dev/null 2>&1 ; then
+ fail "$unexpected present in $errtag results"
+ fi
+ rm -f ${RESULTS}
+}
+
+BASE=${OBJ}/glob
+RESULTS=${OBJ}/results
+DIR=${BASE}/dir
+DATA=${DIR}/file
+
+GLOB1="${DIR}/g-wild*"
+GLOB2="${DIR}/g-wildx"
+QUOTE="${DIR}/g-quote\""
+SLASH="${DIR}/g-sl\\ash"
+ESLASH="${DIR}/g-slash\\"
+QSLASH="${DIR}/g-qs\\\""
+SPACE="${DIR}/g-q space"
+
+rm -rf ${BASE}
+mkdir -p ${DIR}
+touch "${DATA}" "${GLOB1}" "${GLOB2}" "${QUOTE}" "${SPACE}"
+test "x$nobs" = "x" && touch "${QSLASH}" "${ESLASH}" "${SLASH}"
+
+# target message expected unexpected
+sftp_ls "${DIR}/fil*" "file glob" "${DATA}" ""
+sftp_ls "${BASE}/d*" "dir glob" "`basename ${DATA}`" ""
+sftp_ls "${DIR}/g-wild\"*\"" "quoted glob" "g-wild*" "g-wildx"
+sftp_ls "${DIR}/g-wild\*" "escaped glob" "g-wild*" "g-wildx"
+sftp_ls "${DIR}/g-quote\\\"" "escaped quote" "g-quote\"" ""
+sftp_ls "\"${DIR}/g-quote\\\"\"" "quoted quote" "g-quote\"" ""
+sftp_ls "'${DIR}/g-quote\"'" "single-quoted quote" "g-quote\"" ""
+sftp_ls "${DIR}/g-q\\ space" "escaped space" "g-q space" ""
+sftp_ls "'${DIR}/g-q space'" "quoted space" "g-q space" ""
+sftp_ls "${DIR}/g-sl\\\\ash" "escaped slash" "g-sl\\ash" "" "$nobs"
+sftp_ls "'${DIR}/g-sl\\\\ash'" "quoted slash" "g-sl\\ash" "" "$nobs"
+sftp_ls "${DIR}/g-slash\\\\" "escaped slash at EOL" "g-slash\\" "" "$nobs"
+sftp_ls "'${DIR}/g-slash\\\\'" "quoted slash at EOL" "g-slash\\" "" "$nobs"
+sftp_ls "${DIR}/g-qs\\\\\\\"" "escaped slash+quote" "g-qs\\\"" "" "$nobs"
+sftp_ls "'${DIR}/g-qs\\\\\"'" "quoted slash+quote" "g-qs\\\"" "" "$nobs"
+
+rm -rf ${BASE}
+
diff --git a/regress/sftp-perm.sh b/regress/sftp-perm.sh
new file mode 100644
index 00000000..304ca0ac
--- /dev/null
+++ b/regress/sftp-perm.sh
@@ -0,0 +1,269 @@
+# $OpenBSD: sftp-perm.sh,v 1.2 2013/10/17 22:00:18 djm Exp $
+# Placed in the Public Domain.
+
+tid="sftp permissions"
+
+SERVER_LOG=${OBJ}/sftp-server.log
+CLIENT_LOG=${OBJ}/sftp.log
+TEST_SFTP_SERVER=${OBJ}/sftp-server.sh
+
+prepare_server() {
+ printf "#!/bin/sh\nexec $SFTPSERVER -el debug3 $* 2>$SERVER_LOG\n" \
+ > $TEST_SFTP_SERVER
+ chmod a+x $TEST_SFTP_SERVER
+}
+
+run_client() {
+ echo "$@" | ${SFTP} -D ${TEST_SFTP_SERVER} -vvvb - >$CLIENT_LOG 2>&1
+}
+
+prepare_files() {
+ _prep="$1"
+ rm -f ${COPY} ${COPY}.1
+ test -d ${COPY}.dd && { rmdir ${COPY}.dd || fatal "rmdir ${COPY}.dd"; }
+ test -z "$_prep" && return
+ sh -c "$_prep" || fail "preparation failed: \"$_prep\""
+}
+
+postcondition() {
+ _title="$1"
+ _check="$2"
+ test -z "$_check" && return
+ ${TEST_SHELL} -c "$_check" || fail "postcondition check failed: $_title"
+}
+
+ro_test() {
+ _desc=$1
+ _cmd="$2"
+ _prep="$3"
+ _expect_success_post="$4"
+ _expect_fail_post="$5"
+ verbose "$tid: read-only $_desc"
+ # Plain (no options, mostly to test that _cmd is good)
+ prepare_files "$_prep"
+ prepare_server
+ run_client "$_cmd" || fail "plain $_desc failed"
+ postcondition "$_desc no-readonly" "$_expect_success_post"
+ # Read-only enabled
+ prepare_files "$_prep"
+ prepare_server -R
+ run_client "$_cmd" && fail "read-only $_desc succeeded"
+ postcondition "$_desc readonly" "$_expect_fail_post"
+}
+
+perm_test() {
+ _op=$1
+ _whitelist_ops=$2
+ _cmd="$3"
+ _prep="$4"
+ _expect_success_post="$5"
+ _expect_fail_post="$6"
+ verbose "$tid: explicit $_op"
+ # Plain (no options, mostly to test that _cmd is good)
+ prepare_files "$_prep"
+ prepare_server
+ run_client "$_cmd" || fail "plain $_op failed"
+ postcondition "$_op no white/blacklists" "$_expect_success_post"
+ # Whitelist
+ prepare_files "$_prep"
+ prepare_server -p $_op,$_whitelist_ops
+ run_client "$_cmd" || fail "whitelisted $_op failed"
+ postcondition "$_op whitelisted" "$_expect_success_post"
+ # Blacklist
+ prepare_files "$_prep"
+ prepare_server -P $_op
+ run_client "$_cmd" && fail "blacklisted $_op succeeded"
+ postcondition "$_op blacklisted" "$_expect_fail_post"
+ # Whitelist with op missing.
+ prepare_files "$_prep"
+ prepare_server -p $_whitelist_ops
+ run_client "$_cmd" && fail "no whitelist $_op succeeded"
+ postcondition "$_op not in whitelist" "$_expect_fail_post"
+}
+
+ro_test \
+ "upload" \
+ "put $DATA $COPY" \
+ "" \
+ "cmp $DATA $COPY" \
+ "test ! -f $COPY"
+
+ro_test \
+ "setstat" \
+ "chmod 0700 $COPY" \
+ "touch $COPY; chmod 0400 $COPY" \
+ "test -x $COPY" \
+ "test ! -x $COPY"
+
+ro_test \
+ "rm" \
+ "rm $COPY" \
+ "touch $COPY" \
+ "test ! -f $COPY" \
+ "test -f $COPY"
+
+ro_test \
+ "mkdir" \
+ "mkdir ${COPY}.dd" \
+ "" \
+ "test -d ${COPY}.dd" \
+ "test ! -d ${COPY}.dd"
+
+ro_test \
+ "rmdir" \
+ "rmdir ${COPY}.dd" \
+ "mkdir ${COPY}.dd" \
+ "test ! -d ${COPY}.dd" \
+ "test -d ${COPY}.dd"
+
+ro_test \
+ "posix-rename" \
+ "rename $COPY ${COPY}.1" \
+ "touch $COPY" \
+ "test -f ${COPY}.1 -a ! -f $COPY" \
+ "test -f $COPY -a ! -f ${COPY}.1"
+
+ro_test \
+ "oldrename" \
+ "rename -l $COPY ${COPY}.1" \
+ "touch $COPY" \
+ "test -f ${COPY}.1 -a ! -f $COPY" \
+ "test -f $COPY -a ! -f ${COPY}.1"
+
+ro_test \
+ "symlink" \
+ "ln -s $COPY ${COPY}.1" \
+ "touch $COPY" \
+ "test -h ${COPY}.1" \
+ "test ! -h ${COPY}.1"
+
+ro_test \
+ "hardlink" \
+ "ln $COPY ${COPY}.1" \
+ "touch $COPY" \
+ "test -f ${COPY}.1" \
+ "test ! -f ${COPY}.1"
+
+# Test explicit permissions
+
+perm_test \
+ "open" \
+ "realpath,stat,lstat,read,close" \
+ "get $DATA $COPY" \
+ "" \
+ "cmp $DATA $COPY" \
+ "! cmp $DATA $COPY 2>/dev/null"
+
+perm_test \
+ "read" \
+ "realpath,stat,lstat,open,close" \
+ "get $DATA $COPY" \
+ "" \
+ "cmp $DATA $COPY" \
+ "! cmp $DATA $COPY 2>/dev/null"
+
+perm_test \
+ "write" \
+ "realpath,stat,lstat,open,close" \
+ "put $DATA $COPY" \
+ "" \
+ "cmp $DATA $COPY" \
+ "! cmp $DATA $COPY 2>/dev/null"
+
+perm_test \
+ "lstat" \
+ "realpath,stat,open,read,close" \
+ "get $DATA $COPY" \
+ "" \
+ "cmp $DATA $COPY" \
+ "! cmp $DATA $COPY 2>/dev/null"
+
+perm_test \
+ "opendir" \
+ "realpath,readdir,stat,lstat" \
+ "ls -ln $OBJ"
+
+perm_test \
+ "readdir" \
+ "realpath,opendir,stat,lstat" \
+ "ls -ln $OBJ"
+
+perm_test \
+ "setstat" \
+ "realpath,stat,lstat" \
+ "chmod 0700 $COPY" \
+ "touch $COPY; chmod 0400 $COPY" \
+ "test -x $COPY" \
+ "test ! -x $COPY"
+
+perm_test \
+ "remove" \
+ "realpath,stat,lstat" \
+ "rm $COPY" \
+ "touch $COPY" \
+ "test ! -f $COPY" \
+ "test -f $COPY"
+
+perm_test \
+ "mkdir" \
+ "realpath,stat,lstat" \
+ "mkdir ${COPY}.dd" \
+ "" \
+ "test -d ${COPY}.dd" \
+ "test ! -d ${COPY}.dd"
+
+perm_test \
+ "rmdir" \
+ "realpath,stat,lstat" \
+ "rmdir ${COPY}.dd" \
+ "mkdir ${COPY}.dd" \
+ "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"
+
+perm_test \
+ "rename" \
+ "realpath,stat,lstat" \
+ "rename -l $COPY ${COPY}.1" \
+ "touch $COPY" \
+ "test -f ${COPY}.1 -a ! -f $COPY" \
+ "test -f $COPY -a ! -f ${COPY}.1"
+
+perm_test \
+ "symlink" \
+ "realpath,stat,lstat" \
+ "ln -s $COPY ${COPY}.1" \
+ "touch $COPY" \
+ "test -h ${COPY}.1" \
+ "test ! -h ${COPY}.1"
+
+perm_test \
+ "hardlink" \
+ "realpath,stat,lstat" \
+ "ln $COPY ${COPY}.1" \
+ "touch $COPY" \
+ "test -f ${COPY}.1" \
+ "test ! -f ${COPY}.1"
+
+perm_test \
+ "statvfs" \
+ "realpath,stat,lstat" \
+ "df /"
+
+# XXX need good tests for:
+# fstat
+# fsetstat
+# realpath
+# stat
+# readlink
+# fstatvfs
+
+rm -rf ${COPY} ${COPY}.1 ${COPY}.dd
+
diff --git a/regress/sftp-uri.sh b/regress/sftp-uri.sh
new file mode 100644
index 00000000..7be104df
--- /dev/null
+++ b/regress/sftp-uri.sh
@@ -0,0 +1,63 @@
+# $OpenBSD: sftp-uri.sh,v 1.1 2017/10/24 19:33:32 millert Exp $
+# Placed in the Public Domain.
+
+tid="sftp-uri"
+
+#set -x
+
+COPY2=${OBJ}/copy2
+DIR=${COPY}.dd
+DIR2=${COPY}.dd2
+SRC=`dirname ${SCRIPT}`
+
+sftpclean() {
+ rm -rf ${COPY} ${COPY2} ${DIR} ${DIR2}
+ mkdir ${DIR} ${DIR2}
+}
+
+start_sshd -oForceCommand="internal-sftp -d /"
+
+# Remove Port and User from ssh_config, we want to rely on the URI
+cp $OBJ/ssh_config $OBJ/ssh_config.orig
+egrep -v '^ +(Port|User) +.*$' $OBJ/ssh_config.orig > $OBJ/ssh_config
+
+verbose "$tid: non-interactive fetch to local file"
+sftpclean
+${SFTP} -q -S "$SSH" -F $OBJ/ssh_config "sftp://${USER}@somehost:${PORT}/${DATA}" ${COPY} || fail "copy failed"
+cmp ${DATA} ${COPY} || fail "corrupted copy"
+
+verbose "$tid: non-interactive fetch to local dir"
+sftpclean
+cp ${DATA} ${COPY}
+${SFTP} -q -S "$SSH" -F $OBJ/ssh_config "sftp://${USER}@somehost:${PORT}/${COPY}" ${DIR} || fail "copy failed"
+cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
+
+verbose "$tid: put to remote directory (trailing slash)"
+sftpclean
+${SFTP} -q -S "$SSH" -F $OBJ/ssh_config -b - \
+ "sftp://${USER}@somehost:${PORT}/${DIR}/" > /dev/null 2>&1 << EOF
+ version
+ put ${DATA} copy
+EOF
+r=$?
+if [ $r -ne 0 ]; then
+ fail "sftp failed with $r"
+else
+ cmp ${DATA} ${DIR}/copy || fail "corrupted copy"
+fi
+
+verbose "$tid: put to remote directory (no slash)"
+sftpclean
+${SFTP} -q -S "$SSH" -F $OBJ/ssh_config -b - \
+ "sftp://${USER}@somehost:${PORT}/${DIR}" > /dev/null 2>&1 << EOF
+ version
+ put ${DATA} copy
+EOF
+r=$?
+if [ $r -ne 0 ]; then
+ fail "sftp failed with $r"
+else
+ cmp ${DATA} ${DIR}/copy || fail "corrupted copy"
+fi
+
+sftpclean
diff --git a/regress/sftp.sh b/regress/sftp.sh
new file mode 100644
index 00000000..a5c88f58
--- /dev/null
+++ b/regress/sftp.sh
@@ -0,0 +1,32 @@
+# $OpenBSD: sftp.sh,v 1.6 2017/10/30 21:59:43 djm Exp $
+# Placed in the Public Domain.
+
+tid="basic sftp put/get"
+
+SFTPCMDFILE=${OBJ}/batch
+cat >$SFTPCMDFILE <<EOF
+version
+get $DATA ${COPY}.1
+put $DATA ${COPY}.2
+EOF
+
+BUFFERSIZE="5 1000 32000 64000"
+REQUESTS="1 2 10"
+
+for B in ${BUFFERSIZE}; do
+ for R in ${REQUESTS}; do
+ verbose "test $tid: buffer_size $B num_requests $R"
+ rm -f ${COPY}.1 ${COPY}.2
+ ${SFTP} -D ${SFTPSERVER} -B $B -R $R -b $SFTPCMDFILE \
+ > /dev/null 2>&1
+ r=$?
+ if [ $r -ne 0 ]; then
+ fail "sftp failed with $r"
+ else
+ cmp $DATA ${COPY}.1 || fail "corrupted copy after get"
+ cmp $DATA ${COPY}.2 || fail "corrupted copy after put"
+ fi
+ done
+done
+rm -f ${COPY}.1 ${COPY}.2
+rm -f $SFTPCMDFILE
diff --git a/regress/ssh-com-client.sh b/regress/ssh-com-client.sh
new file mode 100644
index 00000000..e4f80cf0
--- /dev/null
+++ b/regress/ssh-com-client.sh
@@ -0,0 +1,130 @@
+# $OpenBSD: ssh-com-client.sh,v 1.7 2013/05/17 04:29:14 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="connect with ssh.com client"
+
+#TEST_COMBASE=/path/to/ssh/com/binaries
+if [ "X${TEST_COMBASE}" = "X" ]; then
+ fatal '$TEST_COMBASE is not set'
+fi
+
+VERSIONS="
+ 2.1.0
+ 2.2.0
+ 2.3.0
+ 2.3.1
+ 2.4.0
+ 3.0.0
+ 3.1.0
+ 3.2.0
+ 3.2.2
+ 3.2.3
+ 3.2.5
+ 3.2.9
+ 3.2.9.1
+ 3.3.0"
+
+# 2.0.10 2.0.12 2.0.13 don't like the test setup
+
+# setup authorized keys
+SRC=`dirname ${SCRIPT}`
+cp ${SRC}/dsa_ssh2.prv ${OBJ}/id.com
+chmod 600 ${OBJ}/id.com
+${SSHKEYGEN} -i -f ${OBJ}/id.com > $OBJ/id.openssh
+chmod 600 ${OBJ}/id.openssh
+${SSHKEYGEN} -y -f ${OBJ}/id.openssh > $OBJ/authorized_keys_$USER
+${SSHKEYGEN} -e -f ${OBJ}/id.openssh > $OBJ/id.com.pub
+echo IdKey ${OBJ}/id.com > ${OBJ}/id.list
+
+# we need a DSA host key
+t=dsa
+rm -f ${OBJ}/$t ${OBJ}/$t.pub
+${SSHKEYGEN} -q -N '' -t $t -f ${OBJ}/$t
+$SUDO cp $OBJ/$t $OBJ/host.$t
+echo HostKey $OBJ/host.$t >> $OBJ/sshd_config
+
+# add hostkeys to known hosts
+mkdir -p ${OBJ}/${USER}/hostkeys
+HK=${OBJ}/${USER}/hostkeys/key_${PORT}_127.0.0.1
+${SSHKEYGEN} -e -f ${OBJ}/rsa.pub > ${HK}.ssh-rsa.pub
+${SSHKEYGEN} -e -f ${OBJ}/dsa.pub > ${HK}.ssh-dss.pub
+
+cat > ${OBJ}/ssh2_config << EOF
+*:
+ QuietMode yes
+ StrictHostKeyChecking yes
+ Port ${PORT}
+ User ${USER}
+ Host 127.0.0.1
+ IdentityFile ${OBJ}/id.list
+ RandomSeedFile ${OBJ}/random_seed
+ UserConfigDirectory ${OBJ}/%U
+ AuthenticationSuccessMsg no
+ BatchMode yes
+ ForwardX11 no
+EOF
+
+# we need a real server (no ProxyConnect option)
+start_sshd
+
+# go for it
+for v in ${VERSIONS}; do
+ ssh2=${TEST_COMBASE}/${v}/ssh2
+ if [ ! -x ${ssh2} ]; then
+ continue
+ fi
+ verbose "ssh2 ${v}"
+ key=ssh-dss
+ skipcat=0
+ case $v in
+ 2.1.*|2.3.0)
+ skipcat=1
+ ;;
+ 3.0.*)
+ key=ssh-rsa
+ ;;
+ esac
+ cp ${HK}.$key.pub ${HK}.pub
+
+ # check exit status
+ ${ssh2} -q -F ${OBJ}/ssh2_config somehost exit 42
+ r=$?
+ if [ $r -ne 42 ]; then
+ fail "ssh2 ${v} exit code test failed (got $r, expected 42)"
+ fi
+
+ # data transfer
+ rm -f ${COPY}
+ ${ssh2} -F ${OBJ}/ssh2_config somehost cat ${DATA} > ${COPY}
+ if [ $? -ne 0 ]; then
+ fail "ssh2 ${v} cat test (receive) failed"
+ fi
+ cmp ${DATA} ${COPY} || fail "ssh2 ${v} cat test (receive) data mismatch"
+
+ # data transfer, again
+ if [ $skipcat -eq 0 ]; then
+ rm -f ${COPY}
+ cat ${DATA} | \
+ ${ssh2} -F ${OBJ}/ssh2_config host "cat > ${COPY}"
+ if [ $? -ne 0 ]; then
+ fail "ssh2 ${v} cat test (send) failed"
+ fi
+ cmp ${DATA} ${COPY} || \
+ fail "ssh2 ${v} cat test (send) data mismatch"
+ fi
+
+ # no stderr after eof
+ rm -f ${COPY}
+ ${ssh2} -F ${OBJ}/ssh2_config somehost \
+ exec sh -c \'"exec > /dev/null; sleep 1; echo bla 1>&2; exit 0"\' \
+ 2> /dev/null
+ if [ $? -ne 0 ]; then
+ fail "ssh2 ${v} stderr test failed"
+ fi
+done
+
+rm -rf ${OBJ}/${USER}
+for i in ssh2_config random_seed dsa.pub dsa host.dsa \
+ id.list id.com id.com.pub id.openssh; do
+ rm -f ${OBJ}/$i
+done
diff --git a/regress/ssh-com-keygen.sh b/regress/ssh-com-keygen.sh
new file mode 100644
index 00000000..29b02d94
--- /dev/null
+++ b/regress/ssh-com-keygen.sh
@@ -0,0 +1,74 @@
+# $OpenBSD: ssh-com-keygen.sh,v 1.4 2004/02/24 17:06:52 markus Exp $
+# Placed in the Public Domain.
+
+tid="ssh.com key import"
+
+#TEST_COMBASE=/path/to/ssh/com/binaries
+if [ "X${TEST_COMBASE}" = "X" ]; then
+ fatal '$TEST_COMBASE is not set'
+fi
+
+VERSIONS="
+ 2.0.10
+ 2.0.12
+ 2.0.13
+ 2.1.0
+ 2.2.0
+ 2.3.0
+ 2.3.1
+ 2.4.0
+ 3.0.0
+ 3.1.0
+ 3.2.0
+ 3.2.2
+ 3.2.3
+ 3.2.5
+ 3.2.9
+ 3.2.9.1
+ 3.3.0"
+
+COMPRV=${OBJ}/comkey
+COMPUB=${COMPRV}.pub
+OPENSSHPRV=${OBJ}/opensshkey
+OPENSSHPUB=${OPENSSHPRV}.pub
+
+# go for it
+for v in ${VERSIONS}; do
+ keygen=${TEST_COMBASE}/${v}/ssh-keygen2
+ if [ ! -x ${keygen} ]; then
+ continue
+ fi
+ types="dss"
+ case $v in
+ 2.3.1|3.*)
+ types="$types rsa"
+ ;;
+ esac
+ for t in $types; do
+ verbose "ssh-keygen $v/$t"
+ rm -f $COMPRV $COMPUB $OPENSSHPRV $OPENSSHPUB
+ ${keygen} -q -P -t $t ${COMPRV} > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ fail "${keygen} -t $t failed"
+ continue
+ fi
+ ${SSHKEYGEN} -if ${COMPUB} > ${OPENSSHPUB}
+ if [ $? -ne 0 ]; then
+ fail "import public key ($v/$t) failed"
+ continue
+ fi
+ ${SSHKEYGEN} -if ${COMPRV} > ${OPENSSHPRV}
+ if [ $? -ne 0 ]; then
+ fail "import private key ($v/$t) failed"
+ continue
+ fi
+ chmod 600 ${OPENSSHPRV}
+ ${SSHKEYGEN} -yf ${OPENSSHPRV} |\
+ diff - ${OPENSSHPUB}
+ if [ $? -ne 0 ]; then
+ fail "public keys ($v/$t) differ"
+ fi
+ done
+done
+
+rm -f $COMPRV $COMPUB $OPENSSHPRV $OPENSSHPUB
diff --git a/regress/ssh-com-sftp.sh b/regress/ssh-com-sftp.sh
new file mode 100644
index 00000000..fabfa498
--- /dev/null
+++ b/regress/ssh-com-sftp.sh
@@ -0,0 +1,65 @@
+# $OpenBSD: ssh-com-sftp.sh,v 1.7 2013/05/17 04:29:14 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="basic sftp put/get with ssh.com server"
+
+SFTPCMDFILE=${OBJ}/batch
+
+cat >$SFTPCMDFILE <<EOF
+version
+get $DATA ${COPY}.1
+put $DATA ${COPY}.2
+EOF
+
+BUFFERSIZE="5 1000 32000 64000"
+REQUESTS="1 2 10"
+
+#TEST_COMBASE=/path/to/ssh/com/binaries
+if [ "X${TEST_COMBASE}" = "X" ]; then
+ fatal '$TEST_COMBASE is not set'
+fi
+
+VERSIONS="
+ 2.0.10
+ 2.0.12
+ 2.0.13
+ 2.1.0
+ 2.2.0
+ 2.3.0
+ 2.3.1
+ 2.4.0
+ 3.0.0
+ 3.1.0
+ 3.2.0
+ 3.2.2
+ 3.2.3
+ 3.2.5
+ 3.2.9
+ 3.2.9.1
+ 3.3.0"
+
+# go for it
+for v in ${VERSIONS}; do
+ server=${TEST_COMBASE}/${v}/sftp-server2
+ if [ ! -x ${server} ]; then
+ continue
+ fi
+ verbose "sftp-server $v"
+ for B in ${BUFFERSIZE}; do
+ for R in ${REQUESTS}; do
+ verbose "test $tid: buffer_size $B num_requests $R"
+ rm -f ${COPY}.1 ${COPY}.2
+ ${SFTP} -D ${server} -B $B -R $R -b $SFTPCMDFILE \
+ > /dev/null 2>&1
+ r=$?
+ if [ $r -ne 0 ]; then
+ fail "sftp failed with $r"
+ else
+ cmp $DATA ${COPY}.1 || fail "corrupted copy after get"
+ cmp $DATA ${COPY}.2 || fail "corrupted copy after put"
+ fi
+ done
+ done
+done
+rm -f ${COPY}.1 ${COPY}.2
+rm -f $SFTPCMDFILE
diff --git a/regress/ssh-com.sh b/regress/ssh-com.sh
new file mode 100644
index 00000000..b1a2505d
--- /dev/null
+++ b/regress/ssh-com.sh
@@ -0,0 +1,119 @@
+# $OpenBSD: ssh-com.sh,v 1.10 2017/05/08 01:52:49 djm Exp $
+# Placed in the Public Domain.
+
+tid="connect to ssh.com server"
+
+#TEST_COMBASE=/path/to/ssh/com/binaries
+if [ "X${TEST_COMBASE}" = "X" ]; then
+ fatal '$TEST_COMBASE is not set'
+fi
+
+VERSIONS="
+ 2.0.12
+ 2.0.13
+ 2.1.0
+ 2.2.0
+ 2.3.0
+ 2.4.0
+ 3.0.0
+ 3.1.0
+ 3.2.0
+ 3.2.2
+ 3.2.3
+ 3.2.5
+ 3.2.9
+ 3.2.9.1
+ 3.3.0"
+# 2.0.10 does not support UserConfigDirectory
+# 2.3.1 requires a config in $HOME/.ssh2
+
+SRC=`dirname ${SCRIPT}`
+
+# ssh.com
+cat << EOF > $OBJ/sshd2_config
+#*:
+ # Port and ListenAddress are not used.
+ QuietMode yes
+ Port 4343
+ ListenAddress 127.0.0.1
+ UserConfigDirectory ${OBJ}/%U
+ Ciphers AnyCipher
+ PubKeyAuthentication yes
+ #AllowedAuthentications publickey
+ AuthorizationFile authorization
+ HostKeyFile ${SRC}/dsa_ssh2.prv
+ PublicHostKeyFile ${SRC}/dsa_ssh2.pub
+ RandomSeedFile ${OBJ}/random_seed
+ MaxConnections 0
+ PermitRootLogin yes
+ VerboseMode no
+ CheckMail no
+ Ssh1Compatibility no
+EOF
+
+# create client config
+sed "s/HostKeyAlias.*/HostKeyAlias ssh2-localhost-with-alias/" \
+ < $OBJ/ssh_config > $OBJ/ssh_config_com
+
+# we need a DSA key for
+rm -f ${OBJ}/dsa ${OBJ}/dsa.pub
+${SSHKEYGEN} -q -N '' -t dsa -f ${OBJ}/dsa
+
+# setup userdir, try rsa first
+mkdir -p ${OBJ}/${USER}
+cp /dev/null ${OBJ}/${USER}/authorization
+for t in rsa dsa; do
+ ${SSHKEYGEN} -e -f ${OBJ}/$t.pub > ${OBJ}/${USER}/$t.com
+ echo Key $t.com >> ${OBJ}/${USER}/authorization
+ echo IdentityFile ${OBJ}/$t >> ${OBJ}/ssh_config_com
+done
+
+# convert and append DSA hostkey
+(
+ printf 'ssh2-localhost-with-alias,127.0.0.1,::1 '
+ ${SSHKEYGEN} -if ${SRC}/dsa_ssh2.pub
+) >> $OBJ/known_hosts
+
+# go for it
+for v in ${VERSIONS}; do
+ sshd2=${TEST_COMBASE}/${v}/sshd2
+ if [ ! -x ${sshd2} ]; then
+ continue
+ fi
+ trace "sshd2 ${v}"
+ PROXY="proxycommand ${sshd2} -qif ${OBJ}/sshd2_config 2> /dev/null"
+ ${SSH} -qF ${OBJ}/ssh_config_com -o "${PROXY}" dummy exit 0
+ if [ $? -ne 0 ]; then
+ fail "ssh connect to sshd2 ${v} failed"
+ fi
+
+ ciphers="3des-cbc"
+ macs="hmac-md5"
+ case $v in
+ 2.4.*)
+ ciphers="$ciphers cast128-cbc"
+ macs="$macs hmac-sha1 hmac-sha1-96 hmac-md5-96"
+ ;;
+ 3.*)
+ ciphers="$ciphers aes128-cbc cast128-cbc"
+ macs="$macs hmac-sha1 hmac-sha1-96 hmac-md5-96"
+ ;;
+ esac
+ #ciphers="3des-cbc"
+ for m in $macs; do
+ for c in $ciphers; do
+ trace "sshd2 ${v} cipher $c mac $m"
+ verbose "test ${tid}: sshd2 ${v} cipher $c mac $m"
+ ${SSH} -c $c -m $m -qF ${OBJ}/ssh_config_com -o "${PROXY}" dummy exit 0
+ if [ $? -ne 0 ]; then
+ fail "ssh connect to sshd2 ${v} with $c/$m failed"
+ fi
+ done
+ done
+done
+
+rm -rf ${OBJ}/${USER}
+for i in sshd_config_proxy ssh_config_proxy random_seed \
+ sshd2_config dsa.pub dsa ssh_config_com; do
+ rm -f ${OBJ}/$i
+done
diff --git a/regress/ssh2putty.sh b/regress/ssh2putty.sh
new file mode 100755
index 00000000..dcb975d9
--- /dev/null
+++ b/regress/ssh2putty.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+# $OpenBSD: ssh2putty.sh,v 1.5 2019/11/21 05:18:47 tb Exp $
+
+if test "x$1" = "x" -o "x$2" = "x" -o "x$3" = "x" ; then
+ echo "Usage: ssh2putty hostname port ssh-private-key"
+ exit 1
+fi
+
+HOST=$1
+PORT=$2
+KEYFILE=$3
+
+# XXX - support DSA keys too
+if grep "BEGIN RSA PRIVATE KEY" $KEYFILE >/dev/null 2>&1 ; then
+ :
+else
+ echo "Unsupported private key format"
+ exit 1
+fi
+
+public_exponent=`
+ openssl rsa -noout -text -in $KEYFILE | grep ^publicExponent |
+ sed 's/.*(//;s/).*//'
+`
+test $? -ne 0 && exit 1
+
+modulus=`
+ openssl rsa -noout -modulus -in $KEYFILE | grep ^Modulus= |
+ sed 's/^Modulus=/0x/' | tr A-Z a-z
+`
+test $? -ne 0 && exit 1
+
+echo "rsa2@$PORT:$HOST $public_exponent,$modulus"
+
diff --git a/regress/sshcfgparse.sh b/regress/sshcfgparse.sh
new file mode 100644
index 00000000..fc72a0a7
--- /dev/null
+++ b/regress/sshcfgparse.sh
@@ -0,0 +1,108 @@
+# $OpenBSD: sshcfgparse.sh,v 1.6 2019/12/21 02:33:07 djm Exp $
+# Placed in the Public Domain.
+
+tid="ssh config parse"
+
+dsa=0
+for t in $SSH_KEYTYPES; do
+ case "$t" in
+ ssh-dss) dsa=1 ;;
+ esac
+done
+
+expect_result_present() {
+ _str="$1" ; shift
+ for _expect in "$@" ; do
+ echo "$f" | tr ',' '\n' | grep "^$_expect\$" >/dev/null
+ if test $? -ne 0 ; then
+ fail "missing expected \"$_expect\" from \"$_str\""
+ fi
+ done
+}
+expect_result_absent() {
+ _str="$1" ; shift
+ for _expect in "$@" ; do
+ echo "$f" | tr ',' '\n' | grep "^$_expect\$" >/dev/null
+ if test $? -eq 0 ; then
+ fail "unexpected \"$_expect\" present in \"$_str\""
+ fi
+ done
+}
+
+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"
+
+verbose "ssh -W opts"
+f=`${SSH} -GF $OBJ/ssh_config host | awk '/exitonforwardfailure/{print $2}'`
+test "$f" = "no" || fail "exitonforwardfailure default"
+f=`${SSH} -GF $OBJ/ssh_config -W a:1 h | awk '/exitonforwardfailure/{print $2}'`
+test "$f" = "yes" || fail "exitonforwardfailure enable"
+f=`${SSH} -GF $OBJ/ssh_config -W a:1 -o exitonforwardfailure=no h | \
+ awk '/exitonforwardfailure/{print $2}'`
+test "$f" = "no" || fail "exitonforwardfailure override"
+
+f=`${SSH} -GF $OBJ/ssh_config host | awk '/clearallforwardings/{print $2}'`
+test "$f" = "no" || fail "clearallforwardings default"
+f=`${SSH} -GF $OBJ/ssh_config -W a:1 h | awk '/clearallforwardings/{print $2}'`
+test "$f" = "yes" || fail "clearallforwardings enable"
+f=`${SSH} -GF $OBJ/ssh_config -W a:1 -o clearallforwardings=no h | \
+ awk '/clearallforwardings/{print $2}'`
+test "$f" = "no" || fail "clearallforwardings override"
+
+verbose "user first match"
+user=`awk '$1=="User" {print $2}' $OBJ/ssh_config`
+f=`${SSH} -GF $OBJ/ssh_config host | awk '/^user /{print $2}'`
+test "$f" = "$user" || fail "user from config, expected '$user' got '$f'"
+f=`${SSH} -GF $OBJ/ssh_config -o user=foo -l bar baz@host | awk '/^user /{print $2}'`
+test "$f" = "foo" || fail "user first match -oUser, expected 'foo' got '$f' "
+f=`${SSH} -GF $OBJ/ssh_config -lbar baz@host user=foo baz@host | awk '/^user /{print $2}'`
+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"
+# Default set
+f=`${SSH} -GF none host | awk '/^pubkeyacceptedkeytypes /{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}'`
+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}'`
+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}'`
+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}'`
+ 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}'`
+ expect_result_present "$f" "ssh-ed25519" "ssh-ed25519-cert-v01.*" "ssh-dss"
+ expect_result_absent "$f" "ssh-dss-cert-v01.*"
+fi
+
+verbose "agentforwarding"
+f=`${SSH} -GF none host | awk '/^forwardagent /{print$2}'`
+expect_result_present "$f" "no"
+f=`${SSH} -GF none -oforwardagent=no host | awk '/^forwardagent /{print$2}'`
+expect_result_present "$f" "no"
+f=`${SSH} -GF none -oforwardagent=yes host | awk '/^forwardagent /{print$2}'`
+expect_result_present "$f" "yes"
+f=`${SSH} -GF none '-oforwardagent=SSH_AUTH_SOCK.forward' host | awk '/^forwardagent /{print$2}'`
+expect_result_present "$f" "SSH_AUTH_SOCK.forward"
+
+# cleanup
+rm -f $OBJ/ssh_config.[012]
diff --git a/regress/sshd-log-wrapper.sh b/regress/sshd-log-wrapper.sh
new file mode 100644
index 00000000..29dc44aa
--- /dev/null
+++ b/regress/sshd-log-wrapper.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# $OpenBSD: sshd-log-wrapper.sh,v 1.4 2016/11/25 02:56:49 dtucker Exp $
+# Placed in the Public Domain.
+#
+# simple wrapper for sshd proxy mode to catch stderr output
+# sh sshd-log-wrapper.sh /path/to/logfile /path/to/sshd [args...]
+
+log=$1
+shift
+
+exec "$@" -E$log
diff --git a/regress/sshsig.sh b/regress/sshsig.sh
new file mode 100644
index 00000000..1e2f9dda
--- /dev/null
+++ b/regress/sshsig.sh
@@ -0,0 +1,196 @@
+# $OpenBSD: sshsig.sh,v 1.4 2020/03/13 03:18:45 djm Exp $
+# Placed in the Public Domain.
+
+tid="sshsig"
+
+DATA2=$OBJ/${DATANAME}.2
+cat ${DATA} ${DATA} > ${DATA2}
+
+rm -f $OBJ/sshsig-*.sig $OBJ/wrong-key* $OBJ/sigca-key*
+
+sig_namespace="test-$$"
+sig_principal="user-$$@example.com"
+
+# Make a "wrong key"
+${SSHKEYGEN} -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 '' \
+ || fatal "couldn't generate key"
+CA_PRIV=$OBJ/sigca-key
+CA_PUB=$OBJ/sigca-key.pub
+
+trace "start agent"
+eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null
+r=$?
+if [ $r -ne 0 ]; then
+ fatal "could not start ssh-agent: exit code $r"
+fi
+
+SIGNKEYS="$SSH_KEYTYPES"
+verbose "$tid: make certificates"
+for t in $SSH_KEYTYPES ; do
+ ${SSHKEYGEN} -q -s $CA_PRIV -z $$ \
+ -I "regress signature key for $USER" \
+ -n $sig_principal $OBJ/${t} || \
+ fatal "couldn't sign ${t}"
+ SIGNKEYS="$SIGNKEYS ${t}-cert.pub"
+done
+
+for t in $SIGNKEYS; do
+ verbose "$tid: check signature for $t"
+ keybase=`basename $t .pub`
+ privkey=${OBJ}/`basename $t -cert.pub`
+ sigfile=${OBJ}/sshsig-${keybase}.sig
+ sigfile_agent=${OBJ}/sshsig-agent-${keybase}.sig
+ pubkey=${OBJ}/${keybase}.pub
+
+ ${SSHKEYGEN} -vvv -Y sign -f ${OBJ}/$t -n $sig_namespace \
+ < $DATA > $sigfile 2>/dev/null || fail "sign using $t failed"
+
+ (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ < $DATA >/dev/null 2>&1 || \
+ fail "failed signature for $t key"
+
+ (printf "$sig_principal namespaces=\"$sig_namespace,whatever\" ";
+ cat $pubkey) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ < $DATA >/dev/null 2>&1 || \
+ fail "failed signature for $t key w/ limited namespace"
+
+ # Invalid option
+ (printf "$sig_principal octopus " ; cat $pubkey) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ < $DATA >/dev/null 2>&1 && \
+ fail "accepted signature for $t key with bad signers option"
+
+ # Wrong key trusted.
+ (printf "$sig_principal " ; cat $WRONG) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ < $DATA >/dev/null 2>&1 && \
+ fail "accepted signature for $t key with wrong key trusted"
+
+ # incorrect data
+ (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ < $DATA2 >/dev/null 2>&1 && \
+ fail "passed signature for wrong data with $t key"
+
+ # wrong principal in signers
+ (printf "josef.k@example.com " ; cat $pubkey) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ < $DATA >/dev/null 2>&1 && \
+ fail "accepted signature for $t key with wrong principal"
+
+ # wrong namespace
+ (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n COWS_COWS_COWS \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ < $DATA >/dev/null 2>&1 && \
+ fail "accepted signature for $t key with wrong namespace"
+
+ # namespace excluded by option
+ (printf "$sig_principal namespaces=\"whatever\" " ;
+ cat $pubkey) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ < $DATA >/dev/null 2>&1 && \
+ fail "accepted signature for $t key with excluded namespace"
+
+ # public key in revoked keys file
+ cat $pubkey > $OBJ/revoked_keys
+ (printf "$sig_principal namespaces=\"whatever\" " ;
+ cat $pubkey) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ -r $OBJ/revoked_keys \
+ < $DATA >/dev/null 2>&1 && \
+ fail "accepted signature for $t key, but key is in revoked_keys"
+
+ # public key not revoked, but other 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 \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ -r $OBJ/revoked_keys \
+ < $DATA >/dev/null 2>&1 || \
+ fail "couldn't verify signature for $t key, but key not in revoked_keys"
+
+ # check-novalidate with valid data
+ ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile -n $sig_namespace \
+ < $DATA >/dev/null 2>&1 || \
+ fail "failed to check valid signature for $t key"
+
+ # check-novalidate with invalid data
+ ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile -n $sig_namespace \
+ < $DATA2 >/dev/null 2>&1 && \
+ fail "succeeded checking signature for $t key with invalid data"
+
+ # Check signing keys using ssh-agent.
+ ${SSHADD} -D >/dev/null 2>&1 # Remove all previously-loaded keys.
+ ${SSHADD} ${privkey} > /dev/null 2>&1 || fail "ssh-add failed"
+
+ # Move private key to ensure agent key is used
+ mv ${privkey} ${privkey}.tmp
+
+ ${SSHKEYGEN} -vvv -Y sign -f $pubkey -n $sig_namespace \
+ < $DATA > $sigfile_agent 2>/dev/null || \
+ fail "ssh-agent based sign using $pubkey failed"
+ ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile_agent \
+ -n $sig_namespace < $DATA >/dev/null 2>&1 || \
+ fail "failed to check valid signature for $t key"
+
+ # Move private key back
+ mv ${privkey}.tmp ${privkey}
+
+ # Remaining tests are for certificates only.
+ case "$keybase" in
+ *-cert) ;;
+ *) continue ;;
+ esac
+
+
+ # correct CA key
+ (printf "$sig_principal cert-authority " ;
+ cat $CA_PUB) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ < $DATA >/dev/null 2>&1 || \
+ fail "failed signature for $t cert"
+
+ # signing key listed as 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 \
+ < $DATA >/dev/null 2>&1 && \
+ fail "accepted signature with $t key listed as CA"
+
+ # CA key not flagged cert-authority
+ (printf "$sig_principal " ; cat $CA_PUB) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ < $DATA >/dev/null 2>&1 && \
+ fail "accepted signature for $t cert with CA not marked"
+
+ # mismatch between cert principal and file
+ (printf "josef.k@example.com cert-authority" ;
+ cat $CA_PUB) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ < $DATA >/dev/null 2>&1 && \
+ fail "accepted signature for $t cert with wrong principal"
+done
+
+trace "kill agent"
+${SSHAGENT} -k > /dev/null
+
diff --git a/regress/stderr-after-eof.sh b/regress/stderr-after-eof.sh
new file mode 100644
index 00000000..9065245e
--- /dev/null
+++ b/regress/stderr-after-eof.sh
@@ -0,0 +1,24 @@
+# $OpenBSD: stderr-after-eof.sh,v 1.3 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="stderr data after eof"
+
+# setup data
+rm -f ${DATA} ${COPY}
+cp /dev/null ${DATA}
+for i in 1 2 3 4 5 6; do
+ (date;echo $i) | md5 >> ${DATA}
+done
+
+${SSH} -F $OBJ/ssh_proxy otherhost \
+ exec sh -c \'"exec > /dev/null; sleep 2; cat ${DATA} 1>&2 $s"\' \
+ 2> ${COPY}
+r=$?
+if [ $r -ne 0 ]; then
+ fail "ssh failed with exit code $r"
+fi
+egrep 'Disconnecting: Received extended_data after EOF' ${COPY} &&
+ fail "ext data received after eof"
+cmp ${DATA} ${COPY} || fail "stderr corrupt"
+
+rm -f ${DATA} ${COPY}
diff --git a/regress/stderr-data.sh b/regress/stderr-data.sh
new file mode 100644
index 00000000..0ceb72b3
--- /dev/null
+++ b/regress/stderr-data.sh
@@ -0,0 +1,27 @@
+# $OpenBSD: stderr-data.sh,v 1.5 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="stderr data transfer"
+
+for n in '' -n; do
+ verbose "test $tid: ($n)"
+ ${SSH} $n -F $OBJ/ssh_proxy otherhost exec \
+ sh -c \'"exec > /dev/null; sleep 3; cat ${DATA} 1>&2 $s"\' \
+ 2> ${COPY}
+ r=$?
+ if [ $r -ne 0 ]; then
+ fail "ssh failed with exit code $r"
+ fi
+ cmp ${DATA} ${COPY} || fail "stderr corrupt"
+ rm -f ${COPY}
+
+ ${SSH} $n -F $OBJ/ssh_proxy otherhost exec \
+ sh -c \'"echo a; exec > /dev/null; sleep 3; cat ${DATA} 1>&2 $s"\' \
+ > /dev/null 2> ${COPY}
+ r=$?
+ if [ $r -ne 0 ]; then
+ fail "ssh failed with exit code $r"
+ fi
+ cmp ${DATA} ${COPY} || fail "stderr corrupt"
+ rm -f ${COPY}
+done
diff --git a/regress/t11.ok b/regress/t11.ok
new file mode 100644
index 00000000..1925bb47
--- /dev/null
+++ b/regress/t11.ok
@@ -0,0 +1 @@
+SHA256:4w1rnrek3klTJOTVhwuCIFd5k+pq9Bfo5KTxxb8BqbY
diff --git a/regress/t4.ok b/regress/t4.ok
new file mode 100644
index 00000000..4631ea8c
--- /dev/null
+++ b/regress/t4.ok
@@ -0,0 +1 @@
+MD5:3b:dd:44:e9:49:18:84:95:f1:e7:33:6b:9d:93:b1:36
diff --git a/regress/t5.ok b/regress/t5.ok
new file mode 100644
index 00000000..bd622f30
--- /dev/null
+++ b/regress/t5.ok
@@ -0,0 +1 @@
+xokes-lylis-byleh-zebib-kalus-bihas-tevah-haroz-suhar-foved-noxex
diff --git a/regress/test-exec.sh b/regress/test-exec.sh
new file mode 100644
index 00000000..5dc975d0
--- /dev/null
+++ b/regress/test-exec.sh
@@ -0,0 +1,702 @@
+# $OpenBSD: test-exec.sh,v 1.76 2020/04/04 23:04:41 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 [ ! -z "$TEST_SSH_PORT" ]; then
+ PORT="$TEST_SSH_PORT"
+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'
+ exit 2
+fi
+if [ ! -d $OBJ ]; then
+ echo "not a directory: $OBJ"
+ exit 2
+fi
+SCRIPT=$2
+if [ "x$SCRIPT" = "x" ]; then
+ echo '$SCRIPT not defined'
+ exit 2
+fi
+if [ ! -f $SCRIPT ]; then
+ echo "not a file: $SCRIPT"
+ exit 2
+fi
+if $TEST_SHELL -n $SCRIPT; then
+ true
+else
+ echo "syntax error in $SCRIPT"
+ exit 2
+fi
+unset SSH_AUTH_SOCK
+
+SRC=`dirname ${SCRIPT}`
+
+# defaults
+SSH=ssh
+SSHD=sshd
+SSHAGENT=ssh-agent
+SSHADD=ssh-add
+SSHKEYGEN=ssh-keygen
+SSHKEYSCAN=ssh-keyscan
+SFTP=sftp
+SFTPSERVER=/usr/libexec/openssh/sftp-server
+SCP=scp
+
+# Set by make_tmpdir() on demand (below).
+SSH_REGRESS_TMP=
+
+# Interop testing
+PLINK=plink
+PUTTYGEN=puttygen
+CONCH=conch
+
+# Tools used by multiple tests
+NC=$OBJ/netcat
+
+if [ "x$TEST_SSH_SSH" != "x" ]; then
+ SSH="${TEST_SSH_SSH}"
+fi
+if [ "x$TEST_SSH_SSHD" != "x" ]; then
+ SSHD="${TEST_SSH_SSHD}"
+fi
+if [ "x$TEST_SSH_SSHAGENT" != "x" ]; then
+ SSHAGENT="${TEST_SSH_SSHAGENT}"
+fi
+if [ "x$TEST_SSH_SSHADD" != "x" ]; then
+ SSHADD="${TEST_SSH_SSHADD}"
+fi
+if [ "x$TEST_SSH_SSHKEYGEN" != "x" ]; then
+ SSHKEYGEN="${TEST_SSH_SSHKEYGEN}"
+fi
+if [ "x$TEST_SSH_SSHKEYSCAN" != "x" ]; then
+ SSHKEYSCAN="${TEST_SSH_SSHKEYSCAN}"
+fi
+if [ "x$TEST_SSH_SFTP" != "x" ]; then
+ SFTP="${TEST_SSH_SFTP}"
+fi
+if [ "x$TEST_SSH_SFTPSERVER" != "x" ]; then
+ SFTPSERVER="${TEST_SSH_SFTPSERVER}"
+fi
+if [ "x$TEST_SSH_SCP" != "x" ]; then
+ SCP="${TEST_SSH_SCP}"
+fi
+if [ "x$TEST_SSH_PLINK" != "x" ]; then
+ # Find real binary, if it exists
+ case "${TEST_SSH_PLINK}" in
+ /*) PLINK="${TEST_SSH_PLINK}" ;;
+ *) PLINK=`which ${TEST_SSH_PLINK} 2>/dev/null` ;;
+ esac
+fi
+if [ "x$TEST_SSH_PUTTYGEN" != "x" ]; then
+ # Find real binary, if it exists
+ case "${TEST_SSH_PUTTYGEN}" in
+ /*) PUTTYGEN="${TEST_SSH_PUTTYGEN}" ;;
+ *) PUTTYGEN=`which ${TEST_SSH_PUTTYGEN} 2>/dev/null` ;;
+ esac
+fi
+if [ "x$TEST_SSH_CONCH" != "x" ]; then
+ # Find real binary, if it exists
+ case "${TEST_SSH_CONCH}" in
+ /*) CONCH="${TEST_SSH_CONCH}" ;;
+ *) CONCH=`which ${TEST_SSH_CONCH} 2>/dev/null` ;;
+ esac
+fi
+if [ "x$TEST_SSH_PKCS11_HELPER" != "x" ]; then
+ SSH_PKCS11_HELPER="${TEST_SSH_PKCS11_HELPER}"
+fi
+if [ "x$TEST_SSH_SK_HELPER" != "x" ]; then
+ SSH_SK_HELPER="${TEST_SSH_SK_HELPER}"
+fi
+
+# Path to sshd must be absolute for rexec
+case "$SSHD" in
+/*) ;;
+*) SSHD=`which $SSHD` ;;
+esac
+
+case "$SSHAGENT" in
+/*) ;;
+*) SSHAGENT=`which $SSHAGENT` ;;
+esac
+
+# Record the actual binaries used.
+SSH_BIN=${SSH}
+SSHD_BIN=${SSHD}
+SSHAGENT_BIN=${SSHAGENT}
+SSHADD_BIN=${SSHADD}
+SSHKEYGEN_BIN=${SSHKEYGEN}
+SSHKEYSCAN_BIN=${SSHKEYSCAN}
+SFTP_BIN=${SFTP}
+SFTPSERVER_BIN=${SFTPSERVER}
+SCP_BIN=${SCP}
+
+if [ "x$USE_VALGRIND" != "x" ]; then
+ rm -rf $OBJ/valgrind-out $OBJ/valgrind-vgdb
+ mkdir -p $OBJ/valgrind-out $OBJ/valgrind-vgdb
+ # When using sudo ensure low-priv tests can write pipes and logs.
+ if [ "x$SUDO" != "x" ]; then
+ chmod 777 $OBJ/valgrind-out $OBJ/valgrind-vgdb
+ fi
+ VG_TEST=`basename $SCRIPT .sh`
+
+ # Some tests are difficult to fix.
+ case "$VG_TEST" in
+ reexec)
+ VG_SKIP=1 ;;
+ sftp-chroot)
+ if [ "x${SUDO}" != "x" ]; then
+ VG_SKIP=1
+ fi ;;
+ esac
+
+ if [ x"$VG_SKIP" = "x" ]; then
+ VG_LEAK="--leak-check=no"
+ if [ x"$VALGRIND_CHECK_LEAKS" != "x" ]; then
+ VG_LEAK="--leak-check=full"
+ fi
+ VG_IGNORE="/bin/*,/sbin/*,/usr/*,/var/*"
+ VG_LOG="$OBJ/valgrind-out/${VG_TEST}."
+ VG_OPTS="--track-origins=yes $VG_LEAK"
+ VG_OPTS="$VG_OPTS --trace-children=yes"
+ VG_OPTS="$VG_OPTS --trace-children-skip=${VG_IGNORE}"
+ VG_OPTS="$VG_OPTS --vgdb-prefix=$OBJ/valgrind-vgdb/"
+ VG_PATH="valgrind"
+ if [ "x$VALGRIND_PATH" != "x" ]; then
+ VG_PATH="$VALGRIND_PATH"
+ fi
+ VG="$VG_PATH $VG_OPTS"
+ SSH="$VG --log-file=${VG_LOG}ssh.%p $SSH"
+ SSHD="$VG --log-file=${VG_LOG}sshd.%p $SSHD"
+ SSHAGENT="$VG --log-file=${VG_LOG}ssh-agent.%p $SSHAGENT"
+ SSHADD="$VG --log-file=${VG_LOG}ssh-add.%p $SSHADD"
+ SSHKEYGEN="$VG --log-file=${VG_LOG}ssh-keygen.%p $SSHKEYGEN"
+ SSHKEYSCAN="$VG --log-file=${VG_LOG}ssh-keyscan.%p $SSHKEYSCAN"
+ SFTP="$VG --log-file=${VG_LOG}sftp.%p ${SFTP}"
+ SCP="$VG --log-file=${VG_LOG}scp.%p $SCP"
+ cat > $OBJ/valgrind-sftp-server.sh << EOF
+#!/bin/sh
+exec $VG --log-file=${VG_LOG}sftp-server.%p $SFTPSERVER "\$@"
+EOF
+ chmod a+rx $OBJ/valgrind-sftp-server.sh
+ SFTPSERVER="$OBJ/valgrind-sftp-server.sh"
+ fi
+fi
+
+# Logfiles.
+# SSH_LOGFILE should be the debug output of ssh(1) only
+# SSHD_LOGFILE should be the debug output of sshd(8) only
+# REGRESS_LOGFILE is the output of the test itself stdout and stderr
+if [ "x$TEST_SSH_LOGFILE" = "x" ]; then
+ TEST_SSH_LOGFILE=$OBJ/ssh.log
+fi
+if [ "x$TEST_SSHD_LOGFILE" = "x" ]; then
+ TEST_SSHD_LOGFILE=$OBJ/sshd.log
+fi
+if [ "x$TEST_REGRESS_LOGFILE" = "x" ]; then
+ TEST_REGRESS_LOGFILE=$OBJ/regress.log
+fi
+
+# truncate logfiles
+>$TEST_SSH_LOGFILE
+>$TEST_SSHD_LOGFILE
+>$TEST_REGRESS_LOGFILE
+
+# Create wrapper ssh with logging. We can't just specify "SSH=ssh -E..."
+# because sftp and scp don't handle spaces in arguments.
+SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh
+echo "#!/bin/sh" > $SSHLOGWRAP
+echo "exec ${SSH} -E${TEST_SSH_LOGFILE} "'"$@"' >>$SSHLOGWRAP
+
+chmod a+rx $OBJ/ssh-log-wrapper.sh
+REAL_SSH="$SSH"
+REAL_SSHD="$SSHD"
+SSH="$SSHLOGWRAP"
+
+# Some test data. We make a copy because some tests will overwrite it.
+# The tests may assume that $DATA exists and is writable and $COPY does
+# not exist. Tests requiring larger data files can call increase_datafile_size
+# [kbytes] to ensure the file is at least that large.
+DATANAME=data
+DATA=$OBJ/${DATANAME}
+cat ${SSHAGENT_BIN} >${DATA}
+chmod u+w ${DATA}
+COPY=$OBJ/copy
+rm -f ${COPY}
+
+increase_datafile_size()
+{
+ while [ `du -k ${DATA} | cut -f1` -lt $1 ]; do
+ cat ${SSHAGENT_BIN} >>${DATA}
+ done
+}
+
+# these should be used in tests
+export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP
+export SSH_PKCS11_HELPER SSH_SK_HELPER
+#echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP
+
+# Portable specific functions
+have_prog()
+{
+ saved_IFS="$IFS"
+ IFS=":"
+ for i in $PATH
+ do
+ if [ -x $i/$1 ]; then
+ IFS="$saved_IFS"
+ return 0
+ fi
+ done
+ IFS="$saved_IFS"
+ return 1
+}
+
+jot() {
+ awk "BEGIN { for (i = $2; i < $2 + $1; i++) { printf \"%d\n\", i } exit }"
+}
+
+# Check whether preprocessor symbols are defined in config.h.
+config_defined ()
+{
+ str=$1
+ while test "x$2" != "x" ; do
+ str="$str|$2"
+ shift
+ done
+ egrep "^#define.*($str)" ${BUILDDIR}/config.h >/dev/null 2>&1
+}
+
+md5 () {
+ if have_prog md5sum; then
+ md5sum
+ elif have_prog openssl; then
+ openssl md5
+ elif have_prog cksum; then
+ cksum
+ elif have_prog sum; then
+ sum
+ else
+ wc -c
+ fi
+}
+# End of portable specific functions
+
+stop_sshd ()
+{
+ if [ -f $PIDFILE ]; then
+ pid=`$SUDO cat $PIDFILE`
+ if [ "X$pid" = "X" ]; then
+ echo no sshd running
+ else
+ if [ $pid -lt 2 ]; then
+ echo bad pid for sshd: $pid
+ else
+ $SUDO kill $pid
+ trace "wait for sshd to exit"
+ i=0;
+ while [ -f $PIDFILE -a $i -lt 5 ]; do
+ i=`expr $i + 1`
+ sleep $i
+ done
+ if test -f $PIDFILE; then
+ if $SUDO kill -0 $pid; then
+ echo "sshd didn't exit " \
+ "port $PORT pid $pid"
+ else
+ echo "sshd died without cleanup"
+ fi
+ exit 1
+ fi
+ fi
+ fi
+ fi
+}
+
+make_tmpdir ()
+{
+ SSH_REGRESS_TMP="$($OBJ/mkdtemp openssh-XXXXXXXX)" || \
+ fatal "failed to create temporary directory"
+}
+
+# helper
+cleanup ()
+{
+ if [ "x$SSH_PID" != "x" ]; then
+ if [ $SSH_PID -lt 2 ]; then
+ echo bad pid for ssh: $SSH_PID
+ else
+ kill $SSH_PID
+ fi
+ fi
+ if [ "x$SSH_REGRESS_TMP" != "x" ]; then
+ rm -rf "$SSH_REGRESS_TMP"
+ fi
+ stop_sshd
+}
+
+start_debug_log ()
+{
+ echo "trace: $@" >$TEST_REGRESS_LOGFILE
+ echo "trace: $@" >$TEST_SSH_LOGFILE
+ echo "trace: $@" >$TEST_SSHD_LOGFILE
+}
+
+save_debug_log ()
+{
+ echo $@ >>$TEST_REGRESS_LOGFILE
+ echo $@ >>$TEST_SSH_LOGFILE
+ echo $@ >>$TEST_SSHD_LOGFILE
+ (cat $TEST_REGRESS_LOGFILE; echo) >>$OBJ/failed-regress.log
+ (cat $TEST_SSH_LOGFILE; echo) >>$OBJ/failed-ssh.log
+ (cat $TEST_SSHD_LOGFILE; echo) >>$OBJ/failed-sshd.log
+}
+
+trace ()
+{
+ start_debug_log $@
+ if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then
+ echo "$@"
+ fi
+}
+
+verbose ()
+{
+ start_debug_log $@
+ if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then
+ echo "$@"
+ fi
+}
+
+warn ()
+{
+ echo "WARNING: $@" >>$TEST_SSH_LOGFILE
+ echo "WARNING: $@"
+}
+
+fail ()
+{
+ save_debug_log "FAIL: $@"
+ RESULT=1
+ echo "$@"
+ if test "x$TEST_SSH_FAIL_FATAL" != "x" ; then
+ cleanup
+ exit $RESULT
+ fi
+}
+
+fatal ()
+{
+ save_debug_log "FATAL: $@"
+ printf "FATAL: "
+ fail "$@"
+ cleanup
+ exit $RESULT
+}
+
+RESULT=0
+PIDFILE=$OBJ/pidfile
+
+trap fatal 3 2
+
+# create server config
+cat << EOF > $OBJ/sshd_config
+ StrictModes no
+ Port $PORT
+ AddressFamily inet
+ ListenAddress 127.0.0.1
+ #ListenAddress ::1
+ PidFile $PIDFILE
+ AuthorizedKeysFile $OBJ/authorized_keys_%u
+ LogLevel DEBUG3
+ AcceptEnv _XXX_TEST_*
+ AcceptEnv _XXX_TEST
+ Subsystem sftp $SFTPSERVER
+EOF
+
+# This may be necessary if /usr/src and/or /usr/obj are group-writable,
+# but if you aren't careful with permissions then the unit tests could
+# be abused to locally escalate privileges.
+if [ ! -z "$TEST_SSH_UNSAFE_PERMISSIONS" ]; then
+ echo "StrictModes no" >> $OBJ/sshd_config
+else
+ # check and warn if excessive permissions are likely to cause failures.
+ unsafe=""
+ dir="${OBJ}"
+ while test ${dir} != "/"; do
+ if test -d "${dir}" && ! test -h "${dir}"; then
+ perms=`ls -ld ${dir}`
+ case "${perms}" in
+ ?????w????*|????????w?*) unsafe="${unsafe} ${dir}" ;;
+ esac
+ fi
+ dir=`dirname ${dir}`
+ done
+ if ! test -z "${unsafe}"; then
+ cat <<EOD
+
+WARNING: Unsafe (group or world writable) directory permissions found:
+${unsafe}
+
+These could be abused to locally escalate privileges. If you are
+sure that this is not a risk (eg there are no other users), you can
+bypass this check by setting TEST_SSH_UNSAFE_PERMISSIONS=1
+
+EOD
+ fi
+fi
+
+if [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then
+ trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS"
+ echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config
+fi
+
+# server config for proxy connects
+cp $OBJ/sshd_config $OBJ/sshd_proxy
+
+# allow group-writable directories in proxy-mode
+echo 'StrictModes no' >> $OBJ/sshd_proxy
+
+# create client config
+cat << EOF > $OBJ/ssh_config
+Host *
+ Hostname 127.0.0.1
+ HostKeyAlias localhost-with-alias
+ Port $PORT
+ User $USER
+ GlobalKnownHostsFile $OBJ/known_hosts
+ UserKnownHostsFile $OBJ/known_hosts
+ PubkeyAuthentication yes
+ ChallengeResponseAuthentication no
+ HostbasedAuthentication no
+ PasswordAuthentication no
+ BatchMode yes
+ StrictHostKeyChecking yes
+ LogLevel DEBUG3
+EOF
+
+if [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then
+ trace "adding ssh_config option $TEST_SSH_SSH_CONFOPTS"
+ echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config
+fi
+
+rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER
+
+SSH_SK_PROVIDER=
+if ! config_defined ENABLE_SK; then
+ trace skipping sk-dummy
+elif [ -f "${SRC}/misc/sk-dummy/obj/sk-dummy.so" ] ; then
+ SSH_SK_PROVIDER="${SRC}/misc/sk-dummy/obj/sk-dummy.so"
+elif [ -f "${SRC}/misc/sk-dummy/sk-dummy.so" ] ; then
+ SSH_SK_PROVIDER="${SRC}/misc/sk-dummy/sk-dummy.so"
+fi
+export SSH_SK_PROVIDER
+
+if ! test -z "$SSH_SK_PROVIDER"; then
+ EXTRA_AGENT_ARGS='-P/*' # XXX want realpath(1)...
+ echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/ssh_config
+ echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/sshd_config
+ echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/sshd_proxy
+fi
+export EXTRA_AGENT_ARGS
+
+maybe_filter_sk() {
+ if test -z "$SSH_SK_PROVIDER" ; then
+ grep -v ^sk
+ else
+ cat
+ fi
+}
+
+SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk`
+SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk`
+
+for t in ${SSH_KEYTYPES}; do
+ # generate user key
+ if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN_BIN} -nt $OBJ/$t ]; then
+ trace "generating key type $t"
+ rm -f $OBJ/$t
+ ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\
+ fail "ssh-keygen for $t failed"
+ else
+ trace "using cached key type $t"
+ fi
+
+ # setup authorized keys
+ cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+ echo IdentityFile $OBJ/$t >> $OBJ/ssh_config
+done
+
+for t in ${SSH_HOSTKEY_TYPES}; do
+ # known hosts file for client
+ (
+ printf 'localhost-with-alias,127.0.0.1,::1 '
+ cat $OBJ/$t.pub
+ ) >> $OBJ/known_hosts
+
+ # use key as host key, too
+ $SUDO cp $OBJ/$t $OBJ/host.$t
+ echo HostKey $OBJ/host.$t >> $OBJ/sshd_config
+
+ # don't use SUDO for proxy connect
+ echo HostKey $OBJ/$t >> $OBJ/sshd_proxy
+done
+chmod 644 $OBJ/authorized_keys_$USER
+
+# Activate Twisted Conch tests if the binary is present
+REGRESS_INTEROP_CONCH=no
+if test -x "$CONCH" ; then
+ REGRESS_INTEROP_CONCH=yes
+fi
+
+# If PuTTY is present and we are running a PuTTY test, prepare keys and
+# configuration
+REGRESS_INTEROP_PUTTY=no
+if test -x "$PUTTYGEN" -a -x "$PLINK" ; then
+ REGRESS_INTEROP_PUTTY=yes
+fi
+case "$SCRIPT" in
+*putty*) ;;
+*) REGRESS_INTEROP_PUTTY=no ;;
+esac
+
+if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then
+ mkdir -p ${OBJ}/.putty
+
+ # Add a PuTTY key to authorized_keys
+ rm -f ${OBJ}/putty.rsa2
+ if ! puttygen -t rsa -o ${OBJ}/putty.rsa2 \
+ --random-device=/dev/urandom \
+ --new-passphrase /dev/null < /dev/null > /dev/null; then
+ echo "Your installed version of PuTTY is too old to support --new-passphrase; trying without (may require manual interaction) ..." >&2
+ puttygen -t rsa -o ${OBJ}/putty.rsa2 < /dev/null > /dev/null
+ fi
+ puttygen -O public-openssh ${OBJ}/putty.rsa2 \
+ >> $OBJ/authorized_keys_$USER
+
+ # Convert rsa2 host key to PuTTY format
+ cp $OBJ/ssh-rsa $OBJ/ssh-rsa_oldfmt
+ ${SSHKEYGEN} -p -N '' -m PEM -f $OBJ/ssh-rsa_oldfmt >/dev/null
+ ${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/ssh-rsa_oldfmt > \
+ ${OBJ}/.putty/sshhostkeys
+ ${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/ssh-rsa_oldfmt >> \
+ ${OBJ}/.putty/sshhostkeys
+ rm -f $OBJ/ssh-rsa_oldfmt
+
+ # Setup proxied session
+ mkdir -p ${OBJ}/.putty/sessions
+ rm -f ${OBJ}/.putty/sessions/localhost_proxy
+ echo "Protocol=ssh" >> ${OBJ}/.putty/sessions/localhost_proxy
+ echo "HostName=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy
+ echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy
+ echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy
+ echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy
+ echo "ProxyLocalhost=1" >> ${OBJ}/.putty/sessions/localhost_proxy
+
+ PUTTYDIR=${OBJ}/.putty
+ export PUTTYDIR
+
+ REGRESS_INTEROP_PUTTY=yes
+fi
+
+# create a proxy version of the client config
+(
+ cat $OBJ/ssh_config
+ echo proxycommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy
+) > $OBJ/ssh_proxy
+
+# check proxy config
+${SSHD} -t -f $OBJ/sshd_proxy || fatal "sshd_proxy broken"
+
+start_sshd ()
+{
+ # start sshd
+ $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken"
+ $SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" \
+ ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE
+
+ trace "wait for sshd"
+ i=0;
+ while [ ! -f $PIDFILE -a $i -lt 10 ]; do
+ i=`expr $i + 1`
+ sleep $i
+ done
+
+ test -f $PIDFILE || fatal "no sshd running on port $PORT"
+}
+
+# source test body
+. $SCRIPT
+
+# kill sshd
+cleanup
+
+if [ "x$USE_VALGRIND" != "x" ]; then
+ # wait for any running process to complete
+ wait; sleep 1
+ VG_RESULTS=$(find $OBJ/valgrind-out -type f -print)
+ VG_RESULT_COUNT=0
+ VG_FAIL_COUNT=0
+ for i in $VG_RESULTS; do
+ if grep "ERROR SUMMARY" $i >/dev/null; then
+ VG_RESULT_COUNT=$(($VG_RESULT_COUNT + 1))
+ if ! grep "ERROR SUMMARY: 0 errors" $i >/dev/null; then
+ VG_FAIL_COUNT=$(($VG_FAIL_COUNT + 1))
+ RESULT=1
+ verbose valgrind failure $i
+ cat $i
+ fi
+ fi
+ done
+ if [ x"$VG_SKIP" != "x" ]; then
+ verbose valgrind skipped
+ else
+ verbose valgrind results $VG_RESULT_COUNT failures $VG_FAIL_COUNT
+ fi
+fi
+
+if [ $RESULT -eq 0 ]; then
+ verbose ok $tid
+else
+ echo failed $tid
+fi
+exit $RESULT
diff --git a/regress/transfer.sh b/regress/transfer.sh
new file mode 100644
index 00000000..cf174a00
--- /dev/null
+++ b/regress/transfer.sh
@@ -0,0 +1,23 @@
+# $OpenBSD: transfer.sh,v 1.4 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="transfer data"
+
+rm -f ${COPY}
+${SSH} -n -q -F $OBJ/ssh_proxy somehost cat ${DATA} > ${COPY}
+if [ $? -ne 0 ]; then
+ fail "ssh cat $DATA failed"
+fi
+cmp ${DATA} ${COPY} || fail "corrupted copy"
+
+for s in 10 100 1k 32k 64k 128k 256k; do
+ trace "dd-size ${s}"
+ rm -f ${COPY}
+ dd if=$DATA obs=${s} 2> /dev/null | \
+ ${SSH} -q -F $OBJ/ssh_proxy somehost "cat > ${COPY}"
+ if [ $? -ne 0 ]; then
+ fail "ssh cat $DATA failed"
+ fi
+ cmp $DATA ${COPY} || fail "corrupted copy"
+done
+rm -f ${COPY}
diff --git a/regress/try-ciphers.sh b/regress/try-ciphers.sh
new file mode 100644
index 00000000..e04268ba
--- /dev/null
+++ b/regress/try-ciphers.sh
@@ -0,0 +1,28 @@
+# $OpenBSD: try-ciphers.sh,v 1.26 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="try ciphers"
+
+cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+
+for c in `${SSH} -Q cipher`; do
+ n=0
+ for m in `${SSH} -Q mac`; do
+ trace "cipher $c mac $m"
+ verbose "test $tid: cipher $c mac $m"
+ cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+ echo "Ciphers=$c" >> $OBJ/sshd_proxy
+ echo "MACs=$m" >> $OBJ/sshd_proxy
+ ${SSH} -F $OBJ/ssh_proxy -m $m -c $c somehost true
+ if [ $? -ne 0 ]; then
+ fail "ssh failed with mac $m cipher $c"
+ fi
+ # No point trying all MACs for AEAD ciphers since they
+ # are ignored.
+ if ${SSH} -Q cipher-auth | grep "^${c}\$" >/dev/null 2>&1 ; then
+ break
+ fi
+ n=`expr $n + 1`
+ done
+done
+
diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile
new file mode 100644
index 00000000..4e56e110
--- /dev/null
+++ b/regress/unittests/Makefile
@@ -0,0 +1,7 @@
+# $OpenBSD: Makefile,v 1.11 2019/04/28 22:53:26 dtucker Exp $
+
+REGRESS_FAIL_EARLY?= yes
+SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion
+SUBDIR+=authopt misc
+
+.include <bsd.subdir.mk>
diff --git a/regress/unittests/Makefile.inc b/regress/unittests/Makefile.inc
new file mode 100644
index 00000000..370224aa
--- /dev/null
+++ b/regress/unittests/Makefile.inc
@@ -0,0 +1,89 @@
+# $OpenBSD: Makefile.inc,v 1.14 2019/11/25 10:32:35 djm Exp $
+
+REGRESS_FAIL_EARLY?= yes
+
+.include <bsd.own.mk>
+.include <bsd.obj.mk>
+
+# User-settable options
+UNITTEST_FAST?= no # Skip slow tests (e.g. less intensive fuzzing).
+UNITTEST_SLOW?= no # Include slower tests (e.g. more intensive fuzzing).
+UNITTEST_VERBOSE?= no # Verbose test output (inc. per-test names).
+
+MALLOC_OPTIONS?= CFGJRSUX
+TEST_ENV?= MALLOC_OPTIONS=${MALLOC_OPTIONS}
+
+# XXX detect from ssh binary?
+OPENSSL?= yes
+
+.if (${OPENSSL:L} == "yes")
+CFLAGS+= -DWITH_OPENSSL
+.endif
+
+# enable warnings
+WARNINGS=Yes
+
+DEBUG=-g
+CFLAGS+= -fstack-protector-all
+CDIAGFLAGS= -Wall
+CDIAGFLAGS+= -Wextra
+CDIAGFLAGS+= -Werror
+CDIAGFLAGS+= -Wchar-subscripts
+CDIAGFLAGS+= -Wcomment
+CDIAGFLAGS+= -Wformat
+CDIAGFLAGS+= -Wformat-security
+CDIAGFLAGS+= -Wimplicit
+CDIAGFLAGS+= -Winline
+CDIAGFLAGS+= -Wmissing-declarations
+CDIAGFLAGS+= -Wmissing-prototypes
+CDIAGFLAGS+= -Wparentheses
+CDIAGFLAGS+= -Wpointer-arith
+CDIAGFLAGS+= -Wreturn-type
+CDIAGFLAGS+= -Wshadow
+CDIAGFLAGS+= -Wsign-compare
+CDIAGFLAGS+= -Wstrict-aliasing
+CDIAGFLAGS+= -Wstrict-prototypes
+CDIAGFLAGS+= -Wswitch
+CDIAGFLAGS+= -Wtrigraphs
+CDIAGFLAGS+= -Wuninitialized
+CDIAGFLAGS+= -Wunused
+CDIAGFLAGS+= -Wno-unused-parameter
+.if ${COMPILER_VERSION:L} != "gcc3"
+CDIAGFLAGS+= -Wold-style-definition
+.endif
+
+SSHREL=../../../../../usr.bin/ssh
+
+CFLAGS+=-I${.CURDIR}/../test_helper -I${.CURDIR}/${SSHREL}
+
+.if exists(${.CURDIR}/../test_helper/${__objdir})
+LDADD+=-L${.CURDIR}/../test_helper/${__objdir} -ltest_helper
+DPADD+=${.CURDIR}/../test_helper/${__objdir}/libtest_helper.a
+.else
+LDADD+=-L${.CURDIR}/../test_helper -ltest_helper
+DPADD+=${.CURDIR}/../test_helper/libtest_helper.a
+.endif
+
+.PATH: ${.CURDIR}/${SSHREL}
+
+LDADD+= -lutil
+DPADD+= ${LIBUTIL}
+
+.if (${OPENSSL:L} == "yes")
+LDADD+= -lcrypto
+DPADD+= ${LIBCRYPTO}
+.endif
+
+LDADD+= -lfido2 -lcbor -lusbhid
+DPADD+= ${LIBFIDO2} ${LIBCBOR} ${LIBUSBHID}
+
+UNITTEST_ARGS?=
+
+.if (${UNITTEST_VERBOSE:L} != "no")
+UNITTEST_ARGS+= -v
+.endif
+.if (${UNITTEST_FAST:L} != "no")
+UNITTEST_ARGS+= -f
+.elif (${UNITTEST_SLOW:L} != "no")
+UNITTEST_ARGS+= -F
+.endif
diff --git a/regress/unittests/authopt/Makefile b/regress/unittests/authopt/Makefile
new file mode 100644
index 00000000..e8edc7b5
--- /dev/null
+++ b/regress/unittests/authopt/Makefile
@@ -0,0 +1,27 @@
+# $OpenBSD: Makefile,v 1.5 2020/04/06 09:43:55 dtucker Exp $
+
+PROG=test_authopt
+SRCS=tests.c
+
+SRCS+=auth-options.c
+
+# From usr.bin/ssh
+SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
+SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c
+SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
+SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
+SRCS+=addrmatch.c bitmap.c
+SRCS+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
+SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c
+SRCS+=ssh-ed25519-sk.c sk-usbhid.c
+
+SRCS+=digest-openssl.c
+#SRCS+=digest-libc.c
+SRCS+=utf8.c
+
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata
+
+.include <bsd.regress.mk>
diff --git a/regress/unittests/authopt/testdata/all_permit.cert b/regress/unittests/authopt/testdata/all_permit.cert
new file mode 100644
index 00000000..38ac5731
--- /dev/null
+++ b/regress/unittests/authopt/testdata/all_permit.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIOv/h7mJS1WkRHukSvqPwKDiNVrcib/VqBLpbHW6xjWCAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQNe1XDN+J4Eb82TH5J5sYypcabocufjTFRfpU57K+csRP41Yo1FCSEWx95ilUuNvK9Iv3yFDOeVPzdqRqzWoHwE= user key
diff --git a/regress/unittests/authopt/testdata/bad_sourceaddr.cert b/regress/unittests/authopt/testdata/bad_sourceaddr.cert
new file mode 100644
index 00000000..9732745a
--- /dev/null
+++ b/regress/unittests/authopt/testdata/bad_sourceaddr.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAILFEJyunlz9scYU3mwbOEJoSSkeO1z20uNBw13tEn+lJAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAHwAAAA5zb3VyY2UtYWRkcmVzcwAAAAkAAAAFeHh4eHgAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEA5xY/OEAJ3tgg8/KJqaBR5KMdYYRDiMJ6u4VKS9lQOV1HJQvDDvjj3F5k53BIqTJRVQx242YWs+B3C4db/uLgB user key
diff --git a/regress/unittests/authopt/testdata/force_command.cert b/regress/unittests/authopt/testdata/force_command.cert
new file mode 100644
index 00000000..f7af27e4
--- /dev/null
+++ b/regress/unittests/authopt/testdata/force_command.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJkpCeqaVl6qnp7qa90KehAmHFecx3HW8HZQ22KEqeKBAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAHAAAAA1mb3JjZS1jb21tYW5kAAAABwAAAANmb28AAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEAxbhjgbXvfEumRP1E7VH8nUfuJyVlDChhCxiPg9Nvb9PFK8cHdDUEybDCzKCsIDieRc3mtLTyEu7Kb52va/B4C user key
diff --git a/regress/unittests/authopt/testdata/host.cert b/regress/unittests/authopt/testdata/host.cert
new file mode 100644
index 00000000..6326d045
--- /dev/null
+++ b/regress/unittests/authopt/testdata/host.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIFWMw3ftP29RSefnxQwdvK1KiE2G9Y7rPRrJ7ZsrDiOeAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAACAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAKTMqwPkaBg23RS7/aj347dc2kY4bWt/sHwzREYSrKRqZ5RNBnSvZOQ8m5euMCEuf92bZ8VJEdF653jRiW6VoBA== user key
diff --git a/regress/unittests/authopt/testdata/mktestdata.sh b/regress/unittests/authopt/testdata/mktestdata.sh
new file mode 100644
index 00000000..06a24e39
--- /dev/null
+++ b/regress/unittests/authopt/testdata/mktestdata.sh
@@ -0,0 +1,48 @@
+#/bin/sh
+
+set -xe
+
+rm -f ca_key ca_key.pub
+rm -f user_key user_key.pub
+rm -f *.cert
+
+ssh-keygen -q -f ca_key -t ed25519 -C CA -N ''
+ssh-keygen -q -f user_key -t ed25519 -C "user key" -N ''
+
+sign() {
+ output=$1
+ shift
+ set -xe
+ ssh-keygen -q -s ca_key -I user -n user \
+ -V 19990101:19991231 -z 1 "$@" user_key.pub
+ mv user_key-cert.pub "$output"
+}
+
+sign all_permit.cert -Opermit-agent-forwarding -Opermit-port-forwarding \
+ -Opermit-pty -Opermit-user-rc -Opermit-X11-forwarding
+sign no_permit.cert -Oclear
+
+sign no_agentfwd.cert -Ono-agent-forwarding
+sign no_portfwd.cert -Ono-port-forwarding
+sign no_pty.cert -Ono-pty
+sign no_user_rc.cert -Ono-user-rc
+sign no_x11fwd.cert -Ono-X11-forwarding
+
+sign only_agentfwd.cert -Oclear -Opermit-agent-forwarding
+sign only_portfwd.cert -Oclear -Opermit-port-forwarding
+sign only_pty.cert -Oclear -Opermit-pty
+sign only_user_rc.cert -Oclear -Opermit-user-rc
+sign only_x11fwd.cert -Oclear -Opermit-X11-forwarding
+
+sign force_command.cert -Oforce-command="foo"
+sign sourceaddr.cert -Osource-address="127.0.0.1/32,::1/128"
+
+# ssh-keygen won't permit generation of certs with invalid source-address
+# values, so we do it as a custom extension.
+sign bad_sourceaddr.cert -Ocritical:source-address=xxxxx
+
+sign unknown_critical.cert -Ocritical:blah=foo
+
+sign host.cert -h
+
+rm -f user_key ca_key user_key.pub ca_key.pub
diff --git a/regress/unittests/authopt/testdata/no_agentfwd.cert b/regress/unittests/authopt/testdata/no_agentfwd.cert
new file mode 100644
index 00000000..bfa5c2e6
--- /dev/null
+++ b/regress/unittests/authopt/testdata/no_agentfwd.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIL2qEsLCVtKaBkbCrZicxbPUorcHHrQ8yw5h/26krTOlAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAGMAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAdRhISpol01OwV30g39PM/JD1t35muskX4lyCcGpFQ08GQtBuHE/hABOp6apbGBJIC7CZYYF+uHkD7PfGU3NPAQ== user key
diff --git a/regress/unittests/authopt/testdata/no_permit.cert b/regress/unittests/authopt/testdata/no_permit.cert
new file mode 100644
index 00000000..351e138a
--- /dev/null
+++ b/regress/unittests/authopt/testdata/no_permit.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIGVQtVgp9sD4sc8esIhVWbZaM8d0NxpX3UbEVzTHm9feAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAIKlI0TqqraKjYTjIuKhwoxAV/XnzWRJHq8lNs4aj5yDb84un2xXDF/0vXoLjPgVcLgEbksBKKn0i4whp+xn9Ag== user key
diff --git a/regress/unittests/authopt/testdata/no_portfwd.cert b/regress/unittests/authopt/testdata/no_portfwd.cert
new file mode 100644
index 00000000..9457dc34
--- /dev/null
+++ b/regress/unittests/authopt/testdata/no_portfwd.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIE6gC/QjjuzGWVDkr8ZyaHhja80V+lKLC/MvmEFa+CEBAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAGQAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQEzpgckYlfc1BK1ir0reDSXo9OIDx4UoDMrNXrFO6I44NXoJJ4TlUUJH07WcKp/Xp5ESCdyVZtqwgHQxZr0+PwI= user key
diff --git a/regress/unittests/authopt/testdata/no_pty.cert b/regress/unittests/authopt/testdata/no_pty.cert
new file mode 100644
index 00000000..e8154ec7
--- /dev/null
+++ b/regress/unittests/authopt/testdata/no_pty.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIFFjhISpSDR3blDejuCf2T9Fe4aHW53jG7KOH2PV/E7jAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAHAAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQF5c4BdxVYgqbMGAep414IGFK4deCFBCeNUTOLpKodrfb1M0gS4d2qoeMxZvMv5yMf/viKl/gallHzEmcrEcIQY= user key
diff --git a/regress/unittests/authopt/testdata/no_user_rc.cert b/regress/unittests/authopt/testdata/no_user_rc.cert
new file mode 100644
index 00000000..6676a0cb
--- /dev/null
+++ b/regress/unittests/authopt/testdata/no_user_rc.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIFUM0VLATkYh05QeS5uuhB1X50NMom3jTWeQUmrPQ1FwAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAGwAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAcmJ3c2FCKJL9BCLv1Ij+uN1N+NWZmMXYionsSkv42Go4pMZiH3g8UfTd+OKq9Q7GAcCzGXa///6Dr/wqFssoDA== user key
diff --git a/regress/unittests/authopt/testdata/no_x11fwd.cert b/regress/unittests/authopt/testdata/no_x11fwd.cert
new file mode 100644
index 00000000..0aff9e6c
--- /dev/null
+++ b/regress/unittests/authopt/testdata/no_x11fwd.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIPRKPAP+b5S+4zihdgoJrYNcMovFBgKZaJupIhN1kUvkAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAGUAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAECMzj6VDfT+BJmIEo1qUKdr8VDLExF92K7KkbNxTH77n7uip7TL24HDfXjYBCvqxSSn9KAGBhnWsIC/GPx6A+cP user key
diff --git a/regress/unittests/authopt/testdata/only_agentfwd.cert b/regress/unittests/authopt/testdata/only_agentfwd.cert
new file mode 100644
index 00000000..3cf64b05
--- /dev/null
+++ b/regress/unittests/authopt/testdata/only_agentfwd.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIOvJ28yW5uvA7yxE3ySuyFvPjcRYKAr03CYr4okGTNIFAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAB8AAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQEG2uTgmOSk9dJ0s/Ol1EIERXFP9PF6AauF9t5jBMSthNyvSANSrC/1EIaf4TV5kMYfhZxJXoS0XHQjGndcq2AE= user key
diff --git a/regress/unittests/authopt/testdata/only_portfwd.cert b/regress/unittests/authopt/testdata/only_portfwd.cert
new file mode 100644
index 00000000..bb09c3a6
--- /dev/null
+++ b/regress/unittests/authopt/testdata/only_portfwd.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIGPoYoExiSyHMyDEvOFgoNZXk5z91u7xq/7357X23TotAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAB4AAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAHN3YnwipcbDKVn+PObGSoaT9rwlau+yrPYZ50oetvCKng3RMjGaV+roqlv0vjjLcxE9J4Y0ti+9MXtQ0D7beBA== user key
diff --git a/regress/unittests/authopt/testdata/only_pty.cert b/regress/unittests/authopt/testdata/only_pty.cert
new file mode 100644
index 00000000..520c89f3
--- /dev/null
+++ b/regress/unittests/authopt/testdata/only_pty.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAILvocWYto5Lg7P46YLbe7U4/b2h9Lr5rWqMZ4Cj4ra7RAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAABIAAAAKcGVybWl0LXB0eQAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABASv2xQvp+Y6E8dCf5pzg3MZaan5bl1ToYXNcmQ3ysGrk9Djkcu8m3TytDpF471KmUejxy/iF4xjs9CDpk7h+SBQ== user key
diff --git a/regress/unittests/authopt/testdata/only_user_rc.cert b/regress/unittests/authopt/testdata/only_user_rc.cert
new file mode 100644
index 00000000..fb49c35f
--- /dev/null
+++ b/regress/unittests/authopt/testdata/only_user_rc.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJwsRZQ7kx4A8AQ0q/G/3i6sHM48kr4TxJtTcyy3lZAPAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAABYAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQDhgEXsvoHr21XrxmiZq/sIjWeYapp11XvEVkkTBPVhBnPwtrrUeJbPmGs3gmJkQdv8BYajYpT7TXEX8GvEeLwU= user key
diff --git a/regress/unittests/authopt/testdata/only_x11fwd.cert b/regress/unittests/authopt/testdata/only_x11fwd.cert
new file mode 100644
index 00000000..6715585a
--- /dev/null
+++ b/regress/unittests/authopt/testdata/only_x11fwd.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIDAhZFZBl3eu8Qa8I5BaHCz/mpH8xCjaPusBwo1eJ9OGAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAB0AAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEDysfgbhniX/zdA8576rrDJpaO2D7QtQse2KWIM9XmREPkLKeP6FKiXKKFcPQiMyV28rptfvK8bBXAiOvITSUgL user key
diff --git a/regress/unittests/authopt/testdata/sourceaddr.cert b/regress/unittests/authopt/testdata/sourceaddr.cert
new file mode 100644
index 00000000..0fcf7b18
--- /dev/null
+++ b/regress/unittests/authopt/testdata/sourceaddr.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJ54qqoPs87gtjN1aJoLUn7ZTYUtcaGxkzLyJvRkYG7nAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAALgAAAA5zb3VyY2UtYWRkcmVzcwAAABgAAAAUMTI3LjAuMC4xLzMyLDo6MS8xMjgAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEAppSUKQ/a9tw/HgIazWceCO3d48GU7mkV4iQMpWWs2nB1dFryY1GDtZrBggAjMviwmBXyM3jIk5vxJDINZXGQJ user key
diff --git a/regress/unittests/authopt/testdata/unknown_critical.cert b/regress/unittests/authopt/testdata/unknown_critical.cert
new file mode 100644
index 00000000..216960ab
--- /dev/null
+++ b/regress/unittests/authopt/testdata/unknown_critical.cert
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIIjs/wRAB/p5QShSfqoU9cWnCLT3lSveUirk61A27KxVAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAEwAAAARibGFoAAAABwAAAANmb28AAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEDix3FV7JIBuHNAwtZOVIqGBq8lqhnEwP51DqPA43qt+Tzynm56EWxuFzgGehBPF3L8gl+fVqxIJmiQ9iHB0LUD user key
diff --git a/regress/unittests/authopt/tests.c b/regress/unittests/authopt/tests.c
new file mode 100644
index 00000000..0e8aacb9
--- /dev/null
+++ b/regress/unittests/authopt/tests.c
@@ -0,0 +1,573 @@
+/* $OpenBSD: tests.c,v 1.1 2018/03/03 03:16:17 djm Exp $ */
+
+/*
+ * Regress test for keys options functions.
+ *
+ * Placed in the public domain
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "test_helper.h"
+
+#include "sshkey.h"
+#include "authfile.h"
+#include "auth-options.h"
+#include "misc.h"
+#include "log.h"
+
+static struct sshkey *
+load_key(const char *name)
+{
+ struct sshkey *ret;
+ int r;
+
+ r = sshkey_load_public(test_data_file(name), &ret, NULL);
+ ASSERT_INT_EQ(r, 0);
+ ASSERT_PTR_NE(ret, NULL);
+ return ret;
+}
+
+static struct sshauthopt *
+default_authkey_opts(void)
+{
+ struct sshauthopt *ret = sshauthopt_new();
+
+ ASSERT_PTR_NE(ret, NULL);
+ ret->permit_port_forwarding_flag = 1;
+ ret->permit_agent_forwarding_flag = 1;
+ ret->permit_x11_forwarding_flag = 1;
+ ret->permit_pty_flag = 1;
+ ret->permit_user_rc = 1;
+ return ret;
+}
+
+static struct sshauthopt *
+default_authkey_restrict_opts(void)
+{
+ struct sshauthopt *ret = sshauthopt_new();
+
+ ASSERT_PTR_NE(ret, NULL);
+ ret->permit_port_forwarding_flag = 0;
+ ret->permit_agent_forwarding_flag = 0;
+ ret->permit_x11_forwarding_flag = 0;
+ ret->permit_pty_flag = 0;
+ ret->permit_user_rc = 0;
+ ret->restricted = 1;
+ return ret;
+}
+
+static char **
+commasplit(const char *s, size_t *np)
+{
+ char *ocp, *cp, *cp2, **ret = NULL;
+ size_t n;
+
+ ocp = cp = strdup(s);
+ ASSERT_PTR_NE(cp, NULL);
+ for (n = 0; (cp2 = strsep(&cp, ",")) != NULL;) {
+ ret = recallocarray(ret, n, n + 1, sizeof(*ret));
+ ASSERT_PTR_NE(ret, NULL);
+ cp2 = strdup(cp2);
+ ASSERT_PTR_NE(cp2, NULL);
+ ret[n++] = cp2;
+ }
+ free(ocp);
+ *np = n;
+ return ret;
+}
+
+static void
+compare_opts(const struct sshauthopt *opts,
+ const struct sshauthopt *expected)
+{
+ size_t i;
+
+ ASSERT_PTR_NE(opts, NULL);
+ ASSERT_PTR_NE(expected, NULL);
+ ASSERT_PTR_NE(expected, opts); /* bozo :) */
+
+#define FLAG_EQ(x) ASSERT_INT_EQ(opts->x, expected->x)
+ FLAG_EQ(permit_port_forwarding_flag);
+ FLAG_EQ(permit_agent_forwarding_flag);
+ FLAG_EQ(permit_x11_forwarding_flag);
+ FLAG_EQ(permit_pty_flag);
+ FLAG_EQ(permit_user_rc);
+ FLAG_EQ(restricted);
+ FLAG_EQ(cert_authority);
+#undef FLAG_EQ
+
+#define STR_EQ(x) \
+ do { \
+ if (expected->x == NULL) \
+ ASSERT_PTR_EQ(opts->x, expected->x); \
+ else \
+ ASSERT_STRING_EQ(opts->x, expected->x); \
+ } while (0)
+ STR_EQ(cert_principals);
+ STR_EQ(force_command);
+ STR_EQ(required_from_host_cert);
+ STR_EQ(required_from_host_keys);
+#undef STR_EQ
+
+#define ARRAY_EQ(nx, x) \
+ do { \
+ ASSERT_SIZE_T_EQ(opts->nx, expected->nx); \
+ if (expected->nx == 0) \
+ break; \
+ for (i = 0; i < expected->nx; i++) \
+ ASSERT_STRING_EQ(opts->x[i], expected->x[i]); \
+ } while (0)
+ ARRAY_EQ(nenv, env);
+ ARRAY_EQ(npermitopen, permitopen);
+#undef ARRAY_EQ
+}
+
+static void
+test_authkeys_parse(void)
+{
+ struct sshauthopt *opts, *expected;
+ const char *errstr;
+
+#define FAIL_TEST(label, keywords) \
+ do { \
+ TEST_START("sshauthopt_parse invalid " label); \
+ opts = sshauthopt_parse(keywords, &errstr); \
+ ASSERT_PTR_EQ(opts, NULL); \
+ ASSERT_PTR_NE(errstr, NULL); \
+ TEST_DONE(); \
+ } while (0)
+#define CHECK_SUCCESS_AND_CLEANUP() \
+ do { \
+ if (errstr != NULL) \
+ ASSERT_STRING_EQ(errstr, ""); \
+ compare_opts(opts, expected); \
+ sshauthopt_free(expected); \
+ sshauthopt_free(opts); \
+ } while (0)
+
+ /* Basic tests */
+ TEST_START("sshauthopt_parse empty");
+ expected = default_authkey_opts();
+ opts = sshauthopt_parse("", &errstr);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ TEST_START("sshauthopt_parse trailing whitespace");
+ expected = default_authkey_opts();
+ opts = sshauthopt_parse(" ", &errstr);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ TEST_START("sshauthopt_parse restrict");
+ expected = default_authkey_restrict_opts();
+ opts = sshauthopt_parse("restrict", &errstr);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ /* Invalid syntax */
+ FAIL_TEST("trailing comma", "restrict,");
+ FAIL_TEST("bare comma", ",");
+ FAIL_TEST("unknown option", "BLAH");
+ FAIL_TEST("unknown option with trailing comma", "BLAH,");
+ FAIL_TEST("unknown option with trailing whitespace", "BLAH ");
+
+ /* force_tun_device */
+ TEST_START("sshauthopt_parse tunnel explicit");
+ expected = default_authkey_opts();
+ expected->force_tun_device = 1;
+ opts = sshauthopt_parse("tunnel=\"1\"", &errstr);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ TEST_START("sshauthopt_parse tunnel any");
+ expected = default_authkey_opts();
+ expected->force_tun_device = SSH_TUNID_ANY;
+ opts = sshauthopt_parse("tunnel=\"any\"", &errstr);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ FAIL_TEST("tunnel", "tunnel=\"blah\"");
+
+ /* Flag options */
+#define FLAG_TEST(keyword, var, val) \
+ do { \
+ TEST_START("sshauthopt_parse " keyword); \
+ expected = default_authkey_opts(); \
+ expected->var = val; \
+ opts = sshauthopt_parse(keyword, &errstr); \
+ CHECK_SUCCESS_AND_CLEANUP(); \
+ expected = default_authkey_restrict_opts(); \
+ expected->var = val; \
+ opts = sshauthopt_parse("restrict,"keyword, &errstr); \
+ CHECK_SUCCESS_AND_CLEANUP(); \
+ TEST_DONE(); \
+ } while (0)
+ /* Positive flags */
+ FLAG_TEST("cert-authority", cert_authority, 1);
+ FLAG_TEST("port-forwarding", permit_port_forwarding_flag, 1);
+ FLAG_TEST("agent-forwarding", permit_agent_forwarding_flag, 1);
+ FLAG_TEST("x11-forwarding", permit_x11_forwarding_flag, 1);
+ FLAG_TEST("pty", permit_pty_flag, 1);
+ FLAG_TEST("user-rc", permit_user_rc, 1);
+ /* Negative flags */
+ FLAG_TEST("no-port-forwarding", permit_port_forwarding_flag, 0);
+ FLAG_TEST("no-agent-forwarding", permit_agent_forwarding_flag, 0);
+ FLAG_TEST("no-x11-forwarding", permit_x11_forwarding_flag, 0);
+ FLAG_TEST("no-pty", permit_pty_flag, 0);
+ FLAG_TEST("no-user-rc", permit_user_rc, 0);
+#undef FLAG_TEST
+ FAIL_TEST("no-cert-authority", "no-cert-authority");
+
+ /* String options */
+#define STRING_TEST(keyword, var, val) \
+ do { \
+ TEST_START("sshauthopt_parse " keyword); \
+ expected = default_authkey_opts(); \
+ expected->var = strdup(val); \
+ ASSERT_PTR_NE(expected->var, NULL); \
+ opts = sshauthopt_parse(keyword "=" #val, &errstr); \
+ CHECK_SUCCESS_AND_CLEANUP(); \
+ expected = default_authkey_restrict_opts(); \
+ expected->var = strdup(val); \
+ ASSERT_PTR_NE(expected->var, NULL); \
+ opts = sshauthopt_parse( \
+ "restrict," keyword "=" #val ",restrict", &errstr); \
+ CHECK_SUCCESS_AND_CLEANUP(); \
+ TEST_DONE(); \
+ } while (0)
+ STRING_TEST("command", force_command, "/bin/true");
+ STRING_TEST("principals", cert_principals, "gregor,josef,K");
+ STRING_TEST("from", required_from_host_keys, "127.0.0.0/8");
+#undef STRING_TEST
+ FAIL_TEST("unquoted command", "command=oops");
+ FAIL_TEST("unquoted principals", "principals=estragon");
+ FAIL_TEST("unquoted from", "from=127.0.0.1");
+
+ /* String array option tests */
+#define ARRAY_TEST(label, keywords, var, nvar, val) \
+ do { \
+ TEST_START("sshauthopt_parse " label); \
+ expected = default_authkey_opts(); \
+ expected->var = commasplit(val, &expected->nvar); \
+ ASSERT_PTR_NE(expected->var, NULL); \
+ opts = sshauthopt_parse(keywords, &errstr); \
+ CHECK_SUCCESS_AND_CLEANUP(); \
+ expected = default_authkey_restrict_opts(); \
+ expected->var = commasplit(val, &expected->nvar); \
+ ASSERT_PTR_NE(expected->var, NULL); \
+ opts = sshauthopt_parse( \
+ "restrict," keywords ",restrict", &errstr); \
+ CHECK_SUCCESS_AND_CLEANUP(); \
+ TEST_DONE(); \
+ } while (0)
+ ARRAY_TEST("environment", "environment=\"foo=1\",environment=\"bar=2\"",
+ env, nenv, "foo=1,bar=2");
+ ARRAY_TEST("permitopen", "permitopen=\"foo:123\",permitopen=\"bar:*\"",
+ permitopen, npermitopen, "foo:123,bar:*");
+#undef ARRAY_TEST
+ FAIL_TEST("environment", "environment=\",=bah\"");
+ FAIL_TEST("permitopen port", "foo:bar");
+ FAIL_TEST("permitopen missing port", "foo:");
+ FAIL_TEST("permitopen missing port specification", "foo");
+ FAIL_TEST("permitopen invalid host", "[:");
+
+#undef CHECK_SUCCESS_AND_CLEANUP
+#undef FAIL_TEST
+}
+
+static void
+test_cert_parse(void)
+{
+ struct sshkey *cert;
+ struct sshauthopt *opts, *expected;
+
+#define CHECK_SUCCESS_AND_CLEANUP() \
+ do { \
+ compare_opts(opts, expected); \
+ sshauthopt_free(expected); \
+ sshauthopt_free(opts); \
+ sshkey_free(cert); \
+ } while (0)
+#define FLAG_TEST(keybase, var) \
+ do { \
+ TEST_START("sshauthopt_from_cert no_" keybase); \
+ cert = load_key("no_" keybase ".cert"); \
+ expected = default_authkey_opts(); \
+ expected->var = 0; \
+ opts = sshauthopt_from_cert(cert); \
+ CHECK_SUCCESS_AND_CLEANUP(); \
+ TEST_DONE(); \
+ TEST_START("sshauthopt_from_cert only_" keybase); \
+ cert = load_key("only_" keybase ".cert"); \
+ expected = sshauthopt_new(); \
+ ASSERT_PTR_NE(expected, NULL); \
+ expected->var = 1; \
+ opts = sshauthopt_from_cert(cert); \
+ CHECK_SUCCESS_AND_CLEANUP(); \
+ TEST_DONE(); \
+ } while (0)
+ FLAG_TEST("agentfwd", permit_agent_forwarding_flag);
+ FLAG_TEST("portfwd", permit_port_forwarding_flag);
+ FLAG_TEST("pty", permit_pty_flag);
+ FLAG_TEST("user_rc", permit_user_rc);
+ FLAG_TEST("x11fwd", permit_x11_forwarding_flag);
+#undef FLAG_TEST
+
+ TEST_START("sshauthopt_from_cert all permitted");
+ cert = load_key("all_permit.cert");
+ expected = default_authkey_opts();
+ opts = sshauthopt_from_cert(cert);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ TEST_START("sshauthopt_from_cert nothing permitted");
+ cert = load_key("no_permit.cert");
+ expected = sshauthopt_new();
+ ASSERT_PTR_NE(expected, NULL);
+ opts = sshauthopt_from_cert(cert);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ TEST_START("sshauthopt_from_cert force-command");
+ cert = load_key("force_command.cert");
+ expected = default_authkey_opts();
+ expected->force_command = strdup("foo");
+ ASSERT_PTR_NE(expected->force_command, NULL);
+ opts = sshauthopt_from_cert(cert);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ TEST_START("sshauthopt_from_cert source-address");
+ cert = load_key("sourceaddr.cert");
+ expected = default_authkey_opts();
+ expected->required_from_host_cert = strdup("127.0.0.1/32,::1/128");
+ ASSERT_PTR_NE(expected->required_from_host_cert, NULL);
+ opts = sshauthopt_from_cert(cert);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+#undef CHECK_SUCCESS_AND_CLEANUP
+
+#define FAIL_TEST(keybase) \
+ do { \
+ TEST_START("sshauthopt_from_cert " keybase); \
+ cert = load_key(keybase ".cert"); \
+ opts = sshauthopt_from_cert(cert); \
+ ASSERT_PTR_EQ(opts, NULL); \
+ sshkey_free(cert); \
+ TEST_DONE(); \
+ } while (0)
+ FAIL_TEST("host");
+ FAIL_TEST("bad_sourceaddr");
+ FAIL_TEST("unknown_critical");
+#undef FAIL_TEST
+}
+
+static void
+test_merge(void)
+{
+ struct sshkey *cert;
+ struct sshauthopt *key_opts, *cert_opts, *merge_opts, *expected;
+ const char *errstr;
+
+ /*
+ * Prepare for a test by making some key and cert options and
+ * attempting to merge them.
+ */
+#define PREPARE(label, keyname, keywords) \
+ do { \
+ expected = NULL; \
+ TEST_START("sshauthopt_merge " label); \
+ cert = load_key(keyname ".cert"); \
+ cert_opts = sshauthopt_from_cert(cert); \
+ ASSERT_PTR_NE(cert_opts, NULL); \
+ key_opts = sshauthopt_parse(keywords, &errstr); \
+ if (errstr != NULL) \
+ ASSERT_STRING_EQ(errstr, ""); \
+ ASSERT_PTR_NE(key_opts, NULL); \
+ merge_opts = sshauthopt_merge(key_opts, \
+ cert_opts, &errstr); \
+ } while (0)
+
+ /* Cleanup stuff allocated by PREPARE() */
+#define CLEANUP() \
+ do { \
+ sshauthopt_free(expected); \
+ sshauthopt_free(merge_opts); \
+ sshauthopt_free(key_opts); \
+ sshauthopt_free(cert_opts); \
+ sshkey_free(cert); \
+ } while (0)
+
+ /* Check the results of PREPARE() against expectation; calls CLEANUP */
+#define CHECK_SUCCESS_AND_CLEANUP() \
+ do { \
+ if (errstr != NULL) \
+ ASSERT_STRING_EQ(errstr, ""); \
+ compare_opts(merge_opts, expected); \
+ CLEANUP(); \
+ } while (0)
+
+ /* Check a single case of merging of flag options */
+#define FLAG_CASE(keybase, label, keyname, keywords, mostly_off, var, val) \
+ do { \
+ PREPARE(keybase " " label, keyname, keywords); \
+ expected = mostly_off ? \
+ sshauthopt_new() : default_authkey_opts(); \
+ expected->var = val; \
+ ASSERT_PTR_NE(expected, NULL); \
+ CHECK_SUCCESS_AND_CLEANUP(); \
+ TEST_DONE(); \
+ } while (0)
+
+ /*
+ * Fairly exhaustive exercise of a flag option. Tests
+ * option both set and clear in certificate, set and clear in
+ * authorized_keys and set and cleared via restrict keyword.
+ */
+#define FLAG_TEST(keybase, keyword, var) \
+ do { \
+ FLAG_CASE(keybase, "keys:default,yes cert:default,no", \
+ "no_" keybase, keyword, 0, var, 0); \
+ FLAG_CASE(keybase,"keys:-*,yes cert:default,no", \
+ "no_" keybase, "restrict," keyword, 1, var, 0); \
+ FLAG_CASE(keybase, "keys:default,no cert:default,no", \
+ "no_" keybase, "no-" keyword, 0, var, 0); \
+ FLAG_CASE(keybase, "keys:-*,no cert:default,no", \
+ "no_" keybase, "restrict,no-" keyword, 1, var, 0); \
+ \
+ FLAG_CASE(keybase, "keys:default,yes cert:-*,yes", \
+ "only_" keybase, keyword, 1, var, 1); \
+ FLAG_CASE(keybase,"keys:-*,yes cert:-*,yes", \
+ "only_" keybase, "restrict," keyword, 1, var, 1); \
+ FLAG_CASE(keybase, "keys:default,no cert:-*,yes", \
+ "only_" keybase, "no-" keyword, 1, var, 0); \
+ FLAG_CASE(keybase, "keys:-*,no cert:-*,yes", \
+ "only_" keybase, "restrict,no-" keyword, 1, var, 0); \
+ \
+ FLAG_CASE(keybase, "keys:default,yes cert:-*", \
+ "no_permit", keyword, 1, var, 0); \
+ FLAG_CASE(keybase,"keys:-*,yes cert:-*", \
+ "no_permit", "restrict," keyword, 1, var, 0); \
+ FLAG_CASE(keybase, "keys:default,no cert:-*", \
+ "no_permit", "no-" keyword, 1, var, 0); \
+ FLAG_CASE(keybase, "keys:-*,no cert:-*", \
+ "no_permit", "restrict,no-" keyword, 1, var, 0); \
+ \
+ FLAG_CASE(keybase, "keys:default,yes cert:*", \
+ "all_permit", keyword, 0, var, 1); \
+ FLAG_CASE(keybase,"keys:-*,yes cert:*", \
+ "all_permit", "restrict," keyword, 1, var, 1); \
+ FLAG_CASE(keybase, "keys:default,no cert:*", \
+ "all_permit", "no-" keyword, 0, var, 0); \
+ FLAG_CASE(keybase, "keys:-*,no cert:*", \
+ "all_permit", "restrict,no-" keyword, 1, var, 0); \
+ \
+ } while (0)
+ FLAG_TEST("portfwd", "port-forwarding", permit_port_forwarding_flag);
+ FLAG_TEST("agentfwd", "agent-forwarding", permit_agent_forwarding_flag);
+ FLAG_TEST("pty", "pty", permit_pty_flag);
+ FLAG_TEST("user_rc", "user-rc", permit_user_rc);
+ FLAG_TEST("x11fwd", "x11-forwarding", permit_x11_forwarding_flag);
+#undef FLAG_TEST
+
+ PREPARE("source-address both", "sourceaddr", "from=\"127.0.0.1\"");
+ expected = default_authkey_opts();
+ expected->required_from_host_cert = strdup("127.0.0.1/32,::1/128");
+ ASSERT_PTR_NE(expected->required_from_host_cert, NULL);
+ expected->required_from_host_keys = strdup("127.0.0.1");
+ ASSERT_PTR_NE(expected->required_from_host_keys, NULL);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ PREPARE("source-address none", "all_permit", "");
+ expected = default_authkey_opts();
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ PREPARE("source-address keys", "all_permit", "from=\"127.0.0.1\"");
+ expected = default_authkey_opts();
+ expected->required_from_host_keys = strdup("127.0.0.1");
+ ASSERT_PTR_NE(expected->required_from_host_keys, NULL);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ PREPARE("source-address cert", "sourceaddr", "");
+ expected = default_authkey_opts();
+ expected->required_from_host_cert = strdup("127.0.0.1/32,::1/128");
+ ASSERT_PTR_NE(expected->required_from_host_cert, NULL);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ PREPARE("force-command both", "force_command", "command=\"foo\"");
+ expected = default_authkey_opts();
+ expected->force_command = strdup("foo");
+ ASSERT_PTR_NE(expected->force_command, NULL);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ PREPARE("force-command none", "all_permit", "");
+ expected = default_authkey_opts();
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ PREPARE("force-command keys", "all_permit", "command=\"bar\"");
+ expected = default_authkey_opts();
+ expected->force_command = strdup("bar");
+ ASSERT_PTR_NE(expected->force_command, NULL);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ PREPARE("force-command cert", "force_command", "");
+ expected = default_authkey_opts();
+ expected->force_command = strdup("foo");
+ ASSERT_PTR_NE(expected->force_command, NULL);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ PREPARE("force-command mismatch", "force_command", "command=\"bar\"");
+ ASSERT_PTR_EQ(merge_opts, NULL);
+ CLEANUP();
+ TEST_DONE();
+
+ PREPARE("tunnel", "all_permit", "tunnel=\"6\"");
+ expected = default_authkey_opts();
+ expected->force_tun_device = 6;
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ PREPARE("permitopen", "all_permit",
+ "permitopen=\"127.0.0.1:*\",permitopen=\"127.0.0.1:123\"");
+ expected = default_authkey_opts();
+ expected->permitopen = commasplit("127.0.0.1:*,127.0.0.1:123",
+ &expected->npermitopen);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+
+ PREPARE("environment", "all_permit",
+ "environment=\"foo=a\",environment=\"bar=b\"");
+ expected = default_authkey_opts();
+ expected->env = commasplit("foo=a,bar=b", &expected->nenv);
+ CHECK_SUCCESS_AND_CLEANUP();
+ TEST_DONE();
+}
+
+void
+tests(void)
+{
+ extern char *__progname;
+ LogLevel ll = test_is_verbose() ?
+ SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_QUIET;
+
+ /* test_cert_parse() are a bit spammy to error() by default... */
+ log_init(__progname, ll, SYSLOG_FACILITY_USER, 1);
+
+ test_authkeys_parse();
+ test_cert_parse();
+ test_merge();
+}
diff --git a/regress/unittests/bitmap/Makefile b/regress/unittests/bitmap/Makefile
new file mode 100644
index 00000000..fe30acc7
--- /dev/null
+++ b/regress/unittests/bitmap/Makefile
@@ -0,0 +1,14 @@
+# $OpenBSD: Makefile,v 1.4 2017/12/21 00:41:22 djm Exp $
+
+PROG=test_bitmap
+SRCS=tests.c
+
+# From usr.sbin/ssh
+SRCS+=bitmap.c atomicio.c
+
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG}
+
+.include <bsd.regress.mk>
diff --git a/regress/unittests/bitmap/tests.c b/regress/unittests/bitmap/tests.c
new file mode 100644
index 00000000..f66a4ce4
--- /dev/null
+++ b/regress/unittests/bitmap/tests.c
@@ -0,0 +1,139 @@
+/* $OpenBSD: tests.c,v 1.1 2015/01/15 07:36:28 djm Exp $ */
+/*
+ * Regress test for bitmap.h bitmap API
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef WITH_OPENSSL
+#include <openssl/bn.h>
+#endif
+
+#include "../test_helper/test_helper.h"
+
+#include "bitmap.h"
+
+#define NTESTS 131
+
+void
+tests(void)
+{
+#ifdef WITH_OPENSSL
+ struct bitmap *b;
+ BIGNUM *bn;
+ size_t len;
+ int i, j, k, n;
+ u_char bbuf[1024], bnbuf[1024];
+ int r;
+
+ TEST_START("bitmap_new");
+ b = bitmap_new();
+ ASSERT_PTR_NE(b, NULL);
+ bn = BN_new();
+ ASSERT_PTR_NE(bn, NULL);
+ TEST_DONE();
+
+ TEST_START("bitmap_set_bit / bitmap_test_bit");
+ for (i = -1; i < NTESTS; i++) {
+ for (j = -1; j < NTESTS; j++) {
+ for (k = -1; k < NTESTS; k++) {
+ bitmap_zero(b);
+ BN_clear(bn);
+
+ test_subtest_info("set %d/%d/%d", i, j, k);
+ /* Set bits */
+ if (i >= 0) {
+ ASSERT_INT_EQ(bitmap_set_bit(b, i), 0);
+ ASSERT_INT_EQ(BN_set_bit(bn, i), 1);
+ }
+ if (j >= 0) {
+ ASSERT_INT_EQ(bitmap_set_bit(b, j), 0);
+ ASSERT_INT_EQ(BN_set_bit(bn, j), 1);
+ }
+ if (k >= 0) {
+ ASSERT_INT_EQ(bitmap_set_bit(b, k), 0);
+ ASSERT_INT_EQ(BN_set_bit(bn, k), 1);
+ }
+
+ /* Check perfect match between bitmap and bn */
+ test_subtest_info("match %d/%d/%d", i, j, k);
+ for (n = 0; n < NTESTS; n++) {
+ ASSERT_INT_EQ(BN_is_bit_set(bn, n),
+ bitmap_test_bit(b, n));
+ }
+
+ /* Test length calculations */
+ test_subtest_info("length %d/%d/%d", i, j, k);
+ ASSERT_INT_EQ(BN_num_bits(bn),
+ (int)bitmap_nbits(b));
+ ASSERT_INT_EQ(BN_num_bytes(bn),
+ (int)bitmap_nbytes(b));
+
+ /* Test serialisation */
+ test_subtest_info("serialise %d/%d/%d",
+ i, j, k);
+ len = bitmap_nbytes(b);
+ memset(bbuf, 0xfc, sizeof(bbuf));
+ ASSERT_INT_EQ(bitmap_to_string(b, bbuf,
+ sizeof(bbuf)), 0);
+ for (n = len; n < (int)sizeof(bbuf); n++)
+ ASSERT_U8_EQ(bbuf[n], 0xfc);
+ r = BN_bn2bin(bn, bnbuf);
+ ASSERT_INT_GE(r, 0);
+ ASSERT_INT_EQ(r, (int)len);
+ ASSERT_MEM_EQ(bbuf, bnbuf, len);
+
+ /* Test deserialisation */
+ test_subtest_info("deserialise %d/%d/%d",
+ i, j, k);
+ bitmap_zero(b);
+ ASSERT_INT_EQ(bitmap_from_string(b, bnbuf,
+ len), 0);
+ for (n = 0; n < NTESTS; n++) {
+ ASSERT_INT_EQ(BN_is_bit_set(bn, n),
+ bitmap_test_bit(b, n));
+ }
+
+ /* Test clearing bits */
+ test_subtest_info("clear %d/%d/%d",
+ i, j, k);
+ for (n = 0; n < NTESTS; n++) {
+ ASSERT_INT_EQ(bitmap_set_bit(b, n), 0);
+ ASSERT_INT_EQ(BN_set_bit(bn, n), 1);
+ }
+ if (i >= 0) {
+ bitmap_clear_bit(b, i);
+ BN_clear_bit(bn, i);
+ }
+ if (j >= 0) {
+ bitmap_clear_bit(b, j);
+ BN_clear_bit(bn, j);
+ }
+ if (k >= 0) {
+ bitmap_clear_bit(b, k);
+ BN_clear_bit(bn, k);
+ }
+ for (n = 0; n < NTESTS; n++) {
+ ASSERT_INT_EQ(BN_is_bit_set(bn, n),
+ bitmap_test_bit(b, n));
+ }
+ }
+ }
+ }
+ bitmap_free(b);
+ BN_free(bn);
+ TEST_DONE();
+#endif
+}
+
diff --git a/regress/unittests/conversion/Makefile b/regress/unittests/conversion/Makefile
new file mode 100644
index 00000000..8b2a09cc
--- /dev/null
+++ b/regress/unittests/conversion/Makefile
@@ -0,0 +1,15 @@
+# $OpenBSD: Makefile,v 1.2 2017/12/21 00:41:22 djm Exp $
+
+PROG=test_conversion
+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
+
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG}
+
+.include <bsd.regress.mk>
diff --git a/regress/unittests/conversion/tests.c b/regress/unittests/conversion/tests.c
new file mode 100644
index 00000000..ae1154d4
--- /dev/null
+++ b/regress/unittests/conversion/tests.c
@@ -0,0 +1,53 @@
+/* $OpenBSD: tests.c,v 1.2 2019/06/14 04:03:48 djm Exp $ */
+/*
+ * Regress test for conversions
+ *
+ * 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 "misc.h"
+
+void
+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);
+ /* 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);
+
+ /* negative time is not allowed */
+ ASSERT_LONG_EQ(convtime("-7"), -1);
+ ASSERT_LONG_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);
+
+ /* 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);
+ TEST_DONE();
+}
diff --git a/regress/unittests/hostkeys/Makefile b/regress/unittests/hostkeys/Makefile
new file mode 100644
index 00000000..d841d96b
--- /dev/null
+++ b/regress/unittests/hostkeys/Makefile
@@ -0,0 +1,25 @@
+# $OpenBSD: Makefile,v 1.8 2020/04/06 09:43:56 dtucker Exp $
+
+PROG=test_hostkeys
+SRCS=tests.c test_iterate.c
+
+# From usr.bin/ssh
+SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
+SRCS+=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+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
+SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c
+SRCS+=ssh-ed25519-sk.c sk-usbhid.c
+
+SRCS+=digest-openssl.c
+#SRCS+=digest-libc.c
+SRCS+=utf8.c
+
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata
+
+.include <bsd.regress.mk>
diff --git a/regress/unittests/hostkeys/mktestdata.sh b/regress/unittests/hostkeys/mktestdata.sh
new file mode 100644
index 00000000..5a46de99
--- /dev/null
+++ b/regress/unittests/hostkeys/mktestdata.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+# $OpenBSD: mktestdata.sh,v 1.2 2017/04/30 23:33:48 djm Exp $
+
+set -ex
+
+cd testdata
+
+rm -f rsa* dsa* ecdsa* ed25519*
+rm -f known_hosts*
+
+gen_all() {
+ _n=$1
+ _ecdsa_bits=256
+ test "x$_n" = "x1" && _ecdsa_bits=384
+ test "x$_n" = "x2" && _ecdsa_bits=521
+ ssh-keygen -qt rsa -b 1024 -C "RSA #$_n" -N "" -f rsa_$_n
+ ssh-keygen -qt dsa -b 1024 -C "DSA #$_n" -N "" -f dsa_$_n
+ ssh-keygen -qt ecdsa -b $_ecdsa_bits -C "ECDSA #$_n" -N "" -f ecdsa_$_n
+ ssh-keygen -qt ed25519 -C "ED25519 #$_n" -N "" -f ed25519_$_n
+ # Don't need private keys
+ rm -f rsa_$_n dsa_$_n ecdsa_$_n ed25519_$_n
+}
+
+hentries() {
+ _preamble=$1
+ _kspec=$2
+ for k in `ls -1 $_kspec | sort` ; do
+ printf "$_preamble "
+ cat $k
+ done
+ echo
+}
+
+gen_all 1
+gen_all 2
+gen_all 3
+gen_all 4
+gen_all 5
+gen_all 6
+
+# A section of known_hosts with hashed hostnames.
+(
+ hentries "sisyphus.example.com" "*_5.pub"
+ hentries "prometheus.example.com,192.0.2.1,2001:db8::1" "*_6.pub"
+) > known_hosts_hash_frag
+ssh-keygen -Hf known_hosts_hash_frag
+rm -f known_hosts_hash_frag.old
+
+# Populated known_hosts, including comments, hashed names and invalid lines
+(
+ echo "# Plain host keys, plain host names"
+ hentries "sisyphus.example.com" "*_1.pub"
+
+ echo "# Plain host keys, hostnames + addresses"
+ hentries "prometheus.example.com,192.0.2.1,2001:db8::1" "*_2.pub"
+
+ echo "# Some hosts with wildcard names / IPs"
+ hentries "*.example.com,192.0.2.*,2001:*" "*_3.pub"
+
+ echo "# Hashed hostname and address entries"
+ cat known_hosts_hash_frag
+ rm -f known_hosts_hash_frag
+ echo
+
+ echo "# Revoked and CA keys"
+ printf "@revoked sisyphus.example.com " ; cat ed25519_4.pub
+ printf "@cert-authority prometheus.example.com " ; cat ecdsa_4.pub
+ printf "@cert-authority *.example.com " ; cat dsa_4.pub
+
+ printf "\n"
+ echo "# Some invalid lines"
+ # Invalid marker
+ printf "@what sisyphus.example.com " ; cat dsa_1.pub
+ # Key missing
+ echo "sisyphus.example.com "
+ # Key blob missing
+ echo "prometheus.example.com ssh-ed25519 "
+ # Key blob truncated
+ echo "sisyphus.example.com ssh-dsa AAAATgAAAAdz"
+ # Invalid type
+ echo "sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg=="
+ # Type mismatch with blob
+ echo "prometheus.example.com ssh-rsa AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg=="
+) > known_hosts
+
+echo OK
diff --git a/regress/unittests/hostkeys/test_iterate.c b/regress/unittests/hostkeys/test_iterate.c
new file mode 100644
index 00000000..5904121e
--- /dev/null
+++ b/regress/unittests/hostkeys/test_iterate.c
@@ -0,0 +1,1065 @@
+/* $OpenBSD: test_iterate.c,v 1.6 2018/07/16 03:09:59 djm Exp $ */
+/*
+ * Regress test for hostfile.h hostkeys_foreach()
+ *
+ * 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 "sshkey.h"
+#include "authfile.h"
+#include "hostfile.h"
+
+struct expected {
+ const char *key_file; /* Path for key, NULL for none */
+ int no_parse_status; /* Expected status w/o key parsing */
+ int no_parse_keytype; /* Expected keytype w/o key parsing */
+ int match_host_p; /* Match 'prometheus.example.com' */
+ int match_host_s; /* Match 'sisyphus.example.com' */
+ int match_ipv4; /* Match '192.0.2.1' */
+ int match_ipv6; /* Match '2001:db8::1' */
+ int match_flags; /* Expected flags from match */
+ struct hostkey_foreach_line l; /* Expected line contents */
+};
+
+struct cbctx {
+ const struct expected *expected;
+ size_t nexpected;
+ size_t i;
+ int flags;
+ int match_host_p;
+ int match_host_s;
+ int match_ipv4;
+ int match_ipv6;
+};
+
+/*
+ * hostkeys_foreach() iterator callback that verifies the line passed
+ * against an array of expected entries.
+ */
+static int
+check(struct hostkey_foreach_line *l, void *_ctx)
+{
+ struct cbctx *ctx = (struct cbctx *)_ctx;
+ const struct expected *expected;
+ int parse_key = (ctx->flags & HKF_WANT_PARSE_KEY) != 0;
+ const int matching = (ctx->flags & HKF_WANT_MATCH) != 0;
+ u_int expected_status, expected_match;
+ int expected_keytype, skip = 0;
+
+ test_subtest_info("entry %zu/%zu, file line %ld",
+ ctx->i + 1, ctx->nexpected, l->linenum);
+
+ for (;;) {
+ ASSERT_SIZE_T_LT(ctx->i, ctx->nexpected);
+ expected = ctx->expected + ctx->i++;
+ /* If we are matching host/IP then skip entries that don't */
+ if (!matching)
+ break;
+ if (ctx->match_host_p && expected->match_host_p)
+ break;
+ if (ctx->match_host_s && expected->match_host_s)
+ break;
+ if (ctx->match_ipv4 && expected->match_ipv4)
+ break;
+ if (ctx->match_ipv6 && expected->match_ipv6)
+ break;
+ }
+ expected_status = (parse_key || expected->no_parse_status < 0) ?
+ expected->l.status : (u_int)expected->no_parse_status;
+ expected_match = expected->l.match;
+#define UPDATE_MATCH_STATUS(x) do { \
+ if (ctx->x && expected->x) { \
+ expected_match |= expected->x; \
+ if (expected_status == HKF_STATUS_OK) \
+ expected_status = HKF_STATUS_MATCHED; \
+ } \
+ } while (0)
+ expected_keytype = (parse_key || expected->no_parse_keytype < 0) ?
+ expected->l.keytype : expected->no_parse_keytype;
+
+#ifndef OPENSSL_HAS_ECC
+ if (expected->l.keytype == KEY_ECDSA ||
+ expected->no_parse_keytype == KEY_ECDSA)
+ skip = 1;
+#endif /* OPENSSL_HAS_ECC */
+#ifndef WITH_OPENSSL
+ if (expected->l.keytype == KEY_DSA ||
+ expected->no_parse_keytype == KEY_DSA ||
+ expected->l.keytype == KEY_RSA ||
+ expected->no_parse_keytype == KEY_RSA ||
+ expected->l.keytype == KEY_ECDSA ||
+ expected->no_parse_keytype == KEY_ECDSA)
+ skip = 1;
+#endif /* WITH_OPENSSL */
+ if (skip) {
+ expected_status = HKF_STATUS_INVALID;
+ expected_keytype = KEY_UNSPEC;
+ parse_key = 0;
+ }
+ UPDATE_MATCH_STATUS(match_host_p);
+ UPDATE_MATCH_STATUS(match_host_s);
+ UPDATE_MATCH_STATUS(match_ipv4);
+ UPDATE_MATCH_STATUS(match_ipv6);
+
+ ASSERT_PTR_NE(l->path, NULL); /* Don't care about path */
+ ASSERT_LONG_LONG_EQ(l->linenum, expected->l.linenum);
+ ASSERT_U_INT_EQ(l->status, expected_status);
+ ASSERT_U_INT_EQ(l->match, expected_match);
+ /* Not all test entries contain fulltext */
+ if (expected->l.line != NULL)
+ ASSERT_STRING_EQ(l->line, expected->l.line);
+ ASSERT_INT_EQ(l->marker, expected->l.marker);
+ /* XXX we skip hashed hostnames for now; implement checking */
+ if (expected->l.hosts != NULL)
+ ASSERT_STRING_EQ(l->hosts, expected->l.hosts);
+ /* Not all test entries contain raw keys */
+ if (expected->l.rawkey != NULL)
+ ASSERT_STRING_EQ(l->rawkey, expected->l.rawkey);
+ /* XXX synthesise raw key for cases lacking and compare */
+ ASSERT_INT_EQ(l->keytype, expected_keytype);
+ if (parse_key) {
+ if (expected->l.key == NULL)
+ ASSERT_PTR_EQ(l->key, NULL);
+ if (expected->l.key != NULL) {
+ ASSERT_PTR_NE(l->key, NULL);
+ ASSERT_INT_EQ(sshkey_equal(l->key, expected->l.key), 1);
+ }
+ }
+ if (parse_key && !(l->comment == NULL && expected->l.comment == NULL))
+ ASSERT_STRING_EQ(l->comment, expected->l.comment);
+ return 0;
+}
+
+/* Loads public keys for a set of expected results */
+static void
+prepare_expected(struct expected *expected, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ if (expected[i].key_file == NULL)
+ continue;
+#ifndef OPENSSL_HAS_ECC
+ if (expected[i].l.keytype == KEY_ECDSA)
+ continue;
+#endif /* OPENSSL_HAS_ECC */
+#ifndef WITH_OPENSSL
+ switch (expected[i].l.keytype) {
+ case KEY_RSA:
+ case KEY_DSA:
+ case KEY_ECDSA:
+ continue;
+ }
+#endif /* WITH_OPENSSL */
+ ASSERT_INT_EQ(sshkey_load_public(
+ test_data_file(expected[i].key_file), &expected[i].l.key,
+ NULL), 0);
+ }
+}
+
+static void
+cleanup_expected(struct expected *expected, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ sshkey_free(expected[i].l.key);
+ expected[i].l.key = NULL;
+ }
+}
+
+struct expected expected_full[] = {
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL, /* path, don't care */
+ 1, /* line number */
+ HKF_STATUS_COMMENT, /* status */
+ 0, /* match flags */
+ "# Plain host keys, plain host names", /* full line, optional */
+ MRK_NONE, /* marker (CA / revoked) */
+ NULL, /* hosts text */
+ NULL, /* raw key, optional */
+ KEY_UNSPEC, /* key type */
+ NULL, /* deserialised key */
+ NULL, /* comment */
+ } },
+ { "dsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 2,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #1",
+ } },
+ { "ecdsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 3,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #1",
+ } },
+ { "ed25519_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 4,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #1",
+ } },
+ { "rsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 5,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #1",
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 6,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 7,
+ HKF_STATUS_COMMENT,
+ 0,
+ "# Plain host keys, hostnames + addresses",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { "dsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 8,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com,192.0.2.1,2001:db8::1",
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #2",
+ } },
+ { "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 9,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com,192.0.2.1,2001:db8::1",
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #2",
+ } },
+ { "ed25519_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 10,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com,192.0.2.1,2001:db8::1",
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #2",
+ } },
+ { "rsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 11,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com,192.0.2.1,2001:db8::1",
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #2",
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 12,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 13,
+ HKF_STATUS_COMMENT,
+ 0,
+ "# Some hosts with wildcard names / IPs",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { "dsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 14,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "*.example.com,192.0.2.*,2001:*",
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #3",
+ } },
+ { "ecdsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 15,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "*.example.com,192.0.2.*,2001:*",
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #3",
+ } },
+ { "ed25519_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 16,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "*.example.com,192.0.2.*,2001:*",
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #3",
+ } },
+ { "rsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 17,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "*.example.com,192.0.2.*,2001:*",
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #3",
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 18,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 19,
+ HKF_STATUS_COMMENT,
+ 0,
+ "# Hashed hostname and address entries",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { "dsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
+ NULL,
+ 20,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #5",
+ } },
+ { "ecdsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
+ NULL,
+ 21,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #5",
+ } },
+ { "ed25519_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
+ NULL,
+ 22,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #5",
+ } },
+ { "rsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
+ NULL,
+ 23,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #5",
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 24,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ /*
+ * The next series have each key listed multiple times, as the
+ * hostname and addresses in the pre-hashed known_hosts are split
+ * to separate lines.
+ */
+ { "dsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
+ NULL,
+ 25,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #6",
+ } },
+ { "dsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
+ NULL,
+ 26,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #6",
+ } },
+ { "dsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
+ NULL,
+ 27,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #6",
+ } },
+ { "ecdsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
+ NULL,
+ 28,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #6",
+ } },
+ { "ecdsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
+ NULL,
+ 29,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #6",
+ } },
+ { "ecdsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
+ NULL,
+ 30,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #6",
+ } },
+ { "ed25519_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
+ NULL,
+ 31,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #6",
+ } },
+ { "ed25519_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
+ NULL,
+ 32,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #6",
+ } },
+ { "ed25519_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
+ NULL,
+ 33,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #6",
+ } },
+ { "rsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
+ NULL,
+ 34,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #6",
+ } },
+ { "rsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
+ NULL,
+ 35,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #6",
+ } },
+ { "rsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
+ NULL,
+ 36,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #6",
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 37,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 38,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 39,
+ HKF_STATUS_COMMENT,
+ 0,
+ "# Revoked and CA keys",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { "ed25519_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 40,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_REVOKE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #4",
+ } },
+ { "ecdsa_4.pub" , -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
+ NULL,
+ 41,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_CA,
+ "prometheus.example.com",
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #4",
+ } },
+ { "dsa_4.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 42,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_CA,
+ "*.example.com",
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #4",
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 43,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 44,
+ HKF_STATUS_COMMENT,
+ 0,
+ "# Some invalid lines",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 45,
+ HKF_STATUS_INVALID,
+ 0,
+ NULL,
+ MRK_ERROR,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 46,
+ HKF_STATUS_INVALID,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
+ NULL,
+ 47,
+ HKF_STATUS_INVALID,
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 48,
+ HKF_STATUS_INVALID, /* Would be ok if key not parsed */
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 49,
+ HKF_STATUS_INVALID,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL, /* filled at runtime */
+ NULL,
+ } },
+ { NULL, HKF_STATUS_OK, KEY_RSA, HKF_MATCH_HOST, 0, 0, 0, -1, {
+ NULL,
+ 50,
+ HKF_STATUS_INVALID, /* Would be ok if key not parsed */
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL, /* filled at runtime */
+ NULL,
+ } },
+};
+
+void test_iterate(void);
+
+void
+test_iterate(void)
+{
+ struct cbctx ctx;
+
+ TEST_START("hostkeys_iterate all with key parse");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate all without key parse");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify host 1");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify host 2");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match host 1");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH;
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match host 2");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH;
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify host missing");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match host missing");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify IPv4");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify IPv6");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match IPv4");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH;
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match IPv6");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH;
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify addr missing");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match addr missing");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify host 2 and IPv4");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ ctx.match_host_s = 1;
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match host 1 and IPv6");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH;
+ ctx.match_host_p = 1;
+ ctx.match_ipv6 = 1;
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify host 2 and IPv4 w/ key parse");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_PARSE_KEY;
+ ctx.match_host_s = 1;
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match host 1 and IPv6 w/ key parse");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH|HKF_WANT_PARSE_KEY;
+ ctx.match_host_p = 1;
+ ctx.match_ipv6 = 1;
+ 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);
+ cleanup_expected(expected_full, ctx.nexpected);
+ TEST_DONE();
+}
+
diff --git a/regress/unittests/hostkeys/testdata/dsa_1.pub b/regress/unittests/hostkeys/testdata/dsa_1.pub
new file mode 100644
index 00000000..56e1e371
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/dsa_1.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1
diff --git a/regress/unittests/hostkeys/testdata/dsa_2.pub b/regress/unittests/hostkeys/testdata/dsa_2.pub
new file mode 100644
index 00000000..394e0bf0
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/dsa_2.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAI38Hy/61/O5Bp6yUG8J5XQCeNjRS0xvjlCdzKLyXCueMa+L+X2L/u9PWUsy5SVbTjGgpB8sF6UkCNsV+va7S8zCCHas2MZ7GPlxP6GZBkRPTIFR0N/Pu7wfBzDQz0t0iL4VmxBfTBQv/SxkGWZg+yHihIQP9fwdSAwD/7aVh6ItAAAAFQDSyihIUlINlswM0PJ8wXSti3yIMwAAAIB+oqzaB6ozqs8YxpN5oQOBa/9HEBQEsp8RSIlQmVubXRNgktp42n+Ii1waU9UUk8DX5ahhIeR6B7ojWkqmDAji4SKpoHf4kmr6HvYo85ZSTSx0W4YK/gJHSpDJwhlT52tAfb1JCbWSObjl09B4STv7KedCHcR5oXQvvrV+XoKOSAAAAIAue/EXrs2INw1RfaKNHC0oqOMxmRitv0BFMuNVPo1VDj39CE5kA7AHjwvS1TNeaHtK5Hhgeb6vsmLmNPTOc8xCob0ilyQbt9O0GbONeF2Ge7D2UJyULA/hxql+tCYFIC6yUrmo35fF9XiNisXLoaflk9fjp7ROWWVwnki/jstaQw== DSA #2
diff --git a/regress/unittests/hostkeys/testdata/dsa_3.pub b/regress/unittests/hostkeys/testdata/dsa_3.pub
new file mode 100644
index 00000000..e506ea42
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/dsa_3.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAI6lz2Ip9bzE7TGuDD4SjO9S4Ac90gq0h6ai1O06eI8t/Ot2uJ5Jk2QyVr2jvIZHDl/5bwBx7+5oyjlwRoUrAPPD814wf5tU2tSnmdu1Wbf0cBswif5q0r4tevzmopp/AtgH11QHo3u0/pfyJd10qBDLV2FaYSKMmZvyPfZJ0s9pAAAAFQD5Eqjl6Rx2qVePodD9OwAPT0bU6wAAAIAfnDm6csZF0sFaJR3NIJvaYgSGr8s7cqlsk2gLltB/1wOOO2yX+NeEC+B0H93hlMfaUsPa08bwgmYxnavSMqEBpmtPceefJiEd68zwYqXd38f88wyWZ9Z5iwaI/6OVZPHzCbDxOa4ewVTevRNYUKP1xUTZNT8/gSMfZLYPk4T2AQAAAIAUKroozRMyV+3V/rxt0gFnNxRXBKk+9cl3vgsQ7ktkI9cYg7V1T2K0XF21AVMK9gODszy6PBJjV6ruXBV6TRiqIbQauivp3bHHKYsG6wiJNqwdbVwIjfvv8nn1qFoZQLXG3sdONr9NwN8KzrX89OV0BlR2dVM5qqp+YxOXymP9yg== DSA #3
diff --git a/regress/unittests/hostkeys/testdata/dsa_4.pub b/regress/unittests/hostkeys/testdata/dsa_4.pub
new file mode 100644
index 00000000..8552c381
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/dsa_4.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAKvjnFHm0VvMr5h2Zu3nURsxQKGoxm+DCzYDxRYcilK07Cm5c4XTrFbA2X86+9sGs++W7QRMcTJUYIg0a+UtIMtAjwORd6ZPXM2K5dBW+gh1oHyvKi767tWX7I2c+1ZPJDY95mUUfZQUEfdy9eGDSBmw/pSsveQ1ur6XNUh/MtP/AAAAFQDHnXk/9jBJAdce1pHtLWnbdPSGdQAAAIEAm2OLy8tZBfiEO3c3X1yyB/GTcDwrQCqRMDkhnsmrliec3dWkOfNTzu+MrdvF8ymTWLEqPpbMheYtvNyZ3TF0HO5W7aVBpdGZbOdOAIfB+6skqGbI8A5Up1d7dak/bSsqL2r5NjwbDOdq+1hBzzvbl/qjh+sQarV2zHrpKoQaV28AAACANtkBVedBbqIAdphCrN/LbUi9WlyuF9UZz+tlpVLYrj8GJVwnplV2tvOmUw6yP5/pzCimTsao8dpL5PWxm7fKxLWVxA+lEsA4WeC885CiZn8xhdaJOCN+NyJ2bqkz+4VPI7oDGBm0aFwUqJn+M1PiSgvI50XdF2dBsFRTRNY0wzA= DSA #4
diff --git a/regress/unittests/hostkeys/testdata/dsa_5.pub b/regress/unittests/hostkeys/testdata/dsa_5.pub
new file mode 100644
index 00000000..149e1efd
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/dsa_5.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5
diff --git a/regress/unittests/hostkeys/testdata/dsa_6.pub b/regress/unittests/hostkeys/testdata/dsa_6.pub
new file mode 100644
index 00000000..edbb9764
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/dsa_6.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6
diff --git a/regress/unittests/hostkeys/testdata/ecdsa_1.pub b/regress/unittests/hostkeys/testdata/ecdsa_1.pub
new file mode 100644
index 00000000..16a535bc
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ecdsa_1.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1
diff --git a/regress/unittests/hostkeys/testdata/ecdsa_2.pub b/regress/unittests/hostkeys/testdata/ecdsa_2.pub
new file mode 100644
index 00000000..d2bad11e
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ecdsa_2.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB8qVcXwgBM92NCmReQlPrZAoui4Bz/mW0VUBFOpHXXW1n+15b/Y7Pc6UBd/ITTZmaBciXY+PWaSBGdwc5GdqGdLgFyJ/QAGrFMPNpVutm/82gNQzlxpNwjbMcKyiZEXzSgnjS6DzMQ0WuSMdzIBXq8OW/Kafxg4ZkU6YqALUXxlQMZuQ== ECDSA #2
diff --git a/regress/unittests/hostkeys/testdata/ecdsa_3.pub b/regress/unittests/hostkeys/testdata/ecdsa_3.pub
new file mode 100644
index 00000000..e3ea9254
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ecdsa_3.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3
diff --git a/regress/unittests/hostkeys/testdata/ecdsa_4.pub b/regress/unittests/hostkeys/testdata/ecdsa_4.pub
new file mode 100644
index 00000000..2d616f5c
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ecdsa_4.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4
diff --git a/regress/unittests/hostkeys/testdata/ecdsa_5.pub b/regress/unittests/hostkeys/testdata/ecdsa_5.pub
new file mode 100644
index 00000000..a3df9b3f
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ecdsa_5.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5
diff --git a/regress/unittests/hostkeys/testdata/ecdsa_6.pub b/regress/unittests/hostkeys/testdata/ecdsa_6.pub
new file mode 100644
index 00000000..139f5a7b
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ecdsa_6.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6
diff --git a/regress/unittests/hostkeys/testdata/ed25519_1.pub b/regress/unittests/hostkeys/testdata/ed25519_1.pub
new file mode 100644
index 00000000..0b12efed
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ed25519_1.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1
diff --git a/regress/unittests/hostkeys/testdata/ed25519_2.pub b/regress/unittests/hostkeys/testdata/ed25519_2.pub
new file mode 100644
index 00000000..78e262bc
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ed25519_2.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2
diff --git a/regress/unittests/hostkeys/testdata/ed25519_3.pub b/regress/unittests/hostkeys/testdata/ed25519_3.pub
new file mode 100644
index 00000000..64e5f12a
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ed25519_3.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3
diff --git a/regress/unittests/hostkeys/testdata/ed25519_4.pub b/regress/unittests/hostkeys/testdata/ed25519_4.pub
new file mode 100644
index 00000000..47b6724e
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ed25519_4.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4
diff --git a/regress/unittests/hostkeys/testdata/ed25519_5.pub b/regress/unittests/hostkeys/testdata/ed25519_5.pub
new file mode 100644
index 00000000..72ccae6f
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ed25519_5.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5
diff --git a/regress/unittests/hostkeys/testdata/ed25519_6.pub b/regress/unittests/hostkeys/testdata/ed25519_6.pub
new file mode 100644
index 00000000..0f719731
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ed25519_6.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6
diff --git a/regress/unittests/hostkeys/testdata/known_hosts b/regress/unittests/hostkeys/testdata/known_hosts
new file mode 100644
index 00000000..4446f45d
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/known_hosts
@@ -0,0 +1,50 @@
+# Plain host keys, plain host names
+sisyphus.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1
+sisyphus.example.com ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1
+sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1
+sisyphus.example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1
+
+# Plain host keys, hostnames + addresses
+prometheus.example.com,192.0.2.1,2001:db8::1 ssh-dss AAAAB3NzaC1kc3MAAACBAI38Hy/61/O5Bp6yUG8J5XQCeNjRS0xvjlCdzKLyXCueMa+L+X2L/u9PWUsy5SVbTjGgpB8sF6UkCNsV+va7S8zCCHas2MZ7GPlxP6GZBkRPTIFR0N/Pu7wfBzDQz0t0iL4VmxBfTBQv/SxkGWZg+yHihIQP9fwdSAwD/7aVh6ItAAAAFQDSyihIUlINlswM0PJ8wXSti3yIMwAAAIB+oqzaB6ozqs8YxpN5oQOBa/9HEBQEsp8RSIlQmVubXRNgktp42n+Ii1waU9UUk8DX5ahhIeR6B7ojWkqmDAji4SKpoHf4kmr6HvYo85ZSTSx0W4YK/gJHSpDJwhlT52tAfb1JCbWSObjl09B4STv7KedCHcR5oXQvvrV+XoKOSAAAAIAue/EXrs2INw1RfaKNHC0oqOMxmRitv0BFMuNVPo1VDj39CE5kA7AHjwvS1TNeaHtK5Hhgeb6vsmLmNPTOc8xCob0ilyQbt9O0GbONeF2Ge7D2UJyULA/hxql+tCYFIC6yUrmo35fF9XiNisXLoaflk9fjp7ROWWVwnki/jstaQw== DSA #2
+prometheus.example.com,192.0.2.1,2001:db8::1 ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB8qVcXwgBM92NCmReQlPrZAoui4Bz/mW0VUBFOpHXXW1n+15b/Y7Pc6UBd/ITTZmaBciXY+PWaSBGdwc5GdqGdLgFyJ/QAGrFMPNpVutm/82gNQzlxpNwjbMcKyiZEXzSgnjS6DzMQ0WuSMdzIBXq8OW/Kafxg4ZkU6YqALUXxlQMZuQ== ECDSA #2
+prometheus.example.com,192.0.2.1,2001:db8::1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2
+prometheus.example.com,192.0.2.1,2001:db8::1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDmbUhNabB5AmBDX6GNHZ3lbn7pRxqfpW+f53QqNGlK0sLV+0gkMIrOfUp1kdE2ZLE6tfzdicatj/RlH6/wuo4yyYb+Pyx3G0vxdmAIiA4aANq38XweDucBC0TZkRWVHK+Gs5V/uV0z7N0axJvkkJujMLvST3CRiiWwlficBc6yVQ== RSA #2
+
+# Some hosts with wildcard names / IPs
+*.example.com,192.0.2.*,2001:* ssh-dss AAAAB3NzaC1kc3MAAACBAI6lz2Ip9bzE7TGuDD4SjO9S4Ac90gq0h6ai1O06eI8t/Ot2uJ5Jk2QyVr2jvIZHDl/5bwBx7+5oyjlwRoUrAPPD814wf5tU2tSnmdu1Wbf0cBswif5q0r4tevzmopp/AtgH11QHo3u0/pfyJd10qBDLV2FaYSKMmZvyPfZJ0s9pAAAAFQD5Eqjl6Rx2qVePodD9OwAPT0bU6wAAAIAfnDm6csZF0sFaJR3NIJvaYgSGr8s7cqlsk2gLltB/1wOOO2yX+NeEC+B0H93hlMfaUsPa08bwgmYxnavSMqEBpmtPceefJiEd68zwYqXd38f88wyWZ9Z5iwaI/6OVZPHzCbDxOa4ewVTevRNYUKP1xUTZNT8/gSMfZLYPk4T2AQAAAIAUKroozRMyV+3V/rxt0gFnNxRXBKk+9cl3vgsQ7ktkI9cYg7V1T2K0XF21AVMK9gODszy6PBJjV6ruXBV6TRiqIbQauivp3bHHKYsG6wiJNqwdbVwIjfvv8nn1qFoZQLXG3sdONr9NwN8KzrX89OV0BlR2dVM5qqp+YxOXymP9yg== DSA #3
+*.example.com,192.0.2.*,2001:* ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3
+*.example.com,192.0.2.*,2001:* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3
+*.example.com,192.0.2.*,2001:* ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3
+
+# Hashed hostname and address entries
+|1|z3xOIdT5ue3Vuf3MzT67kaioqjw=|GZhhe5uwDOBQrC9N4cCjpbLpSn4= ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5
+|1|B7t/AYabn8zgwU47Cb4A/Nqt3eI=|arQPZyRphkzisr7w6wwikvhaOyE= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5
+|1|JR81WxEocTP5d7goIRkl8fHBbno=|l6sj6FOsoXxgEZMzn/BnOfPKN68= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5
+|1|W7x4zY6KtTZJgsopyOusJqvVPag=|QauLt7hKezBZFZi2i4Xopho7Nsk= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5
+
+|1|mxnU8luzqWLvfVi5qBm5xVIyCRM=|9Epopft7LBd80Bf6RmWPIpwa8yU= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6
+|1|klvLmvh2vCpkNMDEjVvrE8SJWTg=|e/dqEEBLnbgqmwEesl4cDRu/7TM= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6
+|1|wsk3ddB3UjuxEsoeNCeZjZ6NvZs=|O3O/q2Z/u7DrxoTiIq6kzCevQT0= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6
+|1|B8epmkLSni+vGZDijr/EwxeR2k4=|7ct8yzNOVJhKm3ZD2w0XIT7df8E= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6
+|1|JojD885UhYhbCu571rgyM/5PpYU=|BJaU2aE1FebQZy3B5tzTDRWFRG0= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6
+|1|5t7UDHDybVrDZVQPCpwdnr6nk4k=|EqJ73W/veIL3H2x+YWHcJxI5ETA= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6
+|1|OCcBfGc/b9+ip+W6Gp+3ftdluO4=|VbrKUdzOOtIBOOmEE+jlK4SD3Xc= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6
+|1|9fLN0YdP+BJ25lKuKvYuOdUo93w=|vZyr0rOiX01hv5XbghhHMW+Zb3U= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6
+|1|nc9RoaaQ0s5jdPxwlUmluGHU3uk=|un6OsJajokKQ3MgyS9mfDNeyP6U= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6
+|1|rsHB6juT9q6GOY91qOeOwL6TSJE=|ps/vXF9Izuues5PbOn887Gw/2Dg= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6
+|1|BsckdLH2aRyWQooRmv+Yo3t4dKg=|Lf3tJc5Iyx0KxNwAG89FsImsfEE= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6
+|1|plqkBA4hq7UATyd5+/Xl+zL7ghw=|stacofaUed46666mfqxp9gJFjt4= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6
+
+
+# Revoked and CA keys
+@revoked sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4
+@cert-authority prometheus.example.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4
+@cert-authority *.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAKvjnFHm0VvMr5h2Zu3nURsxQKGoxm+DCzYDxRYcilK07Cm5c4XTrFbA2X86+9sGs++W7QRMcTJUYIg0a+UtIMtAjwORd6ZPXM2K5dBW+gh1oHyvKi767tWX7I2c+1ZPJDY95mUUfZQUEfdy9eGDSBmw/pSsveQ1ur6XNUh/MtP/AAAAFQDHnXk/9jBJAdce1pHtLWnbdPSGdQAAAIEAm2OLy8tZBfiEO3c3X1yyB/GTcDwrQCqRMDkhnsmrliec3dWkOfNTzu+MrdvF8ymTWLEqPpbMheYtvNyZ3TF0HO5W7aVBpdGZbOdOAIfB+6skqGbI8A5Up1d7dak/bSsqL2r5NjwbDOdq+1hBzzvbl/qjh+sQarV2zHrpKoQaV28AAACANtkBVedBbqIAdphCrN/LbUi9WlyuF9UZz+tlpVLYrj8GJVwnplV2tvOmUw6yP5/pzCimTsao8dpL5PWxm7fKxLWVxA+lEsA4WeC885CiZn8xhdaJOCN+NyJ2bqkz+4VPI7oDGBm0aFwUqJn+M1PiSgvI50XdF2dBsFRTRNY0wzA= DSA #4
+
+# Some invalid lines
+@what sisyphus.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1
+sisyphus.example.com
+prometheus.example.com ssh-ed25519
+sisyphus.example.com ssh-dsa AAAATgAAAAdz
+sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg==
+prometheus.example.com ssh-rsa AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg==
diff --git a/regress/unittests/hostkeys/testdata/rsa1_1.pub b/regress/unittests/hostkeys/testdata/rsa1_1.pub
new file mode 100644
index 00000000..772ce9c0
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa1_1.pub
@@ -0,0 +1 @@
+1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1
diff --git a/regress/unittests/hostkeys/testdata/rsa1_2.pub b/regress/unittests/hostkeys/testdata/rsa1_2.pub
new file mode 100644
index 00000000..78794b94
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa1_2.pub
@@ -0,0 +1 @@
+1024 65537 135970715082947442639683969597180728933388298633245835186618852623800675939308729462220235058285909679252157995530180587329132927339620517781785310829060832352381015614725360278571924286986474946772141568893116432268565829418506866604294073334978275702221949783314402806080929601995102334442541344606109853641 RSA1 #2
diff --git a/regress/unittests/hostkeys/testdata/rsa1_3.pub b/regress/unittests/hostkeys/testdata/rsa1_3.pub
new file mode 100644
index 00000000..0c035fe0
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa1_3.pub
@@ -0,0 +1 @@
+1024 65537 125895605498029643697051635076028105429632810811904702876152645261610759866299221305725069141163240694267669117205342283569102183636228981857946763978553664895308762890072813014496700601576921921752482059207749978374872713540759920335553799711267170948655579130584031555334229966603000896364091459595522912269 RSA1 #3
diff --git a/regress/unittests/hostkeys/testdata/rsa1_4.pub b/regress/unittests/hostkeys/testdata/rsa1_4.pub
new file mode 100644
index 00000000..00064423
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa1_4.pub
@@ -0,0 +1 @@
+1024 65537 174143366122697048196335388217056770310345753698079464367148030836533360510864881734142526411160017107552815906024399248049666856133771656680462456979369587903909343046704480897527203474513676654933090991684252819423129896444427656841613263783484827101210734799449281639493127615902427443211183258155381810593 RSA1 #4
diff --git a/regress/unittests/hostkeys/testdata/rsa1_5.pub b/regress/unittests/hostkeys/testdata/rsa1_5.pub
new file mode 100644
index 00000000..bb53c264
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa1_5.pub
@@ -0,0 +1 @@
+1024 65537 127931411493401587586867047972295564331543694182352197506125410692673654572057908999642645524647232712160516076508316152810117209181150078352725299319149726341058893406440426414316276977768958023952319602422835879783057966985348561111880658922724668687074412548487722084792283453716871417610020757212399252171 RSA1 #5
diff --git a/regress/unittests/hostkeys/testdata/rsa1_6.pub b/regress/unittests/hostkeys/testdata/rsa1_6.pub
new file mode 100644
index 00000000..85d6576b
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa1_6.pub
@@ -0,0 +1 @@
+1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6
diff --git a/regress/unittests/hostkeys/testdata/rsa_1.pub b/regress/unittests/hostkeys/testdata/rsa_1.pub
new file mode 100644
index 00000000..2b87885a
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa_1.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1
diff --git a/regress/unittests/hostkeys/testdata/rsa_2.pub b/regress/unittests/hostkeys/testdata/rsa_2.pub
new file mode 100644
index 00000000..33f1fd93
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa_2.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDmbUhNabB5AmBDX6GNHZ3lbn7pRxqfpW+f53QqNGlK0sLV+0gkMIrOfUp1kdE2ZLE6tfzdicatj/RlH6/wuo4yyYb+Pyx3G0vxdmAIiA4aANq38XweDucBC0TZkRWVHK+Gs5V/uV0z7N0axJvkkJujMLvST3CRiiWwlficBc6yVQ== RSA #2
diff --git a/regress/unittests/hostkeys/testdata/rsa_3.pub b/regress/unittests/hostkeys/testdata/rsa_3.pub
new file mode 100644
index 00000000..c2f6b208
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa_3.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3
diff --git a/regress/unittests/hostkeys/testdata/rsa_4.pub b/regress/unittests/hostkeys/testdata/rsa_4.pub
new file mode 100644
index 00000000..35545a71
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa_4.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDI8AdjBAozcdRnIikVlt69iyDHKyrtxmpdkbRy9bWaL86OH+PTmLUk5e+T/ufiakpeE2pm0hkE3e4Sh/FsY+rsQdRoraWVNFfchcMeVlKvuy5RZN0ElvmaQebOJUeNeBn2LLw8aL8bJ4CP/bQRKrmrSSqjz3+4H9YNVyyk1OGBPQ== RSA #4
diff --git a/regress/unittests/hostkeys/testdata/rsa_5.pub b/regress/unittests/hostkeys/testdata/rsa_5.pub
new file mode 100644
index 00000000..befbaa7d
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa_5.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5
diff --git a/regress/unittests/hostkeys/testdata/rsa_6.pub b/regress/unittests/hostkeys/testdata/rsa_6.pub
new file mode 100644
index 00000000..393e1167
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa_6.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6
diff --git a/regress/unittests/hostkeys/tests.c b/regress/unittests/hostkeys/tests.c
new file mode 100644
index 00000000..92c7646a
--- /dev/null
+++ b/regress/unittests/hostkeys/tests.c
@@ -0,0 +1,16 @@
+/* $OpenBSD: tests.c,v 1.1 2015/02/16 22:18:34 djm Exp $ */
+/*
+ * Regress test for known_hosts-related API.
+ *
+ * Placed in the public domain
+ */
+
+void tests(void);
+void test_iterate(void); /* test_iterate.c */
+
+void
+tests(void)
+{
+ test_iterate();
+}
+
diff --git a/regress/unittests/kex/Makefile b/regress/unittests/kex/Makefile
new file mode 100644
index 00000000..1c5d68ce
--- /dev/null
+++ b/regress/unittests/kex/Makefile
@@ -0,0 +1,40 @@
+# $OpenBSD: Makefile,v 1.10 2020/04/06 09:43:56 dtucker Exp $
+
+PROG=test_kex
+SRCS=tests.c test_kex.c
+
+# From usr.bin/ssh
+SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
+SRCS+=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+=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
+
+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+= utf8.c
+
+SRCS+=digest-openssl.c
+#SRCS+=digest-libc.c
+
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG}
+
+.include <bsd.regress.mk>
+
+LDADD+=-lz
diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c
new file mode 100644
index 00000000..0e7cd9e0
--- /dev/null
+++ b/regress/unittests/kex/test_kex.c
@@ -0,0 +1,205 @@
+/* $OpenBSD: test_kex.c,v 1.4 2019/01/21 12:35:20 djm Exp $ */
+/*
+ * Regress test KEX
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "ssherr.h"
+#include "ssh_api.h"
+#include "sshbuf.h"
+#include "packet.h"
+#include "myproposal.h"
+
+void kex_tests(void);
+static int do_debug = 0;
+
+static int
+do_send_and_receive(struct ssh *from, struct ssh *to)
+{
+ u_char type;
+ size_t len;
+ const u_char *buf;
+ int r;
+
+ for (;;) {
+ if ((r = ssh_packet_next(from, &type)) != 0) {
+ fprintf(stderr, "ssh_packet_next: %s\n", ssh_err(r));
+ return r;
+ }
+ if (type != 0)
+ return 0;
+ buf = ssh_output_ptr(from, &len);
+ if (do_debug)
+ printf("%zu", len);
+ if (len == 0)
+ return 0;
+ if ((r = ssh_output_consume(from, len)) != 0 ||
+ (r = ssh_input_append(to, buf, len)) != 0)
+ return r;
+ }
+}
+
+static void
+run_kex(struct ssh *client, struct ssh *server)
+{
+ int r = 0;
+
+ while (!server->kex->done || !client->kex->done) {
+ if (do_debug)
+ printf(" S:");
+ if ((r = do_send_and_receive(server, client)))
+ break;
+ if (do_debug)
+ printf(" C:");
+ if ((r = do_send_and_receive(client, server)))
+ break;
+ }
+ if (do_debug)
+ printf("done: %s\n", ssh_err(r));
+ ASSERT_INT_EQ(r, 0);
+ ASSERT_INT_EQ(server->kex->done, 1);
+ ASSERT_INT_EQ(client->kex->done, 1);
+}
+
+static void
+do_kex_with_key(char *kex, int keytype, int bits)
+{
+ struct ssh *client = NULL, *server = NULL, *server2 = NULL;
+ struct sshkey *private, *public;
+ struct sshbuf *state;
+ struct kex_params kex_params;
+ char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
+ char *keyname = NULL;
+
+ TEST_START("sshkey_generate");
+ ASSERT_INT_EQ(sshkey_generate(keytype, bits, &private), 0);
+ TEST_DONE();
+
+ TEST_START("sshkey_from_private");
+ ASSERT_INT_EQ(sshkey_from_private(private, &public), 0);
+ TEST_DONE();
+
+ TEST_START("ssh_init");
+ memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
+ if (kex != NULL)
+ kex_params.proposal[PROPOSAL_KEX_ALGS] = kex;
+ keyname = strdup(sshkey_ssh_name(private));
+ ASSERT_PTR_NE(keyname, NULL);
+ kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname;
+ ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0);
+ ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0);
+ ASSERT_PTR_NE(client, NULL);
+ ASSERT_PTR_NE(server, NULL);
+ TEST_DONE();
+
+ TEST_START("ssh_add_hostkey");
+ ASSERT_INT_EQ(ssh_add_hostkey(server, private), 0);
+ ASSERT_INT_EQ(ssh_add_hostkey(client, public), 0);
+ TEST_DONE();
+
+ TEST_START("kex");
+ run_kex(client, server);
+ TEST_DONE();
+
+ TEST_START("rekeying client");
+ ASSERT_INT_EQ(kex_send_kexinit(client), 0);
+ run_kex(client, server);
+ TEST_DONE();
+
+ TEST_START("rekeying server");
+ ASSERT_INT_EQ(kex_send_kexinit(server), 0);
+ run_kex(client, server);
+ TEST_DONE();
+
+ TEST_START("ssh_packet_get_state");
+ state = sshbuf_new();
+ ASSERT_PTR_NE(state, NULL);
+ ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0);
+ ASSERT_INT_GE(sshbuf_len(state), 1);
+ TEST_DONE();
+
+ TEST_START("ssh_packet_set_state");
+ server2 = NULL;
+ ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0);
+ ASSERT_PTR_NE(server2, NULL);
+ ASSERT_INT_EQ(ssh_add_hostkey(server2, private), 0);
+ 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_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 /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
+ server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server;
+ server2->kex->load_host_public_key = server->kex->load_host_public_key;
+ server2->kex->load_host_private_key = server->kex->load_host_private_key;
+ server2->kex->sign = server->kex->sign;
+ TEST_DONE();
+
+ TEST_START("rekeying server2");
+ ASSERT_INT_EQ(kex_send_kexinit(server2), 0);
+ run_kex(client, server2);
+ ASSERT_INT_EQ(kex_send_kexinit(client), 0);
+ run_kex(client, server2);
+ TEST_DONE();
+
+ TEST_START("cleanup");
+ sshkey_free(private);
+ sshkey_free(public);
+ ssh_free(client);
+ ssh_free(server);
+ ssh_free(server2);
+ free(keyname);
+ TEST_DONE();
+}
+
+static void
+do_kex(char *kex)
+{
+#ifdef WITH_OPENSSL
+ do_kex_with_key(kex, KEY_RSA, 2048);
+ do_kex_with_key(kex, KEY_DSA, 1024);
+#ifdef OPENSSL_HAS_ECC
+ do_kex_with_key(kex, KEY_ECDSA, 256);
+#endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
+ do_kex_with_key(kex, KEY_ED25519, 256);
+}
+
+void
+kex_tests(void)
+{
+ do_kex("curve25519-sha256@libssh.org");
+#ifdef WITH_OPENSSL
+#ifdef OPENSSL_HAS_ECC
+ do_kex("ecdh-sha2-nistp256");
+ do_kex("ecdh-sha2-nistp384");
+ do_kex("ecdh-sha2-nistp521");
+#endif /* OPENSSL_HAS_ECC */
+ do_kex("diffie-hellman-group-exchange-sha256");
+ do_kex("diffie-hellman-group-exchange-sha1");
+ do_kex("diffie-hellman-group14-sha1");
+ do_kex("diffie-hellman-group1-sha1");
+#endif /* WITH_OPENSSL */
+}
diff --git a/regress/unittests/kex/tests.c b/regress/unittests/kex/tests.c
new file mode 100644
index 00000000..e7036ec1
--- /dev/null
+++ b/regress/unittests/kex/tests.c
@@ -0,0 +1,14 @@
+/* $OpenBSD: tests.c,v 1.1 2015/01/15 23:41:29 markus Exp $ */
+/*
+ * Placed in the public domain
+ */
+
+#include "../test_helper/test_helper.h"
+
+void kex_tests(void);
+
+void
+tests(void)
+{
+ kex_tests();
+}
diff --git a/regress/unittests/match/Makefile b/regress/unittests/match/Makefile
new file mode 100644
index 00000000..87e75826
--- /dev/null
+++ b/regress/unittests/match/Makefile
@@ -0,0 +1,16 @@
+# $OpenBSD: Makefile,v 1.4 2017/12/21 03:01:49 djm Exp $
+
+PROG=test_match
+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
+
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG}
+
+.include <bsd.regress.mk>
diff --git a/regress/unittests/match/tests.c b/regress/unittests/match/tests.c
new file mode 100644
index 00000000..3d9af55f
--- /dev/null
+++ b/regress/unittests/match/tests.c
@@ -0,0 +1,132 @@
+/* $OpenBSD: tests.c,v 1.5 2018/07/04 13:51:45 djm Exp $ */
+/*
+ * Regress test for matching 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 "match.h"
+
+void
+tests(void)
+{
+ TEST_START("match_pattern");
+ ASSERT_INT_EQ(match_pattern("", ""), 1);
+ ASSERT_INT_EQ(match_pattern("", "aaa"), 0);
+ ASSERT_INT_EQ(match_pattern("aaa", ""), 0);
+ ASSERT_INT_EQ(match_pattern("aaa", "aaaa"), 0);
+ ASSERT_INT_EQ(match_pattern("aaaa", "aaa"), 0);
+ TEST_DONE();
+
+ TEST_START("match_pattern wildcard");
+ ASSERT_INT_EQ(match_pattern("", "*"), 1);
+ ASSERT_INT_EQ(match_pattern("a", "?"), 1);
+ ASSERT_INT_EQ(match_pattern("aa", "a?"), 1);
+ ASSERT_INT_EQ(match_pattern("a", "*"), 1);
+ ASSERT_INT_EQ(match_pattern("aa", "a*"), 1);
+ ASSERT_INT_EQ(match_pattern("aa", "?*"), 1);
+ ASSERT_INT_EQ(match_pattern("aa", "**"), 1);
+ ASSERT_INT_EQ(match_pattern("aa", "?a"), 1);
+ ASSERT_INT_EQ(match_pattern("aa", "*a"), 1);
+ ASSERT_INT_EQ(match_pattern("ba", "a?"), 0);
+ ASSERT_INT_EQ(match_pattern("ba", "a*"), 0);
+ ASSERT_INT_EQ(match_pattern("ab", "?a"), 0);
+ ASSERT_INT_EQ(match_pattern("ab", "*a"), 0);
+ TEST_DONE();
+
+ TEST_START("match_pattern_list");
+ ASSERT_INT_EQ(match_pattern_list("", "", 0), 0); /* no patterns */
+ ASSERT_INT_EQ(match_pattern_list("", "*", 0), 1);
+ ASSERT_INT_EQ(match_pattern_list("", "!*", 0), -1);
+ ASSERT_INT_EQ(match_pattern_list("", "!a,*", 0), 1);
+ ASSERT_INT_EQ(match_pattern_list("", "*,!a", 0), 1);
+ ASSERT_INT_EQ(match_pattern_list("", "a,!*", 0), -1);
+ ASSERT_INT_EQ(match_pattern_list("", "!*,a", 0), -1);
+ ASSERT_INT_EQ(match_pattern_list("a", "", 0), 0);
+ ASSERT_INT_EQ(match_pattern_list("a", "*", 0), 1);
+ ASSERT_INT_EQ(match_pattern_list("a", "!*", 0), -1);
+ ASSERT_INT_EQ(match_pattern_list("a", "!a", 0), -1);
+ /* XXX negated ASSERT_INT_EQ(match_pattern_list("a", "!b", 0), 1); */
+ ASSERT_INT_EQ(match_pattern_list("a", "!a,*", 0), -1);
+ ASSERT_INT_EQ(match_pattern_list("b", "!a,*", 0), 1);
+ ASSERT_INT_EQ(match_pattern_list("a", "*,!a", 0), -1);
+ ASSERT_INT_EQ(match_pattern_list("b", "*,!a", 0), 1);
+ ASSERT_INT_EQ(match_pattern_list("a", "a,!*", 0), -1);
+ ASSERT_INT_EQ(match_pattern_list("b", "a,!*", 0), -1);
+ ASSERT_INT_EQ(match_pattern_list("a", "a,!a", 0), -1);
+ /* XXX negated ASSERT_INT_EQ(match_pattern_list("b", "a,!a", 0), 1); */
+ ASSERT_INT_EQ(match_pattern_list("a", "!*,a", 0), -1);
+ ASSERT_INT_EQ(match_pattern_list("b", "!*,a", 0), -1);
+ TEST_DONE();
+
+ TEST_START("match_pattern_list lowercase");
+ ASSERT_INT_EQ(match_pattern_list("abc", "ABC", 0), 0);
+ ASSERT_INT_EQ(match_pattern_list("ABC", "abc", 0), 0);
+ ASSERT_INT_EQ(match_pattern_list("abc", "ABC", 1), 1);
+ ASSERT_INT_EQ(match_pattern_list("ABC", "abc", 1), 0);
+ TEST_DONE();
+
+ TEST_START("addr_match_list");
+ ASSERT_INT_EQ(addr_match_list("127.0.0.1", "127.0.0.1/44"), -2);
+ ASSERT_INT_EQ(addr_match_list(NULL, "127.0.0.1/44"), -2);
+ ASSERT_INT_EQ(addr_match_list("a", "*"), 0);
+ ASSERT_INT_EQ(addr_match_list("127.0.0.1", "*"), 1);
+ ASSERT_INT_EQ(addr_match_list(NULL, "*"), 0);
+ ASSERT_INT_EQ(addr_match_list("127.0.0.1", "127.0.0.1"), 1);
+ ASSERT_INT_EQ(addr_match_list("127.0.0.1", "127.0.0.2"), 0);
+ ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.0.1"), -1);
+ /* XXX negated ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.0.2"), 1); */
+ ASSERT_INT_EQ(addr_match_list("127.0.0.255", "127.0.0.0/24"), 1);
+ ASSERT_INT_EQ(addr_match_list("127.0.1.1", "127.0.0.0/24"), 0);
+ ASSERT_INT_EQ(addr_match_list("127.0.0.1", "127.0.0.0/24"), 1);
+ ASSERT_INT_EQ(addr_match_list("127.0.0.1", "127.0.1.0/24"), 0);
+ ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.0.0/24"), -1);
+ /* XXX negated ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.1.0/24"), 1); */
+ ASSERT_INT_EQ(addr_match_list("127.0.0.1", "10.0.0.1,!127.0.0.1"), -1);
+ ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.0.1,10.0.0.1"), -1);
+ ASSERT_INT_EQ(addr_match_list("127.0.0.1", "10.0.0.1,127.0.0.2"), 0);
+ ASSERT_INT_EQ(addr_match_list("127.0.0.1", "127.0.0.2,10.0.0.1"), 0);
+ /* XXX negated ASSERT_INT_EQ(addr_match_list("127.0.0.1", "10.0.0.1,!127.0.0.2"), 1); */
+ /* XXX negated ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.0.2,10.0.0.1"), 1); */
+ TEST_DONE();
+
+#define CHECK_FILTER(string,filter,expected) \
+ do { \
+ char *result = match_filter_blacklist((string), (filter)); \
+ ASSERT_STRING_EQ(result, expected); \
+ free(result); \
+ } while (0)
+
+ TEST_START("match_filter_list");
+ CHECK_FILTER("a,b,c", "", "a,b,c");
+ CHECK_FILTER("a,b,c", "a", "b,c");
+ CHECK_FILTER("a,b,c", "b", "a,c");
+ CHECK_FILTER("a,b,c", "c", "a,b");
+ CHECK_FILTER("a,b,c", "a,b", "c");
+ CHECK_FILTER("a,b,c", "a,c", "b");
+ CHECK_FILTER("a,b,c", "b,c", "a");
+ CHECK_FILTER("a,b,c", "a,b,c", "");
+ CHECK_FILTER("a,b,c", "b,c", "a");
+ CHECK_FILTER("", "a,b,c", "");
+ TEST_DONE();
+/*
+ * XXX TODO
+ * 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 *);
+ * int addr_match_cidr_list(const char *, const char *);
+ */
+}
diff --git a/regress/unittests/misc/Makefile b/regress/unittests/misc/Makefile
new file mode 100644
index 00000000..06e954cb
--- /dev/null
+++ b/regress/unittests/misc/Makefile
@@ -0,0 +1,16 @@
+# $OpenBSD: Makefile,v 1.1 2019/04/28 22:53:26 dtucker Exp $
+
+PROG=test_misc
+SRCS=tests.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
+
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG}
+
+.include <bsd.regress.mk>
diff --git a/regress/unittests/misc/tests.c b/regress/unittests/misc/tests.c
new file mode 100644
index 00000000..ed775ebb
--- /dev/null
+++ b/regress/unittests/misc/tests.c
@@ -0,0 +1,79 @@
+/* $OpenBSD: tests.c,v 1.1 2019/04/28 22:53:26 dtucker Exp $ */
+/*
+ * Regress test for misc helper functions.
+ *
+ * Placed in the public domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "test_helper.h"
+
+#include "misc.h"
+
+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();
+}
diff --git a/regress/unittests/sshbuf/Makefile b/regress/unittests/sshbuf/Makefile
new file mode 100644
index 00000000..5f6c4426
--- /dev/null
+++ b/regress/unittests/sshbuf/Makefile
@@ -0,0 +1,21 @@
+# $OpenBSD: Makefile,v 1.8 2020/01/26 00:09:50 djm Exp $
+
+# $OpenBSD: Makefile,v 1.8 2020/01/26 00:09:50 djm Exp $
+
+PROG=test_sshbuf
+SRCS=tests.c
+SRCS+=test_sshbuf.c
+SRCS+=test_sshbuf_getput_basic.c
+SRCS+=test_sshbuf_getput_crypto.c
+SRCS+=test_sshbuf_misc.c
+SRCS+=test_sshbuf_fuzz.c
+SRCS+=test_sshbuf_getput_fuzz.c
+SRCS+=test_sshbuf_fixed.c
+
+# From usr.bin/ssh
+SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
+SRCS+=sshbuf-io.c atomicio.c misc.c xmalloc.c log.c fatal.c ssherr.c cleanup.c
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS}
+
diff --git a/regress/unittests/sshbuf/test_sshbuf.c b/regress/unittests/sshbuf/test_sshbuf.c
new file mode 100644
index 00000000..ee77d693
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf.c
@@ -0,0 +1,240 @@
+/* $OpenBSD: test_sshbuf.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
+/*
+ * Regress test for sshbuf.h buffer API
+ *
+ * Placed in the public domain
+ */
+
+#define SSHBUF_INTERNAL 1 /* access internals for testing */
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "ssherr.h"
+#include "sshbuf.h"
+
+void sshbuf_tests(void);
+
+void
+sshbuf_tests(void)
+{
+ struct sshbuf *p1;
+ const u_char *cdp;
+ u_char *dp;
+ size_t sz;
+ int r;
+
+ TEST_START("allocate sshbuf");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ TEST_DONE();
+
+ TEST_START("max size on fresh buffer");
+ ASSERT_SIZE_T_GT(sshbuf_max_size(p1), 0);
+ TEST_DONE();
+
+ TEST_START("available on fresh buffer");
+ ASSERT_SIZE_T_GT(sshbuf_avail(p1), 0);
+ TEST_DONE();
+
+ TEST_START("len = 0 on empty buffer");
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ TEST_DONE();
+
+ TEST_START("set valid max size");
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, 65536), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 65536);
+ TEST_DONE();
+
+ TEST_START("available on limited buffer");
+ ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 65536);
+ TEST_DONE();
+
+ TEST_START("free");
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("consume on empty buffer");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_consume(p1, 0), 0);
+ ASSERT_INT_EQ(sshbuf_consume(p1, 1), SSH_ERR_MESSAGE_INCOMPLETE);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("consume_end on empty buffer");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_consume_end(p1, 0), 0);
+ ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), SSH_ERR_MESSAGE_INCOMPLETE);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("reserve space");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ r = sshbuf_reserve(p1, 1, &dp);
+ ASSERT_INT_EQ(r, 0);
+ ASSERT_PTR_NE(dp, NULL);
+ *dp = 0x11;
+ r = sshbuf_reserve(p1, 3, &dp);
+ ASSERT_INT_EQ(r, 0);
+ ASSERT_PTR_NE(dp, NULL);
+ *dp++ = 0x22;
+ *dp++ = 0x33;
+ *dp++ = 0x44;
+ TEST_DONE();
+
+ TEST_START("sshbuf_len on filled buffer");
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
+ TEST_DONE();
+
+ TEST_START("sshbuf_ptr on filled buffer");
+ cdp = sshbuf_ptr(p1);
+ ASSERT_PTR_NE(cdp, NULL);
+ ASSERT_U8_EQ(cdp[0], 0x11);
+ ASSERT_U8_EQ(cdp[1], 0x22);
+ ASSERT_U8_EQ(cdp[2], 0x33);
+ ASSERT_U8_EQ(cdp[3], 0x44);
+ TEST_DONE();
+
+ TEST_START("consume on filled buffer");
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
+ ASSERT_INT_EQ(sshbuf_consume(p1, 0), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
+ r = sshbuf_consume(p1, 64);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
+ ASSERT_INT_EQ(sshbuf_consume(p1, 1), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 3);
+ cdp = sshbuf_ptr(p1);
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_U8_EQ(cdp[0], 0x22);
+ ASSERT_INT_EQ(sshbuf_consume(p1, 2), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
+ cdp = sshbuf_ptr(p1);
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_U8_EQ(cdp[0], 0x44);
+ r = sshbuf_consume(p1, 2);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
+ ASSERT_INT_EQ(sshbuf_consume(p1, 1), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ r = sshbuf_consume(p1, 1);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("consume_end on filled buffer");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ r = sshbuf_reserve(p1, 4, &dp);
+ ASSERT_INT_EQ(r, 0);
+ ASSERT_PTR_NE(dp, NULL);
+ *dp++ = 0x11;
+ *dp++ = 0x22;
+ *dp++ = 0x33;
+ *dp++ = 0x44;
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
+ r = sshbuf_consume_end(p1, 5);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
+ ASSERT_INT_EQ(sshbuf_consume_end(p1, 3), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
+ cdp = sshbuf_ptr(p1);
+ ASSERT_PTR_NE(cdp, NULL);
+ ASSERT_U8_EQ(*cdp, 0x11);
+ r = sshbuf_consume_end(p1, 2);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("fill limited buffer");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1223), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223);
+ ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 1223);
+ r = sshbuf_reserve(p1, 1223, &dp);
+ ASSERT_INT_EQ(r, 0);
+ ASSERT_PTR_NE(dp, NULL);
+ memset(dp, 0xd7, 1223);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1223);
+ ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 0);
+ r = sshbuf_reserve(p1, 1, &dp);
+ ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_PTR_EQ(dp, NULL);
+ TEST_DONE();
+
+ TEST_START("consume and force compaction");
+ ASSERT_INT_EQ(sshbuf_consume(p1, 223), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1000);
+ ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 223);
+ r = sshbuf_reserve(p1, 224, &dp);
+ ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_PTR_EQ(dp, NULL);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1000);
+ ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 223);
+ r = sshbuf_reserve(p1, 223, &dp);
+ ASSERT_INT_EQ(r, 0);
+ ASSERT_PTR_NE(dp, NULL);
+ memset(dp, 0x7d, 223);
+ cdp = sshbuf_ptr(p1);
+ ASSERT_PTR_NE(cdp, NULL);
+ ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000);
+ ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223);
+ TEST_DONE();
+
+ TEST_START("resize full buffer");
+ r = sshbuf_set_max_size(p1, 1000);
+ ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
+ sz = roundup(1223 + SSHBUF_SIZE_INC * 3, SSHBUF_SIZE_INC);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, sz), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz);
+ ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - 1223);
+ ASSERT_INT_EQ(sshbuf_len(p1), 1223);
+ TEST_DONE();
+
+ /* NB. uses sshbuf internals */
+ TEST_START("alloc chunking");
+ r = sshbuf_reserve(p1, 1, &dp);
+ ASSERT_INT_EQ(r, 0);
+ ASSERT_PTR_NE(dp, NULL);
+ *dp = 0xff;
+ cdp = sshbuf_ptr(p1);
+ ASSERT_PTR_NE(cdp, NULL);
+ ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000);
+ ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223);
+ ASSERT_MEM_FILLED_EQ(cdp + 1223, 0xff, 1);
+ ASSERT_SIZE_T_EQ(sshbuf_alloc(p1) % SSHBUF_SIZE_INC, 0);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("reset buffer");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1223), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223);
+ r = sshbuf_reserve(p1, 1223, &dp);
+ ASSERT_INT_EQ(r, 0);
+ ASSERT_PTR_NE(dp, NULL);
+ memset(dp, 0xd7, 1223);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1223);
+ sshbuf_reset(p1);
+ ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 1223);
+ sshbuf_free(p1);
+ TEST_DONE();
+}
diff --git a/regress/unittests/sshbuf/test_sshbuf_fixed.c b/regress/unittests/sshbuf/test_sshbuf_fixed.c
new file mode 100644
index 00000000..df4925f7
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf_fixed.c
@@ -0,0 +1,126 @@
+/* $OpenBSD: test_sshbuf_fixed.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
+/*
+ * Regress test for sshbuf.h buffer API
+ *
+ * Placed in the public domain
+ */
+
+#define SSHBUF_INTERNAL 1 /* access internals for testing */
+#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 "sshbuf.h"
+#include "ssherr.h"
+
+void sshbuf_fixed(void);
+
+const u_char test_buf[] = "\x01\x12\x34\x56\x78\x00\x00\x00\x05hello";
+
+void
+sshbuf_fixed(void)
+{
+ struct sshbuf *p1, *p2, *p3;
+ u_char c;
+ char *s;
+ u_int i;
+ size_t l;
+
+ TEST_START("sshbuf_from");
+ p1 = sshbuf_from(test_buf, sizeof(test_buf));
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_PTR_EQ(sshbuf_mutable_ptr(p1), NULL);
+ ASSERT_INT_EQ(sshbuf_check_reserve(p1, 1), SSH_ERR_BUFFER_READ_ONLY);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 1, NULL), SSH_ERR_BUFFER_READ_ONLY);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, 200), SSH_ERR_BUFFER_READ_ONLY);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), SSH_ERR_BUFFER_READ_ONLY);
+ ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 0);
+ ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_from data");
+ p1 = sshbuf_from(test_buf, sizeof(test_buf) - 1);
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf);
+ ASSERT_INT_EQ(sshbuf_get_u8(p1, &c), 0);
+ ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf + 1);
+ ASSERT_U8_EQ(c, 1);
+ ASSERT_INT_EQ(sshbuf_get_u32(p1, &i), 0);
+ ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf + 5);
+ ASSERT_U32_EQ(i, 0x12345678);
+ ASSERT_INT_EQ(sshbuf_get_cstring(p1, &s, &l), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ ASSERT_STRING_EQ(s, "hello");
+ ASSERT_SIZE_T_EQ(l, 5);
+ sshbuf_free(p1);
+ free(s);
+ TEST_DONE();
+
+ TEST_START("sshbuf_fromb ");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_U_INT_EQ(sshbuf_refcount(p1), 1);
+ ASSERT_PTR_EQ(sshbuf_parent(p1), NULL);
+ ASSERT_INT_EQ(sshbuf_put(p1, test_buf, sizeof(test_buf) - 1), 0);
+ p2 = sshbuf_fromb(p1);
+ ASSERT_PTR_NE(p2, NULL);
+ ASSERT_U_INT_EQ(sshbuf_refcount(p1), 2);
+ ASSERT_PTR_EQ(sshbuf_parent(p1), NULL);
+ ASSERT_PTR_EQ(sshbuf_parent(p2), p1);
+ ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1));
+ ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
+ ASSERT_PTR_NE(sshbuf_ptr(p2), NULL);
+ ASSERT_PTR_EQ(sshbuf_mutable_ptr(p1), NULL);
+ ASSERT_PTR_EQ(sshbuf_mutable_ptr(p2), NULL);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sshbuf_len(p2));
+ ASSERT_INT_EQ(sshbuf_get_u8(p2, &c), 0);
+ ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1) + 1);
+ ASSERT_U8_EQ(c, 1);
+ ASSERT_INT_EQ(sshbuf_get_u32(p2, &i), 0);
+ ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1) + 5);
+ ASSERT_U32_EQ(i, 0x12345678);
+ ASSERT_INT_EQ(sshbuf_get_cstring(p2, &s, &l), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p2), 0);
+ ASSERT_STRING_EQ(s, "hello");
+ ASSERT_SIZE_T_EQ(l, 5);
+ sshbuf_free(p1);
+ ASSERT_U_INT_EQ(sshbuf_refcount(p1), 1);
+ sshbuf_free(p2);
+ free(s);
+ TEST_DONE();
+
+ TEST_START("sshbuf_froms");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x01), 0);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0);
+ ASSERT_INT_EQ(sshbuf_put_cstring(p1, "hello"), 0);
+ p2 = sshbuf_new();
+ ASSERT_PTR_NE(p2, NULL);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(test_buf) - 1);
+ ASSERT_INT_EQ(sshbuf_put_stringb(p2, p1), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p2), sizeof(test_buf) + 4 - 1);
+ ASSERT_INT_EQ(sshbuf_froms(p2, &p3), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p2), 0);
+ ASSERT_PTR_NE(p3, NULL);
+ ASSERT_PTR_NE(sshbuf_ptr(p3), NULL);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p3), sizeof(test_buf) - 1);
+ ASSERT_MEM_EQ(sshbuf_ptr(p3), test_buf, sizeof(test_buf) - 1);
+ sshbuf_free(p3);
+ ASSERT_INT_EQ(sshbuf_put_stringb(p2, p1), 0);
+ ASSERT_INT_EQ(sshbuf_consume_end(p2, 1), 0);
+ ASSERT_INT_EQ(sshbuf_froms(p2, &p3), SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_PTR_EQ(p3, NULL);
+ sshbuf_free(p2);
+ sshbuf_free(p1);
+}
diff --git a/regress/unittests/sshbuf/test_sshbuf_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_fuzz.c
new file mode 100644
index 00000000..e236c82f
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf_fuzz.c
@@ -0,0 +1,132 @@
+/* $OpenBSD: test_sshbuf_fuzz.c,v 1.2 2018/10/17 23:28:05 djm Exp $ */
+/*
+ * Regress test for sshbuf.h buffer API
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "ssherr.h"
+#include "sshbuf.h"
+
+#define NUM_FUZZ_TESTS (1 << 18)
+
+void sshbuf_fuzz_tests(void);
+
+void
+sshbuf_fuzz_tests(void)
+{
+ struct sshbuf *p1;
+ u_char *dp;
+ size_t sz, sz2, i, ntests = NUM_FUZZ_TESTS;
+ u_int32_t r;
+ int ret;
+
+ if (test_is_fast())
+ ntests >>= 2;
+ if (test_is_slow())
+ ntests <<= 2;
+
+ /* NB. uses sshbuf internals */
+ TEST_START("fuzz alloc/dealloc");
+ p1 = sshbuf_new();
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, 16 * 1024), 0);
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
+ ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
+ for (i = 0; i < NUM_FUZZ_TESTS; i++) {
+ r = arc4random_uniform(10);
+ if (r == 0) {
+ /* 10% chance: small reserve */
+ r = arc4random_uniform(10);
+ fuzz_reserve:
+ sz = sshbuf_avail(p1);
+ sz2 = sshbuf_len(p1);
+ ret = sshbuf_reserve(p1, r, &dp);
+ if (ret < 0) {
+ ASSERT_PTR_EQ(dp, NULL);
+ ASSERT_SIZE_T_LT(sz, r);
+ ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2);
+ } else {
+ ASSERT_PTR_NE(dp, NULL);
+ ASSERT_SIZE_T_GE(sz, r);
+ ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - r);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 + r);
+ memset(dp, arc4random_uniform(255) + 1, r);
+ }
+ } else if (r < 3) {
+ /* 20% chance: big reserve */
+ r = arc4random_uniform(8 * 1024);
+ goto fuzz_reserve;
+ } else if (r == 3) {
+ /* 10% chance: small consume */
+ r = arc4random_uniform(10);
+ fuzz_consume:
+ sz = sshbuf_avail(p1);
+ sz2 = sshbuf_len(p1);
+ /* 50% change consume from end, otherwise start */
+ ret = ((arc4random() & 1) ?
+ sshbuf_consume : sshbuf_consume_end)(p1, r);
+ if (ret < 0) {
+ ASSERT_SIZE_T_LT(sz2, r);
+ ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2);
+ } else {
+ ASSERT_SIZE_T_GE(sz2, r);
+ ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz + r);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 - r);
+ }
+ } else if (r < 8) {
+ /* 40% chance: big consume */
+ r = arc4random_uniform(2 * 1024);
+ goto fuzz_consume;
+ } else if (r == 8) {
+ /* 10% chance: reset max size */
+ r = arc4random_uniform(16 * 1024);
+ sz = sshbuf_max_size(p1);
+ if (sshbuf_set_max_size(p1, r) < 0)
+ ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz);
+ else
+ ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), r);
+ } else {
+ if (arc4random_uniform(8192) == 0) {
+ /* tiny chance: new buffer */
+ ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
+ ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
+ sshbuf_free(p1);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1,
+ 16 * 1024), 0);
+ } else {
+ /* Almost 10%: giant reserve */
+ /* use arc4random_buf for r > 2^32 on 64 bit */
+ arc4random_buf(&r, sizeof(r));
+ while (r < SSHBUF_SIZE_MAX / 2) {
+ r <<= 1;
+ r |= arc4random() & 1;
+ }
+ goto fuzz_reserve;
+ }
+ }
+ ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
+ ASSERT_SIZE_T_LE(sshbuf_max_size(p1), 16 * 1024);
+ }
+ ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
+ ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
+ sshbuf_free(p1);
+ TEST_DONE();
+}
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_basic.c b/regress/unittests/sshbuf/test_sshbuf_getput_basic.c
new file mode 100644
index 00000000..bea89881
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf_getput_basic.c
@@ -0,0 +1,713 @@
+/* $OpenBSD: test_sshbuf_getput_basic.c,v 1.2 2019/07/14 23:33:19 djm Exp $ */
+/*
+ * Regress test for sshbuf.h buffer API
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test_helper/test_helper.h"
+#include "ssherr.h"
+#include "sshbuf.h"
+
+void sshbuf_getput_basic_tests(void);
+
+void
+sshbuf_getput_basic_tests(void)
+{
+ struct sshbuf *p1, *p2;
+ const u_char *cd;
+ u_char *d, d2[32], x[] = {
+ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x00, 0x99
+ };
+ u_int64_t v64;
+ u_int32_t v32;
+ u_int16_t v16;
+ u_char v8;
+ size_t s;
+ char *s2;
+ int r;
+ u_char bn1[] = { 0x00, 0x00, 0x00 };
+ u_char bn2[] = { 0x00, 0x00, 0x01, 0x02 };
+ u_char bn3[] = { 0x00, 0x80, 0x09 };
+ u_char bn_exp1[] = { 0x00, 0x00, 0x00, 0x00 };
+ u_char bn_exp2[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 0x02 };
+ u_char bn_exp3[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x80, 0x09 };
+
+ TEST_START("PEEK_U64");
+ ASSERT_U64_EQ(PEEK_U64(x), 0x1122334455667788ULL);
+ TEST_DONE();
+
+ TEST_START("PEEK_U32");
+ ASSERT_U32_EQ(PEEK_U32(x), 0x11223344);
+ TEST_DONE();
+
+ TEST_START("PEEK_U16");
+ ASSERT_U16_EQ(PEEK_U16(x), 0x1122);
+ TEST_DONE();
+
+ TEST_START("POKE_U64");
+ bzero(d2, sizeof(d2));
+ POKE_U64(d2, 0x1122334455667788ULL);
+ ASSERT_MEM_EQ(d2, x, 8);
+ TEST_DONE();
+
+ TEST_START("POKE_U32");
+ bzero(d2, sizeof(d2));
+ POKE_U32(d2, 0x11223344);
+ ASSERT_MEM_EQ(d2, x, 4);
+ TEST_DONE();
+
+ TEST_START("POKE_U16");
+ bzero(d2, sizeof(d2));
+ POKE_U16(d2, 0x1122);
+ ASSERT_MEM_EQ(d2, x, 2);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, 5), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 5);
+ cd = sshbuf_ptr(p1);
+ ASSERT_PTR_NE(cd, NULL);
+ ASSERT_U8_EQ(cd[0], 0x11);
+ ASSERT_U8_EQ(cd[1], 0x22);
+ ASSERT_U8_EQ(cd[2], 0x33);
+ ASSERT_U8_EQ(cd[3], 0x44);
+ ASSERT_U8_EQ(cd[4], 0x55);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get");
+ ASSERT_INT_EQ(sshbuf_get(p1, d2, 4), 0);
+ ASSERT_MEM_EQ(d2, x, 4);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
+ ASSERT_U8_EQ(*(sshbuf_ptr(p1)), 0x55);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get truncated");
+ r = sshbuf_get(p1, d2, 4);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
+ ASSERT_U8_EQ(*(sshbuf_ptr(p1)), 0x55);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put truncated");
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, 4), 0);
+ r = sshbuf_put(p1, x, 5);
+ ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_u64");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, 10), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 10);
+ ASSERT_INT_EQ(sshbuf_get_u64(p1, &v64), 0);
+ ASSERT_U64_EQ(v64, 0x1122334455667788ULL);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_u64 truncated");
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
+ r = sshbuf_get_u64(p1, &v64);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_u32");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, 10), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 10);
+ ASSERT_INT_EQ(sshbuf_get_u32(p1, &v32), 0);
+ ASSERT_U32_EQ(v32, 0x11223344);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 6);
+ ASSERT_INT_EQ(sshbuf_get_u32(p1, &v32), 0);
+ ASSERT_U32_EQ(v32, 0x55667788);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_u32 truncated");
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
+ r = sshbuf_get_u32(p1, &v32);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_u16");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, 9), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 9);
+ ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0);
+ ASSERT_U16_EQ(v16, 0x1122);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 7);
+ ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0);
+ ASSERT_U16_EQ(v16, 0x3344);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 5);
+ ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0);
+ ASSERT_U16_EQ(v16, 0x5566);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 3);
+ ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0);
+ ASSERT_U16_EQ(v16, 0x7788);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_u16 truncated");
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
+ r = sshbuf_get_u16(p1, &v16);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_u8");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, 2), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
+ ASSERT_INT_EQ(sshbuf_get_u8(p1, &v8), 0);
+ ASSERT_U8_EQ(v8, 0x11);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
+ ASSERT_INT_EQ(sshbuf_get_u8(p1, &v8), 0);
+ ASSERT_U8_EQ(v8, 0x22);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_u8 truncated");
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ r = sshbuf_get_u8(p1, &v8);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_u64");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u64(p1, 0x1122334455667788ULL), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 8);
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 8);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_u64 exact");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, 8), 0);
+ ASSERT_INT_EQ(sshbuf_put_u64(p1, 0x1122334455667788ULL), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 8);
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 8);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_u64 limited");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, 7), 0);
+ r = sshbuf_put_u64(p1, 0x1122334455667788ULL);
+ ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_u32");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x11223344), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 4);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_u32 exact");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, 4), 0);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x11223344), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 4);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_u32 limited");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, 3), 0);
+ r = sshbuf_put_u32(p1, 0x11223344);
+ ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_u16");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u16(p1, 0x1122), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 2);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_u16");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, 2), 0);
+ ASSERT_INT_EQ(sshbuf_put_u16(p1, 0x1122), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 2);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_u16 limited");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1), 0);
+ r = sshbuf_put_u16(p1, 0x1122);
+ ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_string");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4 + 4);
+ ASSERT_INT_EQ(sshbuf_get_string(p1, &d, &s), 0);
+ ASSERT_SIZE_T_EQ(s, sizeof(x));
+ ASSERT_MEM_EQ(d, x, sizeof(x));
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
+ free(d);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_string exact");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(x) + 4), 0);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
+ ASSERT_INT_EQ(sshbuf_get_string(p1, &d, &s), 0);
+ ASSERT_SIZE_T_EQ(s, sizeof(x));
+ ASSERT_MEM_EQ(d, x, sizeof(x));
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ free(d);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_string truncated");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
+ ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 3);
+ r = sshbuf_get_string(p1, &d, &s);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 3);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_string giant");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, 0xffffffff), 0);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
+ r = sshbuf_get_string(p1, &d, &s);
+ ASSERT_INT_EQ(r, SSH_ERR_STRING_TOO_LARGE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_cstring giant");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, 0xffffffff), 0);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
+ r = sshbuf_get_cstring(p1, &s2, &s);
+ ASSERT_INT_EQ(r, SSH_ERR_STRING_TOO_LARGE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_cstring embedded \\0");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
+ r = sshbuf_get_cstring(p1, &s2, NULL);
+ ASSERT_INT_EQ(r, SSH_ERR_INVALID_FORMAT);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_cstring trailing \\0");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x) - 1), 0);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x) - 1), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4 - 1);
+ ASSERT_INT_EQ(sshbuf_get_cstring(p1, &s2, &s), 0);
+ ASSERT_SIZE_T_EQ(s, sizeof(x) - 1);
+ ASSERT_MEM_EQ(s2, x, s);
+ free(s2);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_string");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_string(p1, x, sizeof(x)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
+ ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), sizeof(x));
+ ASSERT_MEM_EQ(sshbuf_ptr(p1) + 4, x, sizeof(x));
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_string limited");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(x) + 4 - 1), 0);
+ r = sshbuf_put_string(p1, x, sizeof(x));
+ ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_string giant");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ r = sshbuf_put_string(p1, (void *)0x01, 0xfffffffc);
+ ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_putf");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ r = sshbuf_putf(p1, "%s %d %x", "hello", 23, 0x5f);
+ ASSERT_INT_EQ(r, 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 11);
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), "hello 23 5f", 11);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_putb");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ p2 = sshbuf_new();
+ ASSERT_PTR_NE(p2, NULL);
+ ASSERT_INT_EQ(sshbuf_put(p1, "blahblahblah", 12), 0);
+ ASSERT_INT_EQ(sshbuf_putb(p2, p1), 0);
+ sshbuf_free(p1);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p2), 12);
+ ASSERT_MEM_EQ(sshbuf_ptr(p2), "blahblahblah", 12);
+ sshbuf_free(p2);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_bignum2_bytes empty buf");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, NULL, 0), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp1));
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp1, sizeof(bn_exp1));
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_bignum2_bytes all zeroes");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn1, sizeof(bn1)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp1));
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp1, sizeof(bn_exp1));
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_bignum2_bytes simple");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn2+2, sizeof(bn2)-2), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp2));
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp2, sizeof(bn_exp2));
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_bignum2_bytes leading zero");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn2, sizeof(bn2)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp2));
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp2, sizeof(bn_exp2));
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_bignum2_bytes neg");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn3+1, sizeof(bn3)-1), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp3));
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp3, sizeof(bn_exp3));
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_bignum2_bytes neg and leading zero");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn3, sizeof(bn3)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp3));
+ ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp3, sizeof(bn_exp3));
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_peek_u64");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
+ ASSERT_INT_EQ(sshbuf_peek_u64(p1, 0, &v64), 0);
+ ASSERT_U64_EQ(v64, 0x1122334455667788ULL);
+ ASSERT_INT_EQ(sshbuf_peek_u64(p1, 2, &v64), 0);
+ ASSERT_U64_EQ(v64, 0x3344556677880099ULL);
+ ASSERT_INT_EQ(sshbuf_peek_u64(p1, 3, &v64), SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_peek_u64(p1, sizeof(x), &v64),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_peek_u64(p1, 1000, &v64),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_peek_u32");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
+ ASSERT_INT_EQ(sshbuf_peek_u32(p1, 0, &v32), 0);
+ ASSERT_U32_EQ(v32, 0x11223344);
+ ASSERT_INT_EQ(sshbuf_peek_u32(p1, 6, &v32), 0);
+ ASSERT_U32_EQ(v32, 0x77880099);
+ ASSERT_INT_EQ(sshbuf_peek_u32(p1, 7, &v32), SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_peek_u32(p1, sizeof(x), &v32),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_peek_u32(p1, 1000, &v32),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_peek_u16");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
+ ASSERT_INT_EQ(sshbuf_peek_u16(p1, 0, &v16), 0);
+ ASSERT_U16_EQ(v16, 0x1122);
+ ASSERT_INT_EQ(sshbuf_peek_u16(p1, 8, &v16), 0);
+ ASSERT_U16_EQ(v16, 0x99);
+ ASSERT_INT_EQ(sshbuf_peek_u16(p1, 9, &v16), SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_peek_u16(p1, sizeof(x), &v16),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_peek_u16(p1, 1000, &v16),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_peek_u8");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
+ ASSERT_INT_EQ(sshbuf_peek_u8(p1, 0, &v8), 0);
+ ASSERT_U8_EQ(v8, 0x11);
+ ASSERT_INT_EQ(sshbuf_peek_u8(p1, 9, &v8), 0);
+ ASSERT_U8_EQ(v8, 0x99);
+ ASSERT_INT_EQ(sshbuf_peek_u8(p1, sizeof(x), &v8),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_peek_u8(p1, 1000, &v8),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_poke_u64");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke at start of buffer */
+ ASSERT_INT_EQ(sshbuf_poke_u64(p1, 0, 0xa1b2c3d4e5f60718ULL), 0);
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "a1b2c3d4e5f607180000");
+ free(s2);
+ sshbuf_reset(p1);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke aligned with end of buffer */
+ ASSERT_INT_EQ(sshbuf_poke_u64(p1, 2, 0xa1b2c3d4e5f60718ULL), 0);
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "0000a1b2c3d4e5f60718");
+ free(s2);
+ sshbuf_reset(p1);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke past end of buffer */
+ ASSERT_INT_EQ(sshbuf_poke_u64(p1, 3, 0xa1b2c3d4e5f60718ULL),
+ SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_INT_EQ(sshbuf_poke_u64(p1, 10, 0xa1b2c3d4e5f60718ULL),
+ SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_INT_EQ(sshbuf_poke_u64(p1, 1000, 0xa1b2c3d4e5f60718ULL),
+ SSH_ERR_NO_BUFFER_SPACE);
+ /* ensure failed pokes do not modify buffer */
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "00000000000000000000");
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_poke_u32");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke at start of buffer */
+ ASSERT_INT_EQ(sshbuf_poke_u32(p1, 0, 0xa1b2c3d4), 0);
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "a1b2c3d4000000000000");
+ free(s2);
+ sshbuf_reset(p1);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke aligned with end of buffer */
+ ASSERT_INT_EQ(sshbuf_poke_u32(p1, 6, 0xa1b2c3d4), 0);
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "000000000000a1b2c3d4");
+ free(s2);
+ sshbuf_reset(p1);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke past end of buffer */
+ ASSERT_INT_EQ(sshbuf_poke_u32(p1, 7, 0xa1b2c3d4),
+ SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_INT_EQ(sshbuf_poke_u32(p1, 10, 0xa1b2c3d4),
+ SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_INT_EQ(sshbuf_poke_u32(p1, 1000, 0xa1b2c3d4),
+ SSH_ERR_NO_BUFFER_SPACE);
+ /* ensure failed pokes do not modify buffer */
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "00000000000000000000");
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_poke_u16");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke at start of buffer */
+ ASSERT_INT_EQ(sshbuf_poke_u16(p1, 0, 0xa1b2), 0);
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "a1b20000000000000000");
+ free(s2);
+ sshbuf_reset(p1);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke aligned with end of buffer */
+ ASSERT_INT_EQ(sshbuf_poke_u16(p1, 8, 0xa1b2), 0);
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "0000000000000000a1b2");
+ free(s2);
+ sshbuf_reset(p1);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke past end of buffer */
+ ASSERT_INT_EQ(sshbuf_poke_u16(p1, 9, 0xa1b2),
+ SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_INT_EQ(sshbuf_poke_u16(p1, 10, 0xa1b2),
+ SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_INT_EQ(sshbuf_poke_u16(p1, 1000, 0xa1b2),
+ SSH_ERR_NO_BUFFER_SPACE);
+ /* ensure failed pokes do not modify buffer */
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "00000000000000000000");
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_poke_u8");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke at start of buffer */
+ ASSERT_INT_EQ(sshbuf_poke_u8(p1, 0, 0xa1), 0);
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "a1000000000000000000");
+ free(s2);
+ sshbuf_reset(p1);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke aligned with end of buffer */
+ ASSERT_INT_EQ(sshbuf_poke_u8(p1, 9, 0xa1), 0);
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "000000000000000000a1");
+ free(s2);
+ sshbuf_reset(p1);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke past end of buffer */
+ ASSERT_INT_EQ(sshbuf_poke_u8(p1, 10, 0xa1), SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_INT_EQ(sshbuf_poke_u8(p1, 1000, 0xa1), SSH_ERR_NO_BUFFER_SPACE);
+ /* ensure failed pokes do not modify buffer */
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "00000000000000000000");
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_poke");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke at start of buffer */
+ ASSERT_INT_EQ(sshbuf_poke(p1, 0, "hello!", 6), 0);
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "68656c6c6f2100000000");
+ free(s2);
+ sshbuf_reset(p1);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke aligned with end of buffer */
+ ASSERT_INT_EQ(sshbuf_poke(p1, 4, "hello!", 6), 0);
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "0000000068656c6c6f21");
+ free(s2);
+ sshbuf_reset(p1);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0);
+ /* poke past end of buffer */
+ ASSERT_INT_EQ(sshbuf_poke(p1, 7, "hello!", 6),
+ SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_INT_EQ(sshbuf_poke(p1, 10, "hello!", 6),
+ SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_INT_EQ(sshbuf_poke(p1, 1000, "hello!", 6),
+ SSH_ERR_NO_BUFFER_SPACE);
+ /* ensure failed pokes do not modify buffer */
+ s2 = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(s2, NULL);
+ ASSERT_STRING_EQ(s2, "00000000000000000000");
+ sshbuf_free(p1);
+ TEST_DONE();
+}
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
new file mode 100644
index 00000000..492b3bdf
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
@@ -0,0 +1,281 @@
+/* $OpenBSD: test_sshbuf_getput_crypto.c,v 1.2 2019/01/21 12:29:35 djm Exp $ */
+/*
+ * Regress test for sshbuf.h buffer API
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#ifdef WITH_OPENSSL
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/objects.h>
+#ifdef OPENSSL_HAS_NISTP256
+# include <openssl/ec.h>
+#endif
+
+#include "../test_helper/test_helper.h"
+#include "ssherr.h"
+#include "sshbuf.h"
+
+void sshbuf_getput_crypto_tests(void);
+
+void
+sshbuf_getput_crypto_tests(void)
+{
+ struct sshbuf *p1;
+ BIGNUM *bn, *bn2;
+ const char *hexbn1 = "0102030405060708090a0b0c0d0e0f10";
+ /* This one has MSB set to test bignum2 encoding negative-avoidance */
+ const char *hexbn2 = "f0e0d0c0b0a0908070605040302010007fff11";
+ u_char expbn1[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ };
+ u_char expbn2[] = {
+ 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
+ 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
+ 0x7f, 0xff, 0x11
+ };
+#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
+ const u_char *d;
+ size_t s;
+ BIGNUM *bn_x, *bn_y;
+ int ec256_nid = NID_X9_62_prime256v1;
+ char *ec256_x = "0C828004839D0106AA59575216191357"
+ "34B451459DADB586677EF9DF55784999";
+ char *ec256_y = "4D196B50F0B4E94B3C73E3A9D4CD9DF2"
+ "C8F9A35E42BDD047550F69D80EC23CD4";
+ u_char expec256[] = {
+ 0x04,
+ 0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06,
+ 0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57,
+ 0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86,
+ 0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99,
+ 0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b,
+ 0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2,
+ 0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47,
+ 0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4
+ };
+ EC_KEY *eck;
+ EC_POINT *ecp;
+#endif
+ int r;
+
+#define MKBN(b, bnn) \
+ do { \
+ bnn = NULL; \
+ ASSERT_INT_GT(BN_hex2bn(&bnn, b), 0); \
+ } while (0)
+
+ TEST_START("sshbuf_put_bignum2");
+ MKBN(hexbn1, bn);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 4);
+ ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn));
+ ASSERT_MEM_EQ(sshbuf_ptr(p1) + 4, expbn1, sizeof(expbn1));
+ BN_free(bn);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_bignum2 limited");
+ MKBN(hexbn1, bn);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 3), 0);
+ r = sshbuf_put_bignum2(p1, bn);
+ ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ BN_free(bn);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_bignum2 bn2");
+ MKBN(hexbn2, bn);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4 + 1); /* MSB */
+ ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn) + 1);
+ ASSERT_U8_EQ(*(sshbuf_ptr(p1) + 4), 0x00);
+ ASSERT_MEM_EQ(sshbuf_ptr(p1) + 5, expbn2, sizeof(expbn2));
+ BN_free(bn);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_put_bignum2 bn2 limited");
+ MKBN(hexbn2, bn);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn2) + 3), 0);
+ r = sshbuf_put_bignum2(p1, bn);
+ ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
+ BN_free(bn);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_bignum2");
+ MKBN(hexbn1, bn);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0);
+ ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + sizeof(expbn1));
+ ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0);
+ bn2 = NULL;
+ ASSERT_INT_EQ(sshbuf_get_bignum2(p1, &bn2), 0);
+ ASSERT_BIGNUM_EQ(bn, bn2);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
+ BN_free(bn);
+ BN_free(bn2);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_bignum2 truncated");
+ MKBN(hexbn1, bn);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0);
+ ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1) - 1), 0);
+ bn2 = NULL;
+ r = sshbuf_get_bignum2(p1, &bn2);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 3);
+ BN_free(bn);
+ BN_free(bn2);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_bignum2 giant");
+ MKBN(hexbn1, bn);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, 65536), 0);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 65536, NULL), 0);
+ bn2 = NULL;
+ r = sshbuf_get_bignum2(p1, &bn2);
+ ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_TOO_LARGE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 65536 + 4);
+ BN_free(bn);
+ BN_free(bn2);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_bignum2 bn2");
+ MKBN(hexbn2, bn);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0); /* MSB */
+ ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0);
+ ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + 1 + sizeof(expbn2));
+ ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0);
+ bn2 = NULL;
+ ASSERT_INT_EQ(sshbuf_get_bignum2(p1, &bn2), 0);
+ ASSERT_BIGNUM_EQ(bn, bn2);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
+ BN_free(bn);
+ BN_free(bn2);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_bignum2 bn2 truncated");
+ MKBN(hexbn2, bn);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0);
+ ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0);
+ ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2) - 1), 0);
+ bn2 = NULL;
+ r = sshbuf_get_bignum2(p1, &bn2);
+ ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 1 + 4 - 1);
+ BN_free(bn);
+ BN_free(bn2);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_bignum2 bn2 negative");
+ MKBN(hexbn2, bn);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0);
+ ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0);
+ bn2 = NULL;
+ r = sshbuf_get_bignum2(p1, &bn2);
+ ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_IS_NEGATIVE);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4);
+ BN_free(bn);
+ BN_free(bn2);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
+ TEST_START("sshbuf_put_ec");
+ eck = EC_KEY_new_by_curve_name(ec256_nid);
+ ASSERT_PTR_NE(eck, NULL);
+ ecp = EC_POINT_new(EC_KEY_get0_group(eck));
+ ASSERT_PTR_NE(ecp, NULL);
+ MKBN(ec256_x, bn_x);
+ MKBN(ec256_y, bn_y);
+ ASSERT_INT_EQ(EC_POINT_set_affine_coordinates_GFp(
+ EC_KEY_get0_group(eck), ecp, bn_x, bn_y, NULL), 1);
+ ASSERT_INT_EQ(EC_KEY_set_public_key(eck, ecp), 1);
+ BN_free(bn_x);
+ BN_free(bn_y);
+ EC_POINT_free(ecp);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_eckey(p1, eck), 0);
+ ASSERT_INT_EQ(sshbuf_get_string_direct(p1, &d, &s), 0);
+ ASSERT_SIZE_T_EQ(s, sizeof(expec256));
+ ASSERT_MEM_EQ(d, expec256, sizeof(expec256));
+ sshbuf_free(p1);
+ EC_KEY_free(eck);
+ TEST_DONE();
+
+ TEST_START("sshbuf_get_ec");
+ eck = EC_KEY_new_by_curve_name(ec256_nid);
+ ASSERT_PTR_NE(eck, NULL);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_string(p1, expec256, sizeof(expec256)), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expec256) + 4);
+ ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0);
+ ASSERT_INT_EQ(sshbuf_get_eckey(p1, eck), 0);
+ bn_x = BN_new();
+ bn_y = BN_new();
+ ASSERT_PTR_NE(bn_x, NULL);
+ ASSERT_PTR_NE(bn_y, NULL);
+ ASSERT_INT_EQ(EC_POINT_get_affine_coordinates_GFp(
+ EC_KEY_get0_group(eck), EC_KEY_get0_public_key(eck),
+ bn_x, bn_y, NULL), 1);
+ MKBN(ec256_x, bn);
+ MKBN(ec256_y, bn2);
+ ASSERT_INT_EQ(BN_cmp(bn_x, bn), 0);
+ ASSERT_INT_EQ(BN_cmp(bn_y, bn2), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
+ sshbuf_free(p1);
+ EC_KEY_free(eck);
+ BN_free(bn_x);
+ BN_free(bn_y);
+ BN_free(bn);
+ BN_free(bn2);
+ TEST_DONE();
+#endif
+}
+
+#endif /* WITH_OPENSSL */
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
new file mode 100644
index 00000000..1ca30be9
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
@@ -0,0 +1,131 @@
+/* $OpenBSD: test_sshbuf_getput_fuzz.c,v 1.4 2019/01/21 12:29:35 djm Exp $ */
+/*
+ * Regress test for sshbuf.h buffer API
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/objects.h>
+#ifdef OPENSSL_HAS_NISTP256
+# include <openssl/ec.h>
+#endif
+
+#include "../test_helper/test_helper.h"
+#include "ssherr.h"
+#include "sshbuf.h"
+
+void sshbuf_getput_fuzz_tests(void);
+
+static void
+attempt_parse_blob(u_char *blob, size_t len)
+{
+ struct sshbuf *p1;
+#ifdef WITH_OPENSSL
+ BIGNUM *bn;
+#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
+ EC_KEY *eck;
+#endif /* defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) */
+#endif /* WITH_OPENSSL */
+ u_char *s;
+ size_t l;
+ u_int8_t u8;
+ u_int16_t u16;
+ u_int32_t u32;
+ u_int64_t u64;
+
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put(p1, blob, len), 0);
+ sshbuf_get_u8(p1, &u8);
+ sshbuf_get_u16(p1, &u16);
+ sshbuf_get_u32(p1, &u32);
+ sshbuf_get_u64(p1, &u64);
+ if (sshbuf_get_string(p1, &s, &l) == 0) {
+ bzero(s, l);
+ free(s);
+ }
+#ifdef WITH_OPENSSL
+ bn = NULL;
+ sshbuf_get_bignum2(p1, &bn);
+ BN_clear_free(bn);
+#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
+ eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ ASSERT_PTR_NE(eck, NULL);
+ sshbuf_get_eckey(p1, eck);
+ EC_KEY_free(eck);
+#endif /* defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) */
+#endif /* WITH_OPENSSL */
+ sshbuf_free(p1);
+}
+
+
+static void
+onerror(void *fuzz)
+{
+ fprintf(stderr, "Failed during fuzz:\n");
+ fuzz_dump((struct fuzz *)fuzz);
+}
+
+void
+sshbuf_getput_fuzz_tests(void)
+{
+ u_char blob[] = {
+ /* u8 */
+ 0xd0,
+ /* u16 */
+ 0xc0, 0xde,
+ /* u32 */
+ 0xfa, 0xce, 0xde, 0xad,
+ /* u64 */
+ 0xfe, 0xed, 0xac, 0x1d, 0x1f, 0x1c, 0xbe, 0xef,
+ /* string */
+ 0x00, 0x00, 0x00, 0x09,
+ 'O', ' ', 'G', 'o', 'r', 'g', 'o', 'n', '!',
+ /* bignum2 */
+ 0x00, 0x00, 0x00, 0x14,
+ 0x00,
+ 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
+ 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
+ 0x7f, 0xff, 0x11,
+ /* EC point (NIST-256 curve) */
+ 0x00, 0x00, 0x00, 0x41,
+ 0x04,
+ 0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06,
+ 0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57,
+ 0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86,
+ 0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99,
+ 0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b,
+ 0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2,
+ 0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47,
+ 0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4,
+ };
+ struct fuzz *fuzz;
+ u_int fuzzers = FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP |
+ FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP |
+ FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END;
+
+ if (test_is_fast())
+ fuzzers &= ~(FUZZ_2_BYTE_FLIP|FUZZ_2_BIT_FLIP);
+
+ TEST_START("fuzz blob parsing");
+ fuzz = fuzz_begin(fuzzers, blob, sizeof(blob));
+ TEST_ONERROR(onerror, fuzz);
+ for(; !fuzz_done(fuzz); fuzz_next(fuzz))
+ attempt_parse_blob(blob, sizeof(blob));
+ fuzz_cleanup(fuzz);
+ TEST_DONE();
+ TEST_ONERROR(NULL, NULL);
+}
+
diff --git a/regress/unittests/sshbuf/test_sshbuf_misc.c b/regress/unittests/sshbuf/test_sshbuf_misc.c
new file mode 100644
index 00000000..c53db937
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf_misc.c
@@ -0,0 +1,218 @@
+/* $OpenBSD: test_sshbuf_misc.c,v 1.4 2019/07/16 22:16:49 djm Exp $ */
+/*
+ * Regress test for sshbuf.h buffer API
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "sshbuf.h"
+#include "ssherr.h"
+
+void sshbuf_misc_tests(void);
+
+void
+sshbuf_misc_tests(void)
+{
+ struct sshbuf *p1;
+ char tmp[512], msg[] = "imploring ping silence ping over", *p;
+ FILE *out;
+ size_t sz;
+
+ TEST_START("sshbuf_dump");
+ out = tmpfile();
+ ASSERT_PTR_NE(out, NULL);
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0);
+ sshbuf_dump(p1, out);
+ fflush(out);
+ rewind(out);
+ sz = fread(tmp, 1, sizeof(tmp), out);
+ ASSERT_INT_EQ(ferror(out), 0);
+ ASSERT_INT_NE(feof(out), 0);
+ ASSERT_SIZE_T_GT(sz, 0);
+ tmp[sz] = '\0';
+ ASSERT_PTR_NE(strstr(tmp, "12 34 56 78"), NULL);
+ fclose(out);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_dtob16");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0);
+ p = sshbuf_dtob16(p1);
+ ASSERT_PTR_NE(p, NULL);
+ ASSERT_STRING_EQ(p, "12345678");
+ free(p);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_dtob64_string len 1");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0);
+ p = sshbuf_dtob64_string(p1, 0);
+ ASSERT_PTR_NE(p, NULL);
+ ASSERT_STRING_EQ(p, "EQ==");
+ free(p);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_dtob64_string len 2");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0);
+ ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x22), 0);
+ p = sshbuf_dtob64_string(p1, 0);
+ ASSERT_PTR_NE(p, NULL);
+ ASSERT_STRING_EQ(p, "ESI=");
+ free(p);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_dtob64_string len 3");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0);
+ ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x22), 0);
+ ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x33), 0);
+ p = sshbuf_dtob64_string(p1, 0);
+ ASSERT_PTR_NE(p, NULL);
+ ASSERT_STRING_EQ(p, "ESIz");
+ free(p);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_dtob64_string len 8191");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_reserve(p1, 8192, NULL), 0);
+ bzero(sshbuf_mutable_ptr(p1), 8192);
+ p = sshbuf_dtob64_string(p1, 0);
+ ASSERT_PTR_NE(p, NULL);
+ ASSERT_SIZE_T_EQ(strlen(p), ((8191 + 2) / 3) * 4);
+ free(p);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_b64tod len 1");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A=="), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
+ ASSERT_U8_EQ(*sshbuf_ptr(p1), 0xd0);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_b64tod len 2");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A8="), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
+ ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), 0xd00f);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_b64tod len 4");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A/QDw=="), 0);
+ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
+ ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), 0xd00fd00f);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_dup_string");
+ p1 = sshbuf_new();
+ ASSERT_PTR_NE(p1, NULL);
+ /* Check empty buffer */
+ p = sshbuf_dup_string(p1);
+ ASSERT_PTR_NE(p, NULL);
+ ASSERT_SIZE_T_EQ(strlen(p), 0);
+ free(p);
+ /* Check buffer with string */
+ ASSERT_INT_EQ(sshbuf_put(p1, "quad1", strlen("quad1")), 0);
+ p = sshbuf_dup_string(p1);
+ ASSERT_PTR_NE(p, NULL);
+ ASSERT_SIZE_T_EQ(strlen(p), strlen("quad1"));
+ ASSERT_STRING_EQ(p, "quad1");
+ free(p);
+ /* Check buffer with terminating nul */
+ ASSERT_INT_EQ(sshbuf_put(p1, "\0", 1), 0);
+ p = sshbuf_dup_string(p1);
+ ASSERT_PTR_NE(p, NULL);
+ ASSERT_SIZE_T_EQ(strlen(p), strlen("quad1"));
+ ASSERT_STRING_EQ(p, "quad1");
+ free(p);
+ /* Check buffer with data after nul (expect failure) */
+ ASSERT_INT_EQ(sshbuf_put(p1, "quad2", strlen("quad2")), 0);
+ p = sshbuf_dup_string(p1);
+ ASSERT_PTR_EQ(p, NULL);
+ sshbuf_free(p1);
+ TEST_DONE();
+
+ TEST_START("sshbuf_cmp");
+ p1 = sshbuf_from(msg, sizeof(msg) - 1);
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_cmp(p1, 0, "i", 1), 0);
+ ASSERT_INT_EQ(sshbuf_cmp(p1, 0, "j", 1), SSH_ERR_INVALID_FORMAT);
+ ASSERT_INT_EQ(sshbuf_cmp(p1, 0, "imploring", 9), 0);
+ ASSERT_INT_EQ(sshbuf_cmp(p1, 0, "implored", 9), SSH_ERR_INVALID_FORMAT);
+ ASSERT_INT_EQ(sshbuf_cmp(p1, 10, "ping", 4), 0);
+ ASSERT_INT_EQ(sshbuf_cmp(p1, 10, "ring", 4), SSH_ERR_INVALID_FORMAT);
+ ASSERT_INT_EQ(sshbuf_cmp(p1, 28, "over", 4), 0);
+ ASSERT_INT_EQ(sshbuf_cmp(p1, 28, "rove", 4), SSH_ERR_INVALID_FORMAT);
+ ASSERT_INT_EQ(sshbuf_cmp(p1, 28, "overt", 5),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_cmp(p1, 32, "ping", 4),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_cmp(p1, 1000, "silence", 7),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_cmp(p1, 0, msg, sizeof(msg) - 1), 0);
+ TEST_DONE();
+
+ TEST_START("sshbuf_find");
+ p1 = sshbuf_from(msg, sizeof(msg) - 1);
+ ASSERT_PTR_NE(p1, NULL);
+ ASSERT_INT_EQ(sshbuf_find(p1, 0, "i", 1, &sz), 0);
+ ASSERT_SIZE_T_EQ(sz, 0);
+ ASSERT_INT_EQ(sshbuf_find(p1, 0, "j", 1, &sz), SSH_ERR_INVALID_FORMAT);
+ ASSERT_INT_EQ(sshbuf_find(p1, 0, "imploring", 9, &sz), 0);
+ ASSERT_SIZE_T_EQ(sz, 0);
+ ASSERT_INT_EQ(sshbuf_find(p1, 0, "implored", 9, &sz),
+ SSH_ERR_INVALID_FORMAT);
+ ASSERT_INT_EQ(sshbuf_find(p1, 3, "ping", 4, &sz), 0);
+ ASSERT_SIZE_T_EQ(sz, 10);
+ ASSERT_INT_EQ(sshbuf_find(p1, 11, "ping", 4, &sz), 0);
+ ASSERT_SIZE_T_EQ(sz, 23);
+ ASSERT_INT_EQ(sshbuf_find(p1, 20, "over", 4, &sz), 0);
+ ASSERT_SIZE_T_EQ(sz, 28);
+ ASSERT_INT_EQ(sshbuf_find(p1, 28, "over", 4, &sz), 0);
+ ASSERT_SIZE_T_EQ(sz, 28);
+ ASSERT_INT_EQ(sshbuf_find(p1, 28, "rove", 4, &sz),
+ SSH_ERR_INVALID_FORMAT);
+ ASSERT_INT_EQ(sshbuf_find(p1, 28, "overt", 5, &sz),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_find(p1, 32, "ping", 4, &sz),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_find(p1, 1000, "silence", 7, &sz),
+ SSH_ERR_MESSAGE_INCOMPLETE);
+ ASSERT_INT_EQ(sshbuf_find(p1, 0, msg + 1, sizeof(msg) - 2, &sz), 0);
+ ASSERT_SIZE_T_EQ(sz, 1);
+ TEST_DONE();
+}
+
diff --git a/regress/unittests/sshbuf/tests.c b/regress/unittests/sshbuf/tests.c
new file mode 100644
index 00000000..29916a10
--- /dev/null
+++ b/regress/unittests/sshbuf/tests.c
@@ -0,0 +1,30 @@
+/* $OpenBSD: tests.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
+/*
+ * Regress test for sshbuf.h buffer API
+ *
+ * Placed in the public domain
+ */
+
+#include "../test_helper/test_helper.h"
+
+void sshbuf_tests(void);
+void sshbuf_getput_basic_tests(void);
+void sshbuf_getput_crypto_tests(void);
+void sshbuf_misc_tests(void);
+void sshbuf_fuzz_tests(void);
+void sshbuf_getput_fuzz_tests(void);
+void sshbuf_fixed(void);
+
+void
+tests(void)
+{
+ sshbuf_tests();
+ sshbuf_getput_basic_tests();
+#ifdef WITH_OPENSSL
+ sshbuf_getput_crypto_tests();
+#endif
+ sshbuf_misc_tests();
+ sshbuf_fuzz_tests();
+ sshbuf_getput_fuzz_tests();
+ sshbuf_fixed();
+}
diff --git a/regress/unittests/sshkey/Makefile b/regress/unittests/sshkey/Makefile
new file mode 100644
index 00000000..29c9b3ba
--- /dev/null
+++ b/regress/unittests/sshkey/Makefile
@@ -0,0 +1,26 @@
+# $OpenBSD: Makefile,v 1.10 2020/04/06 09:43:56 dtucker Exp $
+
+PROG=test_sshkey
+SRCS=tests.c test_sshkey.c test_file.c test_fuzz.c common.c
+
+# From usr.bin/ssh
+SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
+SRCS+=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+=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/sshkey/common.c b/regress/unittests/sshkey/common.c
new file mode 100644
index 00000000..effea578
--- /dev/null
+++ b/regress/unittests/sshkey/common.c
@@ -0,0 +1,164 @@
+/* $OpenBSD: common.c,v 1.4 2020/01/26 00:09:50 djm Exp $ */
+/*
+ * Helpers for key API tests
+ *
+ * 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>
+
+#ifdef WITH_OPENSSL
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/objects.h>
+#ifdef OPENSSL_HAS_NISTP256
+# include <openssl/ec.h>
+#endif /* OPENSSL_HAS_NISTP256 */
+#endif /* WITH_OPENSSL */
+
+#include "openbsd-compat/openssl-compat.h"
+
+#include "../test_helper/test_helper.h"
+
+#include "ssherr.h"
+#include "authfile.h"
+#include "sshkey.h"
+#include "sshbuf.h"
+
+#include "common.h"
+
+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;
+}
+
+struct sshbuf *
+load_text_file(const char *name)
+{
+ struct sshbuf *ret = load_file(name);
+ const u_char *p;
+
+ /* Trim whitespace at EOL */
+ for (p = sshbuf_ptr(ret); sshbuf_len(ret) > 0;) {
+ if (p[sshbuf_len(ret) - 1] == '\r' ||
+ p[sshbuf_len(ret) - 1] == '\t' ||
+ p[sshbuf_len(ret) - 1] == ' ' ||
+ p[sshbuf_len(ret) - 1] == '\n')
+ ASSERT_INT_EQ(sshbuf_consume_end(ret, 1), 0);
+ else
+ break;
+ }
+ /* \0 terminate */
+ ASSERT_INT_EQ(sshbuf_put_u8(ret, 0), 0);
+ return ret;
+}
+
+#ifdef WITH_OPENSSL
+BIGNUM *
+load_bignum(const char *name)
+{
+ BIGNUM *ret = NULL;
+ struct sshbuf *buf;
+
+ buf = load_text_file(name);
+ ASSERT_INT_NE(BN_hex2bn(&ret, (const char *)sshbuf_ptr(buf)), 0);
+ sshbuf_free(buf);
+ return ret;
+}
+
+const BIGNUM *
+rsa_n(struct sshkey *k)
+{
+ const BIGNUM *n = NULL;
+
+ ASSERT_PTR_NE(k, NULL);
+ ASSERT_PTR_NE(k->rsa, NULL);
+ RSA_get0_key(k->rsa, &n, NULL, NULL);
+ return n;
+}
+
+const BIGNUM *
+rsa_e(struct sshkey *k)
+{
+ const BIGNUM *e = NULL;
+
+ ASSERT_PTR_NE(k, NULL);
+ ASSERT_PTR_NE(k->rsa, NULL);
+ RSA_get0_key(k->rsa, NULL, &e, NULL);
+ return e;
+}
+
+const BIGNUM *
+rsa_p(struct sshkey *k)
+{
+ const BIGNUM *p = NULL;
+
+ ASSERT_PTR_NE(k, NULL);
+ ASSERT_PTR_NE(k->rsa, NULL);
+ RSA_get0_factors(k->rsa, &p, NULL);
+ return p;
+}
+
+const BIGNUM *
+rsa_q(struct sshkey *k)
+{
+ const BIGNUM *q = NULL;
+
+ ASSERT_PTR_NE(k, NULL);
+ ASSERT_PTR_NE(k->rsa, NULL);
+ RSA_get0_factors(k->rsa, NULL, &q);
+ return q;
+}
+
+const BIGNUM *
+dsa_g(struct sshkey *k)
+{
+ const BIGNUM *g = NULL;
+
+ ASSERT_PTR_NE(k, NULL);
+ ASSERT_PTR_NE(k->dsa, NULL);
+ DSA_get0_pqg(k->dsa, NULL, NULL, &g);
+ return g;
+}
+
+const BIGNUM *
+dsa_pub_key(struct sshkey *k)
+{
+ const BIGNUM *pub_key = NULL;
+
+ ASSERT_PTR_NE(k, NULL);
+ ASSERT_PTR_NE(k->dsa, NULL);
+ DSA_get0_key(k->dsa, &pub_key, NULL);
+ return pub_key;
+}
+
+const BIGNUM *
+dsa_priv_key(struct sshkey *k)
+{
+ const BIGNUM *priv_key = NULL;
+
+ ASSERT_PTR_NE(k, NULL);
+ ASSERT_PTR_NE(k->dsa, NULL);
+ DSA_get0_key(k->dsa, NULL, &priv_key);
+ return priv_key;
+}
+#endif /* WITH_OPENSSL */
+
diff --git a/regress/unittests/sshkey/common.h b/regress/unittests/sshkey/common.h
new file mode 100644
index 00000000..7a514fdc
--- /dev/null
+++ b/regress/unittests/sshkey/common.h
@@ -0,0 +1,25 @@
+/* $OpenBSD: common.h,v 1.2 2018/09/13 09:03:20 djm Exp $ */
+/*
+ * Helpers for key API tests
+ *
+ * Placed in the public domain
+ */
+
+/* Load a binary file into a buffer */
+struct sshbuf *load_file(const char *name);
+
+/* Load a text file into a buffer */
+struct sshbuf *load_text_file(const char *name);
+
+/* Load a bignum from a file */
+BIGNUM *load_bignum(const char *name);
+
+/* Accessors for key components */
+const BIGNUM *rsa_n(struct sshkey *k);
+const BIGNUM *rsa_e(struct sshkey *k);
+const BIGNUM *rsa_p(struct sshkey *k);
+const BIGNUM *rsa_q(struct sshkey *k);
+const BIGNUM *dsa_g(struct sshkey *k);
+const BIGNUM *dsa_pub_key(struct sshkey *k);
+const BIGNUM *dsa_priv_key(struct sshkey *k);
+
diff --git a/regress/unittests/sshkey/mktestdata.sh b/regress/unittests/sshkey/mktestdata.sh
new file mode 100755
index 00000000..8efe6dd0
--- /dev/null
+++ b/regress/unittests/sshkey/mktestdata.sh
@@ -0,0 +1,181 @@
+#!/bin/sh
+# $OpenBSD: mktestdata.sh,v 1.10 2020/05/01 04:03:14 djm Exp $
+
+PW=mekmitasdigoat
+
+rsa_params() {
+ _in="$1"
+ _outbase="$2"
+ set -e
+ openssl rsa -noout -text -in $_in | \
+ awk '/^modulus:$/,/^publicExponent:/' | \
+ grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.n
+ openssl rsa -noout -text -in $_in | \
+ awk '/^prime1:$/,/^prime2:/' | \
+ grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.p
+ openssl rsa -noout -text -in $_in | \
+ awk '/^prime2:$/,/^exponent1:/' | \
+ grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.q
+ for x in n p q ; do
+ echo "" >> ${_outbase}.$x
+ echo ============ ${_outbase}.$x
+ cat ${_outbase}.$x
+ echo ============
+ done
+}
+
+dsa_params() {
+ _in="$1"
+ _outbase="$2"
+ set -e
+ openssl dsa -noout -text -in $_in | \
+ awk '/^priv:$/,/^pub:/' | \
+ grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.priv
+ openssl dsa -noout -text -in $_in | \
+ awk '/^pub:/,/^P:/' | #\
+ grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.pub
+ openssl dsa -noout -text -in $_in | \
+ awk '/^G:/,0' | \
+ grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.g
+ for x in priv pub g ; do
+ echo "" >> ${_outbase}.$x
+ echo ============ ${_outbase}.$x
+ cat ${_outbase}.$x
+ echo ============
+ done
+}
+
+ecdsa_params() {
+ _in="$1"
+ _outbase="$2"
+ set -e
+ openssl ec -noout -text -in $_in | \
+ awk '/^priv:$/,/^pub:/' | \
+ grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.priv
+ openssl ec -noout -text -in $_in | \
+ awk '/^pub:/,/^ASN1 OID:/' | #\
+ grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.pub
+ openssl ec -noout -text -in $_in | \
+ grep "ASN1 OID:" | \
+ sed 's/.*: //;s/ *$//' | tr -d '\n' > ${_outbase}.curve
+ for x in priv pub curve ; do
+ echo "" >> ${_outbase}.$x
+ echo ============ ${_outbase}.$x
+ cat ${_outbase}.$x
+ echo ============
+ done
+}
+
+set -ex
+
+cd testdata
+
+rm -f rsa_1 dsa_1 ecdsa_1 ed25519_1
+rm -f rsa_2 dsa_2 ecdsa_2 ed25519_2
+rm -f rsa_n dsa_n ecdsa_n # new-format keys
+rm -f rsa_1_pw dsa_1_pw ecdsa_1_pw ed25519_1_pw
+rm -f rsa_n_pw dsa_n_pw ecdsa_n_pw
+rm -f pw *.pub *.bn.* *.param.* *.fp *.fp.bb
+
+ssh-keygen -t rsa -b 1024 -C "RSA test key #1" -N "" -f rsa_1 -m PEM
+ssh-keygen -t dsa -b 1024 -C "DSA test key #1" -N "" -f dsa_1 -m PEM
+ssh-keygen -t ecdsa -b 256 -C "ECDSA test key #1" -N "" -f ecdsa_1 -m PEM
+ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_1
+
+ssh-keygen -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
+
+cp rsa_1 rsa_n
+cp dsa_1 dsa_n
+cp ecdsa_1 ecdsa_n
+
+ssh-keygen -pf rsa_n -N ""
+ssh-keygen -pf dsa_n -N ""
+ssh-keygen -pf ecdsa_n -N ""
+
+cp rsa_1 rsa_1_pw
+cp dsa_1 dsa_1_pw
+cp ecdsa_1 ecdsa_1_pw
+cp ed25519_1 ed25519_1_pw
+cp rsa_1 rsa_n_pw
+cp dsa_1 dsa_n_pw
+cp ecdsa_1 ecdsa_n_pw
+
+ssh-keygen -pf rsa_1_pw -m PEM -N "$PW"
+ssh-keygen -pf dsa_1_pw -m PEM -N "$PW"
+ssh-keygen -pf ecdsa_1_pw -m PEM -N "$PW"
+ssh-keygen -pf ed25519_1_pw -N "$PW"
+ssh-keygen -pf rsa_n_pw -N "$PW"
+ssh-keygen -pf dsa_n_pw -N "$PW"
+ssh-keygen -pf ecdsa_n_pw -N "$PW"
+
+rsa_params rsa_1 rsa_1.param
+rsa_params rsa_2 rsa_2.param
+dsa_params dsa_1 dsa_1.param
+dsa_params dsa_1 dsa_1.param
+ecdsa_params ecdsa_1 ecdsa_1.param
+ecdsa_params ecdsa_2 ecdsa_2.param
+# XXX ed25519 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 \
+ -V 19990101:20110101 -z 1 rsa_1.pub
+ssh-keygen -s rsa_2 -I hugo -n user1,user2 \
+ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \
+ -V 19990101:20110101 -z 2 dsa_1.pub
+ssh-keygen -s rsa_2 -I hugo -n user1,user2 \
+ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \
+ -V 19990101:20110101 -z 3 ecdsa_1.pub
+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
+
+# Make a few RSA variant signature too.
+cp rsa_1 rsa_1_sha1
+cp rsa_1 rsa_1_sha512
+cp rsa_1.pub rsa_1_sha1.pub
+cp rsa_1.pub rsa_1_sha512.pub
+ssh-keygen -s rsa_2 -I hugo -n user1,user2 -t ssh-rsa \
+ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \
+ -V 19990101:20110101 -z 1 rsa_1_sha1.pub
+ssh-keygen -s rsa_2 -I hugo -n user1,user2 -t rsa-sha2-512 \
+ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \
+ -V 19990101:20110101 -z 1 rsa_1_sha512.pub
+
+ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \
+ -V 19990101:20110101 -z 5 rsa_1.pub
+ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \
+ -V 19990101:20110101 -z 6 dsa_1.pub
+ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \
+ -V 19990101:20110101 -z 7 ecdsa_1.pub
+ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \
+ -V 19990101:20110101 -z 8 ed25519_1.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 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 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 -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 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)
+
+echo "$PW" > pw
diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c
new file mode 100644
index 00000000..55627bc1
--- /dev/null
+++ b/regress/unittests/sshkey/test_file.c
@@ -0,0 +1,427 @@
+/* $OpenBSD: test_file.c,v 1.8 2018/09/13 09:03:20 djm Exp $ */
+/*
+ * Regress test for sshkey.h key management 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>
+
+#ifdef WITH_OPENSSL
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/objects.h>
+#ifdef OPENSSL_HAS_NISTP256
+# include <openssl/ec.h>
+#endif /* OPENSSL_HAS_NISTP256 */
+#endif /* WITH_OPENSSL */
+
+#include "../test_helper/test_helper.h"
+
+#include "ssherr.h"
+#include "authfile.h"
+#include "sshkey.h"
+#include "sshbuf.h"
+#include "digest.h"
+
+#include "common.h"
+
+void sshkey_file_tests(void);
+
+void
+sshkey_file_tests(void)
+{
+ struct sshkey *k1, *k2;
+ struct sshbuf *buf, *pw;
+#ifdef WITH_OPENSSL
+ BIGNUM *a, *b, *c;
+#endif
+ char *cp;
+
+ TEST_START("load passphrase");
+ pw = load_text_file("pw");
+ TEST_DONE();
+
+
+#ifdef WITH_OPENSSL
+ TEST_START("parse RSA from private");
+ buf = load_file("rsa_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k1, NULL);
+ a = load_bignum("rsa_1.param.n");
+ b = load_bignum("rsa_1.param.p");
+ c = load_bignum("rsa_1.param.q");
+ ASSERT_BIGNUM_EQ(rsa_n(k1), a);
+ ASSERT_BIGNUM_EQ(rsa_p(k1), b);
+ ASSERT_BIGNUM_EQ(rsa_q(k1), c);
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ TEST_DONE();
+
+ TEST_START("parse RSA from private w/ passphrase");
+ buf = load_file("rsa_1_pw");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
+ (const char *)sshbuf_ptr(pw), &k2, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("parse RSA from new-format");
+ buf = load_file("rsa_n");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k2, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("parse RSA from new-format w/ passphrase");
+ buf = load_file("rsa_n_pw");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
+ (const char *)sshbuf_ptr(pw), &k2, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load RSA from public");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2,
+ NULL), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load RSA cert with SHA1 signature");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha1"), &k2), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(k2->type, KEY_RSA_CERT);
+ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
+ ASSERT_STRING_EQ(k2->cert->signature_type, "ssh-rsa");
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load RSA cert with SHA512 signature");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha512"), &k2), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(k2->type, KEY_RSA_CERT);
+ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
+ ASSERT_STRING_EQ(k2->cert->signature_type, "rsa-sha2-512");
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load RSA cert");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k2), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(k2->type, KEY_RSA_CERT);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 0);
+ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
+ TEST_DONE();
+
+ TEST_START("RSA key hex fingerprint");
+ buf = load_text_file("rsa_1.fp");
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ TEST_DONE();
+
+ TEST_START("RSA cert hex fingerprint");
+ buf = load_text_file("rsa_1-cert.fp");
+ cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("RSA key bubblebabble fingerprint");
+ buf = load_text_file("rsa_1.fp.bb");
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ TEST_DONE();
+
+ sshkey_free(k1);
+
+ TEST_START("parse DSA from private");
+ buf = load_file("dsa_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k1, NULL);
+ a = load_bignum("dsa_1.param.g");
+ b = load_bignum("dsa_1.param.priv");
+ c = load_bignum("dsa_1.param.pub");
+ ASSERT_BIGNUM_EQ(dsa_g(k1), a);
+ ASSERT_BIGNUM_EQ(dsa_priv_key(k1), b);
+ ASSERT_BIGNUM_EQ(dsa_pub_key(k1), c);
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ TEST_DONE();
+
+ TEST_START("parse DSA from private w/ passphrase");
+ buf = load_file("dsa_1_pw");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
+ (const char *)sshbuf_ptr(pw), &k2, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("parse DSA from new-format");
+ buf = load_file("dsa_n");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k2, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("parse DSA from new-format w/ passphrase");
+ buf = load_file("dsa_n_pw");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
+ (const char *)sshbuf_ptr(pw), &k2, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load DSA from public");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_1.pub"), &k2,
+ NULL), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load DSA cert");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k2), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(k2->type, KEY_DSA_CERT);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 0);
+ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
+ TEST_DONE();
+
+ TEST_START("DSA key hex fingerprint");
+ buf = load_text_file("dsa_1.fp");
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ TEST_DONE();
+
+ TEST_START("DSA cert hex fingerprint");
+ buf = load_text_file("dsa_1-cert.fp");
+ cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("DSA key bubblebabble fingerprint");
+ buf = load_text_file("dsa_1.fp.bb");
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ TEST_DONE();
+
+ sshkey_free(k1);
+
+#ifdef OPENSSL_HAS_ECC
+ TEST_START("parse ECDSA from private");
+ buf = load_file("ecdsa_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k1, NULL);
+ buf = load_text_file("ecdsa_1.param.curve");
+ ASSERT_STRING_EQ((const char *)sshbuf_ptr(buf),
+ OBJ_nid2sn(k1->ecdsa_nid));
+ sshbuf_free(buf);
+ a = load_bignum("ecdsa_1.param.priv");
+ b = load_bignum("ecdsa_1.param.pub");
+ c = EC_POINT_point2bn(EC_KEY_get0_group(k1->ecdsa),
+ EC_KEY_get0_public_key(k1->ecdsa), POINT_CONVERSION_UNCOMPRESSED,
+ NULL, NULL);
+ ASSERT_PTR_NE(c, NULL);
+ ASSERT_BIGNUM_EQ(EC_KEY_get0_private_key(k1->ecdsa), a);
+ ASSERT_BIGNUM_EQ(b, c);
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ TEST_DONE();
+
+ TEST_START("parse ECDSA from private w/ passphrase");
+ buf = load_file("ecdsa_1_pw");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
+ (const char *)sshbuf_ptr(pw), &k2, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("parse ECDSA from new-format");
+ buf = load_file("ecdsa_n");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k2, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("parse ECDSA from new-format w/ passphrase");
+ buf = load_file("ecdsa_n_pw");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
+ (const char *)sshbuf_ptr(pw), &k2, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load ECDSA from public");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_1.pub"), &k2,
+ NULL), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load ECDSA cert");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k2), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(k2->type, KEY_ECDSA_CERT);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 0);
+ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
+ TEST_DONE();
+
+ TEST_START("ECDSA key hex fingerprint");
+ buf = load_text_file("ecdsa_1.fp");
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ TEST_DONE();
+
+ TEST_START("ECDSA cert hex fingerprint");
+ buf = load_text_file("ecdsa_1-cert.fp");
+ cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("ECDSA key bubblebabble fingerprint");
+ buf = load_text_file("ecdsa_1.fp.bb");
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ TEST_DONE();
+
+ sshkey_free(k1);
+#endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
+
+ TEST_START("parse Ed25519 from private");
+ buf = load_file("ed25519_1");
+ 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);
+ /* XXX check key contents */
+ TEST_DONE();
+
+ TEST_START("parse Ed25519 from private w/ passphrase");
+ buf = load_file("ed25519_1_pw");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
+ (const char *)sshbuf_ptr(pw), &k2, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load Ed25519 from public");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_1.pub"), &k2,
+ NULL), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load Ed25519 cert");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k2), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(k2->type, KEY_ED25519_CERT);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 0);
+ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
+ TEST_DONE();
+
+ TEST_START("Ed25519 key hex fingerprint");
+ buf = load_text_file("ed25519_1.fp");
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ TEST_DONE();
+
+ TEST_START("Ed25519 cert hex fingerprint");
+ buf = load_text_file("ed25519_1-cert.fp");
+ cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("Ed25519 key bubblebabble fingerprint");
+ buf = load_text_file("ed25519_1.fp.bb");
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ TEST_DONE();
+
+ sshkey_free(k1);
+
+ sshbuf_free(pw);
+
+}
diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c
new file mode 100644
index 00000000..35981189
--- /dev/null
+++ b/regress/unittests/sshkey/test_fuzz.c
@@ -0,0 +1,390 @@
+/* $OpenBSD: test_fuzz.c,v 1.11 2019/11/25 10:32:35 djm Exp $ */
+/*
+ * Fuzz tests for key parsing
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/objects.h>
+#ifdef OPENSSL_HAS_NISTP256
+# include <openssl/ec.h>
+#endif
+
+#include "../test_helper/test_helper.h"
+
+#include "ssherr.h"
+#include "authfile.h"
+#include "sshkey.h"
+#include "sshbuf.h"
+
+#include "common.h"
+
+void sshkey_fuzz_tests(void);
+
+static void
+onerror(void *fuzz)
+{
+ fprintf(stderr, "Failed during fuzz:\n");
+ fuzz_dump((struct fuzz *)fuzz);
+}
+
+static void
+public_fuzz(struct sshkey *k)
+{
+ struct sshkey *k1;
+ struct sshbuf *buf;
+ struct fuzz *fuzz;
+ u_int fuzzers = FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
+ FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END;
+
+ if (test_is_fast())
+ fuzzers &= ~FUZZ_1_BIT_FLIP;
+ if (test_is_slow())
+ fuzzers |= FUZZ_2_BIT_FLIP | FUZZ_2_BYTE_FLIP;
+ ASSERT_PTR_NE(buf = sshbuf_new(), NULL);
+ ASSERT_INT_EQ(sshkey_putb(k, buf), 0);
+ fuzz = fuzz_begin(fuzzers, sshbuf_mutable_ptr(buf), sshbuf_len(buf));
+ ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(buf), sshbuf_len(buf),
+ &k1), 0);
+ sshkey_free(k1);
+ sshbuf_free(buf);
+ TEST_ONERROR(onerror, fuzz);
+ for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
+ if (sshkey_from_blob(fuzz_ptr(fuzz), fuzz_len(fuzz), &k1) == 0)
+ sshkey_free(k1);
+ }
+ fuzz_cleanup(fuzz);
+}
+
+static void
+sig_fuzz(struct sshkey *k, const char *sig_alg)
+{
+ struct fuzz *fuzz;
+ u_char *sig, c[] = "some junk to be signed";
+ size_t l;
+ u_int fuzzers = FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP |
+ FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END;
+
+ if (test_is_fast())
+ fuzzers &= ~FUZZ_2_BYTE_FLIP;
+ if (test_is_slow())
+ fuzzers |= FUZZ_2_BIT_FLIP;
+
+ ASSERT_INT_EQ(sshkey_sign(k, &sig, &l, c, sizeof(c),
+ sig_alg, 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);
+ free(sig);
+ TEST_ONERROR(onerror, fuzz);
+ for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
+ /* Ensure 1-bit difference at least */
+ if (fuzz_matches_original(fuzz))
+ continue;
+ ASSERT_INT_NE(sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz),
+ c, sizeof(c), NULL, 0, NULL), 0);
+ }
+ fuzz_cleanup(fuzz);
+}
+
+#define NUM_FAST_BASE64_TESTS 1024
+
+void
+sshkey_fuzz_tests(void)
+{
+ struct sshkey *k1;
+ struct sshbuf *buf, *fuzzed;
+ struct fuzz *fuzz;
+ int r, i;
+
+#ifdef WITH_OPENSSL
+ TEST_START("fuzz RSA private");
+ buf = load_file("rsa_1");
+ fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
+ sshbuf_len(buf));
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshkey_free(k1);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
+ TEST_ONERROR(onerror, fuzz);
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
+ r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
+ ASSERT_INT_EQ(r, 0);
+ if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
+ sshkey_free(k1);
+ sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
+ }
+ sshbuf_free(fuzzed);
+ fuzz_cleanup(fuzz);
+ TEST_DONE();
+
+ TEST_START("fuzz RSA new-format private");
+ buf = load_file("rsa_n");
+ fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
+ sshbuf_len(buf));
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshkey_free(k1);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
+ TEST_ONERROR(onerror, fuzz);
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
+ r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
+ ASSERT_INT_EQ(r, 0);
+ if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
+ sshkey_free(k1);
+ sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
+ }
+ sshbuf_free(fuzzed);
+ fuzz_cleanup(fuzz);
+ TEST_DONE();
+
+ TEST_START("fuzz DSA private");
+ buf = load_file("dsa_1");
+ fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
+ sshbuf_len(buf));
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshkey_free(k1);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
+ TEST_ONERROR(onerror, fuzz);
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
+ r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
+ ASSERT_INT_EQ(r, 0);
+ if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
+ sshkey_free(k1);
+ sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
+ }
+ sshbuf_free(fuzzed);
+ fuzz_cleanup(fuzz);
+ TEST_DONE();
+
+ TEST_START("fuzz DSA new-format private");
+ buf = load_file("dsa_n");
+ fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
+ sshbuf_len(buf));
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshkey_free(k1);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
+ TEST_ONERROR(onerror, fuzz);
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
+ r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
+ ASSERT_INT_EQ(r, 0);
+ if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
+ sshkey_free(k1);
+ sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
+ }
+ sshbuf_free(fuzzed);
+ fuzz_cleanup(fuzz);
+ TEST_DONE();
+
+#ifdef OPENSSL_HAS_ECC
+ TEST_START("fuzz ECDSA private");
+ buf = load_file("ecdsa_1");
+ fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
+ sshbuf_len(buf));
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshkey_free(k1);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
+ TEST_ONERROR(onerror, fuzz);
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
+ r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
+ ASSERT_INT_EQ(r, 0);
+ if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
+ sshkey_free(k1);
+ sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
+ }
+ sshbuf_free(fuzzed);
+ fuzz_cleanup(fuzz);
+ TEST_DONE();
+
+ TEST_START("fuzz ECDSA new-format private");
+ buf = load_file("ecdsa_n");
+ fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
+ sshbuf_len(buf));
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshkey_free(k1);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
+ TEST_ONERROR(onerror, fuzz);
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
+ r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
+ ASSERT_INT_EQ(r, 0);
+ if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
+ sshkey_free(k1);
+ sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
+ }
+ sshbuf_free(fuzzed);
+ fuzz_cleanup(fuzz);
+ TEST_DONE();
+#endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
+
+ TEST_START("fuzz Ed25519 private");
+ buf = load_file("ed25519_1");
+ fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
+ sshbuf_len(buf));
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshkey_free(k1);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
+ TEST_ONERROR(onerror, fuzz);
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
+ r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
+ ASSERT_INT_EQ(r, 0);
+ if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
+ sshkey_free(k1);
+ sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
+ }
+ sshbuf_free(fuzzed);
+ fuzz_cleanup(fuzz);
+ TEST_DONE();
+
+#ifdef WITH_OPENSSL
+ TEST_START("fuzz RSA public");
+ buf = load_file("rsa_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ public_fuzz(k1);
+ sshkey_free(k1);
+ TEST_DONE();
+
+ TEST_START("fuzz RSA cert");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0);
+ public_fuzz(k1);
+ sshkey_free(k1);
+ TEST_DONE();
+
+ TEST_START("fuzz DSA public");
+ buf = load_file("dsa_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ public_fuzz(k1);
+ sshkey_free(k1);
+ TEST_DONE();
+
+ TEST_START("fuzz DSA cert");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0);
+ public_fuzz(k1);
+ sshkey_free(k1);
+ TEST_DONE();
+
+#ifdef OPENSSL_HAS_ECC
+ TEST_START("fuzz ECDSA public");
+ buf = load_file("ecdsa_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ public_fuzz(k1);
+ sshkey_free(k1);
+ TEST_DONE();
+
+ TEST_START("fuzz ECDSA cert");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k1), 0);
+ public_fuzz(k1);
+ sshkey_free(k1);
+ TEST_DONE();
+#endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
+
+ TEST_START("fuzz Ed25519 public");
+ buf = load_file("ed25519_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ public_fuzz(k1);
+ sshkey_free(k1);
+ TEST_DONE();
+
+ TEST_START("fuzz Ed25519 cert");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k1), 0);
+ public_fuzz(k1);
+ sshkey_free(k1);
+ TEST_DONE();
+
+#ifdef WITH_OPENSSL
+ TEST_START("fuzz RSA sig");
+ buf = load_file("rsa_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ sig_fuzz(k1, "ssh-rsa");
+ sshkey_free(k1);
+ TEST_DONE();
+
+ TEST_START("fuzz RSA SHA256 sig");
+ buf = load_file("rsa_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ sig_fuzz(k1, "rsa-sha2-256");
+ sshkey_free(k1);
+ TEST_DONE();
+
+ TEST_START("fuzz RSA SHA512 sig");
+ buf = load_file("rsa_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ sig_fuzz(k1, "rsa-sha2-512");
+ sshkey_free(k1);
+ TEST_DONE();
+
+ TEST_START("fuzz DSA sig");
+ buf = load_file("dsa_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ sig_fuzz(k1, NULL);
+ sshkey_free(k1);
+ TEST_DONE();
+
+#ifdef OPENSSL_HAS_ECC
+ TEST_START("fuzz ECDSA sig");
+ buf = load_file("ecdsa_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ sig_fuzz(k1, NULL);
+ sshkey_free(k1);
+ TEST_DONE();
+#endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
+
+ TEST_START("fuzz Ed25519 sig");
+ buf = load_file("ed25519_1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ sig_fuzz(k1, NULL);
+ sshkey_free(k1);
+ TEST_DONE();
+
+/* XXX fuzz decoded new-format blobs too */
+/* XXX fuzz XMSS too */
+
+}
diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c
new file mode 100644
index 00000000..025bb981
--- /dev/null
+++ b/regress/unittests/sshkey/test_sshkey.c
@@ -0,0 +1,526 @@
+/* $OpenBSD: test_sshkey.c,v 1.20 2019/11/25 10:32:35 djm Exp $ */
+/*
+ * Regress test for sshkey.h key management API
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
+# include <openssl/ec.h>
+#endif
+
+#include "../test_helper/test_helper.h"
+
+#include "ssherr.h"
+#include "sshbuf.h"
+#define SSHBUF_INTERNAL 1 /* access internals for testing */
+#include "sshkey.h"
+
+#include "authfile.h"
+#include "common.h"
+#include "ssh2.h"
+
+void sshkey_tests(void);
+
+static void
+put_opt(struct sshbuf *b, const char *name, const char *value)
+{
+ struct sshbuf *sect;
+
+ sect = sshbuf_new();
+ ASSERT_PTR_NE(sect, NULL);
+ ASSERT_INT_EQ(sshbuf_put_cstring(b, name), 0);
+ if (value != NULL)
+ ASSERT_INT_EQ(sshbuf_put_cstring(sect, value), 0);
+ ASSERT_INT_EQ(sshbuf_put_stringb(b, sect), 0);
+ sshbuf_free(sect);
+}
+
+#ifdef WITH_OPENSSL
+static void
+build_cert(struct sshbuf *b, struct sshkey *k, const char *type,
+ struct sshkey *sign_key, struct sshkey *ca_key,
+ const char *sig_alg)
+{
+ struct sshbuf *ca_buf, *pk, *principals, *critopts, *exts;
+ u_char *sigblob;
+ size_t siglen;
+
+ ca_buf = sshbuf_new();
+ ASSERT_PTR_NE(ca_buf, NULL);
+ ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0);
+
+ /*
+ * Get the public key serialisation by rendering the key and skipping
+ * the type string. This is a bit of a hack :/
+ */
+ pk = sshbuf_new();
+ ASSERT_PTR_NE(pk, NULL);
+ ASSERT_INT_EQ(sshkey_putb_plain(k, pk), 0);
+ ASSERT_INT_EQ(sshbuf_skip_string(pk), 0);
+
+ principals = sshbuf_new();
+ ASSERT_PTR_NE(principals, NULL);
+ ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0);
+ ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0);
+
+ critopts = sshbuf_new();
+ ASSERT_PTR_NE(critopts, NULL);
+ put_opt(critopts, "force-command", "/usr/local/bin/nethack");
+ put_opt(critopts, "source-address", "192.168.0.0/24,127.0.0.1,::1");
+
+ exts = sshbuf_new();
+ ASSERT_PTR_NE(exts, NULL);
+ put_opt(critopts, "permit-X11-forwarding", NULL);
+
+ ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0);
+ ASSERT_INT_EQ(sshbuf_put_cstring(b, "noncenoncenonce!"), 0); /* nonce */
+ ASSERT_INT_EQ(sshbuf_putb(b, pk), 0); /* public key serialisation */
+ ASSERT_INT_EQ(sshbuf_put_u64(b, 1234), 0); /* serial */
+ ASSERT_INT_EQ(sshbuf_put_u32(b, SSH2_CERT_TYPE_USER), 0); /* type */
+ ASSERT_INT_EQ(sshbuf_put_cstring(b, "gregor"), 0); /* key ID */
+ ASSERT_INT_EQ(sshbuf_put_stringb(b, principals), 0); /* principals */
+ ASSERT_INT_EQ(sshbuf_put_u64(b, 0), 0); /* start */
+ ASSERT_INT_EQ(sshbuf_put_u64(b, 0xffffffffffffffffULL), 0); /* end */
+ ASSERT_INT_EQ(sshbuf_put_stringb(b, critopts), 0); /* options */
+ ASSERT_INT_EQ(sshbuf_put_stringb(b, exts), 0); /* extensions */
+ 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);
+ ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */
+
+ free(sigblob);
+ sshbuf_free(ca_buf);
+ sshbuf_free(exts);
+ sshbuf_free(critopts);
+ sshbuf_free(principals);
+ sshbuf_free(pk);
+}
+#endif /* WITH_OPENSSL */
+
+static void
+signature_test(struct sshkey *k, struct sshkey *bad, const char *sig_alg,
+ const u_char *d, size_t l)
+{
+ size_t len;
+ u_char *sig;
+
+ ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, 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);
+ ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0);
+ /* Fuzz test is more comprehensive, this is just a smoke test */
+ sig[len - 5] ^= 0x10;
+ ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0);
+ free(sig);
+}
+
+static void
+banana(u_char *s, size_t l)
+{
+ size_t o;
+ const u_char the_banana[] = { 'b', 'a', 'n', 'a', 'n', 'a' };
+
+ for (o = 0; o < l; o += sizeof(the_banana)) {
+ if (l - o < sizeof(the_banana)) {
+ memcpy(s + o, "nanananana", l - o);
+ break;
+ }
+ memcpy(s + o, banana, sizeof(the_banana));
+ }
+}
+
+static void
+signature_tests(struct sshkey *k, struct sshkey *bad, const char *sig_alg)
+{
+ u_char i, buf[2049];
+ size_t lens[] = {
+ 1, 2, 7, 8, 9, 15, 16, 17, 31, 32, 33, 127, 128, 129,
+ 255, 256, 257, 1023, 1024, 1025, 2047, 2048, 2049
+ };
+
+ for (i = 0; i < (sizeof(lens)/sizeof(lens[0])); i++) {
+ test_subtest_info("%s key, banana length %zu",
+ sshkey_type(k), lens[i]);
+ banana(buf, lens[i]);
+ signature_test(k, bad, sig_alg, buf, lens[i]);
+ }
+}
+
+static struct sshkey *
+get_private(const char *n)
+{
+ struct sshbuf *b;
+ struct sshkey *ret;
+
+ b = load_file(n);
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(b, "", &ret, NULL), 0);
+ sshbuf_free(b);
+ return ret;
+}
+
+void
+sshkey_tests(void)
+{
+ struct sshkey *k1, *k2, *k3, *kf;
+#ifdef WITH_OPENSSL
+ struct sshkey *k4, *kr, *kd;
+#ifdef OPENSSL_HAS_ECC
+ struct sshkey *ke;
+#endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
+ struct sshbuf *b;
+
+ TEST_START("new invalid");
+ k1 = sshkey_new(-42);
+ ASSERT_PTR_EQ(k1, NULL);
+ TEST_DONE();
+
+ TEST_START("new/free KEY_UNSPEC");
+ k1 = sshkey_new(KEY_UNSPEC);
+ ASSERT_PTR_NE(k1, NULL);
+ sshkey_free(k1);
+ TEST_DONE();
+
+#ifdef WITH_OPENSSL
+ TEST_START("new/free KEY_RSA");
+ k1 = sshkey_new(KEY_RSA);
+ ASSERT_PTR_NE(k1, NULL);
+ ASSERT_PTR_NE(k1->rsa, NULL);
+ sshkey_free(k1);
+ TEST_DONE();
+
+ TEST_START("new/free KEY_DSA");
+ k1 = sshkey_new(KEY_DSA);
+ ASSERT_PTR_NE(k1, NULL);
+ ASSERT_PTR_NE(k1->dsa, NULL);
+ sshkey_free(k1);
+ TEST_DONE();
+
+#ifdef OPENSSL_HAS_ECC
+ TEST_START("new/free KEY_ECDSA");
+ k1 = sshkey_new(KEY_ECDSA);
+ ASSERT_PTR_NE(k1, NULL);
+ ASSERT_PTR_EQ(k1->ecdsa, NULL); /* Can't allocate without NID */
+ sshkey_free(k1);
+ TEST_DONE();
+#endif
+
+ TEST_START("new/free KEY_ED25519");
+ k1 = sshkey_new(KEY_ED25519);
+ ASSERT_PTR_NE(k1, NULL);
+ /* These should be blank until key loaded or generated */
+ ASSERT_PTR_EQ(k1->ed25519_sk, NULL);
+ ASSERT_PTR_EQ(k1->ed25519_pk, NULL);
+ sshkey_free(k1);
+ TEST_DONE();
+
+ TEST_START("generate KEY_RSA too small modulus");
+ ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 128, &k1),
+ SSH_ERR_KEY_LENGTH);
+ ASSERT_PTR_EQ(k1, NULL);
+ TEST_DONE();
+
+ TEST_START("generate KEY_RSA too large modulus");
+ ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1 << 20, &k1),
+ SSH_ERR_KEY_LENGTH);
+ ASSERT_PTR_EQ(k1, NULL);
+ TEST_DONE();
+
+ TEST_START("generate KEY_DSA wrong bits");
+ ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 2048, &k1),
+ SSH_ERR_KEY_LENGTH);
+ ASSERT_PTR_EQ(k1, NULL);
+ sshkey_free(k1);
+ TEST_DONE();
+
+#ifdef OPENSSL_HAS_ECC
+ TEST_START("generate KEY_ECDSA wrong bits");
+ ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 42, &k1),
+ SSH_ERR_KEY_LENGTH);
+ ASSERT_PTR_EQ(k1, NULL);
+ sshkey_free(k1);
+ TEST_DONE();
+#endif
+
+ TEST_START("generate KEY_RSA");
+ ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 767, &kr),
+ SSH_ERR_KEY_LENGTH);
+ ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &kr), 0);
+ ASSERT_PTR_NE(kr, NULL);
+ ASSERT_PTR_NE(kr->rsa, NULL);
+ ASSERT_PTR_NE(rsa_n(kr), NULL);
+ ASSERT_PTR_NE(rsa_e(kr), NULL);
+ ASSERT_PTR_NE(rsa_p(kr), NULL);
+ ASSERT_INT_EQ(BN_num_bits(rsa_n(kr)), 1024);
+ TEST_DONE();
+
+ TEST_START("generate KEY_DSA");
+ ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0);
+ ASSERT_PTR_NE(kd, NULL);
+ ASSERT_PTR_NE(kd->dsa, NULL);
+ ASSERT_PTR_NE(dsa_g(kd), NULL);
+ ASSERT_PTR_NE(dsa_priv_key(kd), NULL);
+ TEST_DONE();
+
+#ifdef OPENSSL_HAS_ECC
+ TEST_START("generate KEY_ECDSA");
+ ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &ke), 0);
+ ASSERT_PTR_NE(ke, NULL);
+ ASSERT_PTR_NE(ke->ecdsa, NULL);
+ ASSERT_PTR_NE(EC_KEY_get0_public_key(ke->ecdsa), NULL);
+ ASSERT_PTR_NE(EC_KEY_get0_private_key(ke->ecdsa), NULL);
+ TEST_DONE();
+#endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
+
+ TEST_START("generate KEY_ED25519");
+ ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 256, &kf), 0);
+ ASSERT_PTR_NE(kf, NULL);
+ ASSERT_INT_EQ(kf->type, KEY_ED25519);
+ ASSERT_PTR_NE(kf->ed25519_pk, NULL);
+ ASSERT_PTR_NE(kf->ed25519_sk, NULL);
+ TEST_DONE();
+
+#ifdef WITH_OPENSSL
+ TEST_START("demote KEY_RSA");
+ ASSERT_INT_EQ(sshkey_from_private(kr, &k1), 0);
+ ASSERT_PTR_NE(k1, NULL);
+ ASSERT_PTR_NE(kr, k1);
+ ASSERT_INT_EQ(k1->type, KEY_RSA);
+ ASSERT_PTR_NE(k1->rsa, NULL);
+ ASSERT_PTR_NE(rsa_n(k1), NULL);
+ ASSERT_PTR_NE(rsa_e(k1), NULL);
+ ASSERT_PTR_EQ(rsa_p(k1), NULL);
+ TEST_DONE();
+
+ TEST_START("equal KEY_RSA/demoted KEY_RSA");
+ ASSERT_INT_EQ(sshkey_equal(kr, k1), 1);
+ sshkey_free(k1);
+ TEST_DONE();
+
+ TEST_START("demote KEY_DSA");
+ ASSERT_INT_EQ(sshkey_from_private(kd, &k1), 0);
+ ASSERT_PTR_NE(k1, NULL);
+ ASSERT_PTR_NE(kd, k1);
+ ASSERT_INT_EQ(k1->type, KEY_DSA);
+ ASSERT_PTR_NE(k1->dsa, NULL);
+ ASSERT_PTR_NE(dsa_g(k1), NULL);
+ ASSERT_PTR_EQ(dsa_priv_key(k1), NULL);
+ TEST_DONE();
+
+ TEST_START("equal KEY_DSA/demoted KEY_DSA");
+ ASSERT_INT_EQ(sshkey_equal(kd, k1), 1);
+ sshkey_free(k1);
+ TEST_DONE();
+
+#ifdef OPENSSL_HAS_ECC
+ TEST_START("demote KEY_ECDSA");
+ ASSERT_INT_EQ(sshkey_from_private(ke, &k1), 0);
+ ASSERT_PTR_NE(k1, NULL);
+ ASSERT_PTR_NE(ke, k1);
+ ASSERT_INT_EQ(k1->type, KEY_ECDSA);
+ ASSERT_PTR_NE(k1->ecdsa, NULL);
+ ASSERT_INT_EQ(k1->ecdsa_nid, ke->ecdsa_nid);
+ ASSERT_PTR_NE(EC_KEY_get0_public_key(ke->ecdsa), NULL);
+ ASSERT_PTR_EQ(EC_KEY_get0_private_key(k1->ecdsa), NULL);
+ TEST_DONE();
+
+ TEST_START("equal KEY_ECDSA/demoted KEY_ECDSA");
+ ASSERT_INT_EQ(sshkey_equal(ke, k1), 1);
+ sshkey_free(k1);
+ TEST_DONE();
+#endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
+
+ TEST_START("demote KEY_ED25519");
+ ASSERT_INT_EQ(sshkey_from_private(kf, &k1), 0);
+ ASSERT_PTR_NE(k1, NULL);
+ ASSERT_PTR_NE(kf, k1);
+ ASSERT_INT_EQ(k1->type, KEY_ED25519);
+ ASSERT_PTR_NE(k1->ed25519_pk, NULL);
+ ASSERT_PTR_EQ(k1->ed25519_sk, NULL);
+ TEST_DONE();
+
+ TEST_START("equal KEY_ED25519/demoted KEY_ED25519");
+ ASSERT_INT_EQ(sshkey_equal(kf, k1), 1);
+ sshkey_free(k1);
+ TEST_DONE();
+
+#ifdef WITH_OPENSSL
+ TEST_START("equal mismatched key types");
+ ASSERT_INT_EQ(sshkey_equal(kd, kr), 0);
+#ifdef OPENSSL_HAS_ECC
+ ASSERT_INT_EQ(sshkey_equal(kd, ke), 0);
+ ASSERT_INT_EQ(sshkey_equal(kr, ke), 0);
+ ASSERT_INT_EQ(sshkey_equal(ke, kf), 0);
+#endif /* OPENSSL_HAS_ECC */
+ ASSERT_INT_EQ(sshkey_equal(kd, kf), 0);
+ TEST_DONE();
+#endif /* WITH_OPENSSL */
+
+ TEST_START("equal different keys");
+#ifdef WITH_OPENSSL
+ ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &k1), 0);
+ ASSERT_INT_EQ(sshkey_equal(kr, k1), 0);
+ sshkey_free(k1);
+ ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &k1), 0);
+ ASSERT_INT_EQ(sshkey_equal(kd, k1), 0);
+ sshkey_free(k1);
+#ifdef OPENSSL_HAS_ECC
+ ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &k1), 0);
+ ASSERT_INT_EQ(sshkey_equal(ke, k1), 0);
+ sshkey_free(k1);
+#endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
+ ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 256, &k1), 0);
+ ASSERT_INT_EQ(sshkey_equal(kf, k1), 0);
+ sshkey_free(k1);
+ TEST_DONE();
+
+#ifdef WITH_OPENSSL
+ sshkey_free(kr);
+ sshkey_free(kd);
+#ifdef OPENSSL_HAS_ECC
+ sshkey_free(ke);
+#endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
+ sshkey_free(kf);
+
+ TEST_START("certify key");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_1.pub"),
+ &k1, NULL), 0);
+ k2 = get_private("ed25519_2");
+ ASSERT_INT_EQ(sshkey_to_certified(k1), 0);
+ ASSERT_PTR_NE(k1->cert, NULL);
+ k1->cert->type = SSH2_CERT_TYPE_USER;
+ k1->cert->serial = 1234;
+ k1->cert->key_id = strdup("estragon");
+ ASSERT_PTR_NE(k1->cert->key_id, NULL);
+ k1->cert->principals = calloc(4, sizeof(*k1->cert->principals));
+ ASSERT_PTR_NE(k1->cert->principals, NULL);
+ k1->cert->principals[0] = strdup("estragon");
+ k1->cert->principals[1] = strdup("vladimir");
+ k1->cert->principals[2] = strdup("pozzo");
+ k1->cert->principals[3] = strdup("lucky");
+ ASSERT_PTR_NE(k1->cert->principals[0], NULL);
+ ASSERT_PTR_NE(k1->cert->principals[1], NULL);
+ ASSERT_PTR_NE(k1->cert->principals[2], NULL);
+ ASSERT_PTR_NE(k1->cert->principals[3], NULL);
+ k1->cert->nprincipals = 4;
+ k1->cert->valid_after = 0;
+ k1->cert->valid_before = (u_int64_t)-1;
+ sshbuf_free(k1->cert->critical);
+ k1->cert->critical = sshbuf_new();
+ ASSERT_PTR_NE(k1->cert->critical, NULL);
+ sshbuf_free(k1->cert->extensions);
+ k1->cert->extensions = sshbuf_new();
+ ASSERT_PTR_NE(k1->cert->extensions, NULL);
+ put_opt(k1->cert->critical, "force-command", "/usr/bin/true");
+ put_opt(k1->cert->critical, "source-address", "127.0.0.1");
+ 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);
+ b = sshbuf_new();
+ ASSERT_PTR_NE(b, NULL);
+ ASSERT_INT_EQ(sshkey_putb(k1, b), 0);
+ ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k3), 0);
+
+ sshkey_free(k1);
+ sshkey_free(k2);
+ sshkey_free(k3);
+ sshbuf_reset(b);
+ TEST_DONE();
+
+#ifdef WITH_OPENSSL
+ TEST_START("sign and verify RSA");
+ k1 = get_private("rsa_1");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_2.pub"), &k2,
+ NULL), 0);
+ signature_tests(k1, k2, "ssh-rsa");
+ sshkey_free(k1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("sign and verify RSA-SHA256");
+ k1 = get_private("rsa_1");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_2.pub"), &k2,
+ NULL), 0);
+ signature_tests(k1, k2, "rsa-sha2-256");
+ sshkey_free(k1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("sign and verify RSA-SHA512");
+ k1 = get_private("rsa_1");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_2.pub"), &k2,
+ NULL), 0);
+ signature_tests(k1, k2, "rsa-sha2-512");
+ sshkey_free(k1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("sign and verify DSA");
+ k1 = get_private("dsa_1");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_2.pub"), &k2,
+ NULL), 0);
+ signature_tests(k1, k2, NULL);
+ sshkey_free(k1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+#ifdef OPENSSL_HAS_ECC
+ TEST_START("sign and verify ECDSA");
+ k1 = get_private("ecdsa_1");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_2.pub"), &k2,
+ NULL), 0);
+ signature_tests(k1, k2, NULL);
+ sshkey_free(k1);
+ sshkey_free(k2);
+ TEST_DONE();
+#endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
+
+ TEST_START("sign and verify ED25519");
+ k1 = get_private("ed25519_1");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_2.pub"), &k2,
+ NULL), 0);
+ signature_tests(k1, k2, NULL);
+ sshkey_free(k1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+#ifdef WITH_OPENSSL
+ TEST_START("nested certificate");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0);
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2,
+ NULL), 0);
+ k3 = get_private("rsa_1");
+ build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1, NULL);
+ ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4),
+ SSH_ERR_KEY_CERT_INVALID_SIGN_KEY);
+ ASSERT_PTR_EQ(k4, NULL);
+ sshkey_free(k1);
+ sshkey_free(k2);
+ sshkey_free(k3);
+ sshbuf_free(b);
+ TEST_DONE();
+#endif /* WITH_OPENSSL */
+}
diff --git a/regress/unittests/sshkey/testdata/dsa_1 b/regress/unittests/sshkey/testdata/dsa_1
new file mode 100644
index 00000000..d3f24824
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQD6kutNFRsHTwEAv6d39Lhsqy1apdHBZ9c2HfyRr7WmypyGIy2m
+Ka43vzXI8CNwmRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+MiwfurwrR3CRe61QRYb8Py
+mcHOxueHs95IcjrbIPNn86cjnPP5qvv/guUzCjuww4zBdJOXpligrGt2XwIVAKMD
+/50qQy7j8JaMk+1+Xtg1pK01AoGBAO7l9QVVbSSoy5lq6cOtvpf8UlwOa6+zBwbl
+o4gmFd1RwX1yWkA8kQ7RrhCSg8Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEWtN4P
+h8fVUeS74iQbIwFQeKlYHIlNTRoGtAbdi3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgz
+LND26HrdAoGBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxb
+OXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joo
+t+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAhRYIbQ5
+KfXsZuBPuWe5FJz3ldaEgw==
+-----END DSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/dsa_1-cert.fp b/regress/unittests/sshkey/testdata/dsa_1-cert.fp
new file mode 100644
index 00000000..75ff0e9c
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1-cert.fp
@@ -0,0 +1 @@
+SHA256:kOLgXSoAT8O5T6r36n5NJUYigbux1d7gdH/rmWiJm6s
diff --git a/regress/unittests/sshkey/testdata/dsa_1-cert.pub b/regress/unittests/sshkey/testdata/dsa_1-cert.pub
new file mode 100644
index 00000000..e768db1e
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1-cert.pub
@@ -0,0 +1 @@
+ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgdTlbNU9Hn9Qng3FHxwH971bxCIoq1ern/QWFFDWXgmYAAACBAPqS600VGwdPAQC/p3f0uGyrLVql0cFn1zYd/JGvtabKnIYjLaYprje/NcjwI3CZFJiz4Dp3S8kLs+X5/1DMn/Tg1Y4D4yLB+6vCtHcJF7rVBFhvw/KZwc7G54ez3khyOtsg82fzpyOc8/mq+/+C5TMKO7DDjMF0k5emWKCsa3ZfAAAAFQCjA/+dKkMu4/CWjJPtfl7YNaStNQAAAIEA7uX1BVVtJKjLmWrpw62+l/xSXA5rr7MHBuWjiCYV3VHBfXJaQDyRDtGuEJKDwdzqYgacpGApGWL/cuBtJ9nShsUl6GRG0Ra03g+Hx9VR5LviJBsjAVB4qVgciU1NGga0Bt2Lecd1X4EGQRBzVXeuOpiqGM6jP/I2yDMs0Pboet0AAACBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxbOXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joot+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAAAAAAAAAAYAAAACAAAABmp1bGl1cwAAABIAAAAFaG9zdDEAAAAFaG9zdDIAAAAANowB8AAAAABNHmBwAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQAAAFMAAAALc3NoLWVkMjU1MTkAAABAh/z1LIdNL1b66tQ8t9DY9BTB3BQKpTKmc7ezyFKLwl96yaIniZwD9Ticdbe/8i/Li3uCFE3EAt8NAIv9zff8Bg== DSA test key #1
diff --git a/regress/unittests/sshkey/testdata/dsa_1.fp b/regress/unittests/sshkey/testdata/dsa_1.fp
new file mode 100644
index 00000000..75ff0e9c
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1.fp
@@ -0,0 +1 @@
+SHA256:kOLgXSoAT8O5T6r36n5NJUYigbux1d7gdH/rmWiJm6s
diff --git a/regress/unittests/sshkey/testdata/dsa_1.fp.bb b/regress/unittests/sshkey/testdata/dsa_1.fp.bb
new file mode 100644
index 00000000..ba37776e
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1.fp.bb
@@ -0,0 +1 @@
+xetag-todiz-mifah-torec-mynyv-cyvit-gopon-pygag-rupic-cenav-bexax
diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.g b/regress/unittests/sshkey/testdata/dsa_1.param.g
new file mode 100644
index 00000000..e51c3f9f
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1.param.g
@@ -0,0 +1 @@
+00eee5f505556d24a8cb996ae9c3adbe97fc525c0e6bafb30706e5a3882615dd51c17d725a403c910ed1ae109283c1dcea62069ca460291962ff72e06d27d9d286c525e86446d116b4de0f87c7d551e4bbe2241b23015078a9581c894d4d1a06b406dd8b79c7755f81064110735577ae3a98aa18cea33ff236c8332cd0f6e87add
diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.priv b/regress/unittests/sshkey/testdata/dsa_1.param.priv
new file mode 100644
index 00000000..4f743314
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1.param.priv
@@ -0,0 +1 @@
+5821b43929f5ec66e04fb967b9149cf795d68483
diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.pub b/regress/unittests/sshkey/testdata/dsa_1.param.pub
new file mode 100644
index 00000000..ba0313be
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1.param.pub
@@ -0,0 +1 @@
+00e757a727e6a1b10168ea9902ebe08f53f4ba18c6d8fdf551fbabbf6d8558f054dc0f6aae4c5b397c04d0bc2f8c2bebb1057f96b621273fed8b2b38d1579a86e956644e520073171887fde4b88b4a0697323928ee3a28b7e2caf3896d2f29b067840c9d88e765249c95fd54bb240c714b5bdf8f88d2ef58727ca1a7699216c42d
diff --git a/regress/unittests/sshkey/testdata/dsa_1.pub b/regress/unittests/sshkey/testdata/dsa_1.pub
new file mode 100644
index 00000000..41cae2f6
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAPqS600VGwdPAQC/p3f0uGyrLVql0cFn1zYd/JGvtabKnIYjLaYprje/NcjwI3CZFJiz4Dp3S8kLs+X5/1DMn/Tg1Y4D4yLB+6vCtHcJF7rVBFhvw/KZwc7G54ez3khyOtsg82fzpyOc8/mq+/+C5TMKO7DDjMF0k5emWKCsa3ZfAAAAFQCjA/+dKkMu4/CWjJPtfl7YNaStNQAAAIEA7uX1BVVtJKjLmWrpw62+l/xSXA5rr7MHBuWjiCYV3VHBfXJaQDyRDtGuEJKDwdzqYgacpGApGWL/cuBtJ9nShsUl6GRG0Ra03g+Hx9VR5LviJBsjAVB4qVgciU1NGga0Bt2Lecd1X4EGQRBzVXeuOpiqGM6jP/I2yDMs0Pboet0AAACBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxbOXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joot+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQt DSA test key #1
diff --git a/regress/unittests/sshkey/testdata/dsa_1_pw b/regress/unittests/sshkey/testdata/dsa_1_pw
new file mode 100644
index 00000000..24c73039
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1_pw
@@ -0,0 +1,15 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,BC8386C373B22EB7F00ADC821D5D8BE9
+
++HDV2DQ09sxrIAeXTz9r3YFuPRa2hk1+NGcr3ETkXbC6KiZ14wpTnGTloKwaQjIW
+eXTa9mpCOWAoohgvsVb+hOuOlP7AfeHu1IXV4EAS+GDpkiV5UxlCXXwqlD75Buu4
+wwDd/p4SWzILH3WGjDk5JIXoxWNY13LHwC7Q6gtGJx4AicUG7YBRTXMIBDa/Kh77
+6o2rFETKmp4VHBvHbakmiETfptdM8bbWxKWeY2vakThyESgeofsLoTOQCIwlEfJC
+s2D/KYL65C8VbHYgIoSLTQnooO45DDyxIuhCqP+H23mhv9vB1Od3nc2atgHj/XFs
+dcOPFkF/msDRYqxY3V0AS6+jpKwFodZ7g/hyGcyPxOkzlJVuKoKuH6P5PyQ69Gx0
+iqri0xEPyABr7kGlXNrjjctojX+B4WwSnjg/2euXXWFXCRalIdA7ErATTiQbGOx7
+Vd6Gn8PZbSy1MkqEDrZRip0pfAFJYI/8GXPC75BpnRsrVlfhtrngbW+kBP35LzaN
+l2K+RQ3gSB3iFoqNb1Kuu6T5MZlyVl5H2dVlJSeb1euQ2OycXdDoFTyJ4AiyWS7w
+Vlh8zeJnso5QRDjMwx99pZilbbuFGSLsahiGEveFc6o=
+-----END DSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/dsa_2 b/regress/unittests/sshkey/testdata/dsa_2
new file mode 100644
index 00000000..3cc9631a
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_2
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvQIBAAKBgQCbyPXNdHeLsjpobPVCMkfagBkt15Zsltqf/PGNP1y1cuz7rsTX
+ZekQwUkSTNm5coqXe+ZOw2O4tjobJDd60I1/VPgaB0NYlQR9Hn87M284WD4f6VY+
+aunHmP134a8ybG5G4NqVNF3ihvxAR2pVITqb7kE46r2uYZNcNlHI8voRCwIVAMcP
+bwqFNsQbH5pJyZW30wj4KVZ3AoGBAIK98BVeKQVf8qDFqx9ovMuNgVSxpd+N0Yta
+5ZEy1OI2ziu5RhjueIM2K7Gq2Mnp38ob1AM53BUxqlcBJaHEDa6rj6yvuMgW9oCJ
+dImBM8sIFxfBbXNbpJiMaDwa6WyT84OkpDE6uuAepTMnWOUWkUVkAiyokHDUGXkG
+GyoQblbXAoGBAIsf7TaZ804sUWwRV0wI8DYx+hxD5QdrfYPYMtL2fHn3lICimGt0
+FTtUZ25jKg0E0DMBPdET6ZEHB3ZZkR8hFoUzZhdnyJMu3UjVtgaV88Ue3PrXxchk
+0W2jHPaAgQU3JIWzo8HFIFqvC/HEL+EyW3rBTY2uXM3XGI+YcWSA4ZrZAhUAsY2f
+bDFNzgZ4DaZ9wLRzTgOswPU=
+-----END DSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/dsa_2.fp b/regress/unittests/sshkey/testdata/dsa_2.fp
new file mode 100644
index 00000000..51fbeb4d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_2.fp
@@ -0,0 +1 @@
+SHA256:ecwhWcXgpdBxZ2e+OjpRRY7dqXHHCD62BGtoVQQBwCk
diff --git a/regress/unittests/sshkey/testdata/dsa_2.fp.bb b/regress/unittests/sshkey/testdata/dsa_2.fp.bb
new file mode 100644
index 00000000..4d908ee3
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_2.fp.bb
@@ -0,0 +1 @@
+xeser-megad-pocan-rozit-belup-tapoh-fapif-kyvit-vonav-cehab-naxax
diff --git a/regress/unittests/sshkey/testdata/dsa_2.pub b/regress/unittests/sshkey/testdata/dsa_2.pub
new file mode 100644
index 00000000..77bb555d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_2.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAJvI9c10d4uyOmhs9UIyR9qAGS3XlmyW2p/88Y0/XLVy7PuuxNdl6RDBSRJM2blyipd75k7DY7i2OhskN3rQjX9U+BoHQ1iVBH0efzszbzhYPh/pVj5q6ceY/XfhrzJsbkbg2pU0XeKG/EBHalUhOpvuQTjqva5hk1w2Ucjy+hELAAAAFQDHD28KhTbEGx+aScmVt9MI+ClWdwAAAIEAgr3wFV4pBV/yoMWrH2i8y42BVLGl343Ri1rlkTLU4jbOK7lGGO54gzYrsarYyenfyhvUAzncFTGqVwElocQNrquPrK+4yBb2gIl0iYEzywgXF8Ftc1ukmIxoPBrpbJPzg6SkMTq64B6lMydY5RaRRWQCLKiQcNQZeQYbKhBuVtcAAACBAIsf7TaZ804sUWwRV0wI8DYx+hxD5QdrfYPYMtL2fHn3lICimGt0FTtUZ25jKg0E0DMBPdET6ZEHB3ZZkR8hFoUzZhdnyJMu3UjVtgaV88Ue3PrXxchk0W2jHPaAgQU3JIWzo8HFIFqvC/HEL+EyW3rBTY2uXM3XGI+YcWSA4ZrZ DSA test key #2
diff --git a/regress/unittests/sshkey/testdata/dsa_n b/regress/unittests/sshkey/testdata/dsa_n
new file mode 100644
index 00000000..657624e0
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_n
@@ -0,0 +1,21 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABswAAAAdzc2gtZH
+NzAAAAgQD6kutNFRsHTwEAv6d39Lhsqy1apdHBZ9c2HfyRr7WmypyGIy2mKa43vzXI8CNw
+mRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+MiwfurwrR3CRe61QRYb8PymcHOxueHs95IcjrbIP
+Nn86cjnPP5qvv/guUzCjuww4zBdJOXpligrGt2XwAAABUAowP/nSpDLuPwloyT7X5e2DWk
+rTUAAACBAO7l9QVVbSSoy5lq6cOtvpf8UlwOa6+zBwblo4gmFd1RwX1yWkA8kQ7RrhCSg8
+Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEWtN4Ph8fVUeS74iQbIwFQeKlYHIlNTRoGtAbd
+i3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgzLND26HrdAAAAgQDnV6cn5qGxAWjqmQLr4I9T9L
+oYxtj99VH7q79thVjwVNwPaq5MWzl8BNC8L4wr67EFf5a2ISc/7YsrONFXmobpVmROUgBz
+FxiH/eS4i0oGlzI5KO46KLfiyvOJbS8psGeEDJ2I52UknJX9VLskDHFLW9+PiNLvWHJ8oa
+dpkhbELQAAAdhWTOFbVkzhWwAAAAdzc2gtZHNzAAAAgQD6kutNFRsHTwEAv6d39Lhsqy1a
+pdHBZ9c2HfyRr7WmypyGIy2mKa43vzXI8CNwmRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+Miwf
+urwrR3CRe61QRYb8PymcHOxueHs95IcjrbIPNn86cjnPP5qvv/guUzCjuww4zBdJOXplig
+rGt2XwAAABUAowP/nSpDLuPwloyT7X5e2DWkrTUAAACBAO7l9QVVbSSoy5lq6cOtvpf8Ul
+wOa6+zBwblo4gmFd1RwX1yWkA8kQ7RrhCSg8Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEW
+tN4Ph8fVUeS74iQbIwFQeKlYHIlNTRoGtAbdi3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgzLN
+D26HrdAAAAgQDnV6cn5qGxAWjqmQLr4I9T9LoYxtj99VH7q79thVjwVNwPaq5MWzl8BNC8
+L4wr67EFf5a2ISc/7YsrONFXmobpVmROUgBzFxiH/eS4i0oGlzI5KO46KLfiyvOJbS8psG
+eEDJ2I52UknJX9VLskDHFLW9+PiNLvWHJ8oadpkhbELQAAABRYIbQ5KfXsZuBPuWe5FJz3
+ldaEgwAAAAAB
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/dsa_n_pw b/regress/unittests/sshkey/testdata/dsa_n_pw
new file mode 100644
index 00000000..24ac299a
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_n_pw
@@ -0,0 +1,21 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABCVs+LsMJ
+wnB5zM9U9pTXrGAAAAEAAAAAEAAAGzAAAAB3NzaC1kc3MAAACBAPqS600VGwdPAQC/p3f0
+uGyrLVql0cFn1zYd/JGvtabKnIYjLaYprje/NcjwI3CZFJiz4Dp3S8kLs+X5/1DMn/Tg1Y
+4D4yLB+6vCtHcJF7rVBFhvw/KZwc7G54ez3khyOtsg82fzpyOc8/mq+/+C5TMKO7DDjMF0
+k5emWKCsa3ZfAAAAFQCjA/+dKkMu4/CWjJPtfl7YNaStNQAAAIEA7uX1BVVtJKjLmWrpw6
+2+l/xSXA5rr7MHBuWjiCYV3VHBfXJaQDyRDtGuEJKDwdzqYgacpGApGWL/cuBtJ9nShsUl
+6GRG0Ra03g+Hx9VR5LviJBsjAVB4qVgciU1NGga0Bt2Lecd1X4EGQRBzVXeuOpiqGM6jP/
+I2yDMs0Pboet0AAACBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxb
+OXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joot+LK84
+ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAAAB4HiOcRW4w+sIqBL0
+TPVbf0glN1hUi0rcE63Pqxmvxb8LkldC4IxAUagPrjhNAEW2AY42+CvPrtGB1z7gDADAIW
+xZX6wKwIcXP0Qh+xHE12F4u6mwfasssnAp4t1Ki8uCjMjnimgb3KdWpp0kiUV0oR062TXV
+PAdfrWjaq4fw0KOqbHIAG/v36AqzuqjSTfDbqvLZM3y0gp2Q1RxaQVJA5ZIKKyqRyFX7sr
+BaEIyCgeE3hM0EB7BycY1oIcS/eNxrACBWVJCENl5N7LtEYXNX7TANFniztfXzwaqGTT6A
+fCfbW4gz1UKldLUBzbIrPwMWlirAstbHvOf/2Iay2pNAs/SHhI0aF2jsGfvv5/D6N+r9dG
+B2SgDKBg7pywMH1DTvg6YT3P4GjCx0GUHqRCFLvD1rDdk4KSjvaRMpVq1PJ0/Wv6UGtsMS
+TR0PaEHDRNZqAX4YxqujnWrGKuRJhuz0eUvp7fZvbWHtiAMKV7368kkeUmkOHanb+TS+zs
+KINX8ev8zJZ6WVr8Vl+IQavpv0i2bXwS6QqbEuifpv/+uBb7pqRiU4u8en0eMdX1bZoTPM
+R6xHCnGD/Jpb3zS91Ya57T6CiXZ12KCaL6nWGnCkZVpzkfJ2HjFklWSWBQ6uyaosDQ==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1 b/regress/unittests/sshkey/testdata/ecdsa_1
new file mode 100644
index 00000000..80382b62
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIPPNyUAnjvFr+eT/7t/IyjuQQd/aLFiTY92LB9gIjyrMoAoGCCqGSM49
+AwEHoUQDQgAEDFlblkOrW9ydKVhtM+9AY3c9saBE7SG3lFx38nBavkADDaI9jh3/
+kvG/Jt9vpm22qwoklTCGDfzCkXkIKaWlBw==
+-----END EC PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp b/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp
new file mode 100644
index 00000000..e48304f6
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp
@@ -0,0 +1 @@
+SHA256:8ty77fOpABat1y88aNdclQTfU+lVvWe7jYZGw8VYtfg
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub b/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub
new file mode 100644
index 00000000..55e2a256
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgOtFRnMigkGliaYfPmX5IidVWfV3tRH6lqRXv0l8bvKoAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQcAAAAAAAAABwAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2jAHwAAAAAE0eYHAAAAAAAAAAAAAAAAAAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQcAAABkAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABJAAAAIHbxGwTnue7KxhHXGFvRcxBnekhQ3Qx84vV/Vs4oVCrpAAAAIQC7vk2+d14aS7td7kVXLQn392oALjEBzMZoDvT1vT/zOA== ECDSA test key #1
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.fp b/regress/unittests/sshkey/testdata/ecdsa_1.fp
new file mode 100644
index 00000000..e48304f6
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1.fp
@@ -0,0 +1 @@
+SHA256:8ty77fOpABat1y88aNdclQTfU+lVvWe7jYZGw8VYtfg
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb
new file mode 100644
index 00000000..fa23c33c
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb
@@ -0,0 +1 @@
+xibah-vocun-sogyn-byhen-rivem-hegyh-luneh-dozyr-vatyf-dufid-myxyx
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.param.curve b/regress/unittests/sshkey/testdata/ecdsa_1.param.curve
new file mode 100644
index 00000000..fa040046
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1.param.curve
@@ -0,0 +1 @@
+prime256v1
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.param.priv b/regress/unittests/sshkey/testdata/ecdsa_1.param.priv
new file mode 100644
index 00000000..dc908ad7
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1.param.priv
@@ -0,0 +1 @@
+00f3cdc940278ef16bf9e4ffeedfc8ca3b9041dfda2c589363dd8b07d8088f2acc
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.param.pub b/regress/unittests/sshkey/testdata/ecdsa_1.param.pub
new file mode 100644
index 00000000..71c9584d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1.param.pub
@@ -0,0 +1 @@
+040c595b9643ab5bdc9d29586d33ef4063773db1a044ed21b7945c77f2705abe40030da23d8e1dff92f1bf26df6fa66db6ab0a249530860dfcc291790829a5a507
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.pub b/regress/unittests/sshkey/testdata/ecdsa_1.pub
new file mode 100644
index 00000000..84a71f97
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQc= ECDSA test key #1
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1_pw b/regress/unittests/sshkey/testdata/ecdsa_1_pw
new file mode 100644
index 00000000..5c83a658
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1_pw
@@ -0,0 +1,8 @@
+-----BEGIN EC PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,7BA38DE00F67851E4207216809C3BB15
+
+8QkFoZHQkj9a2mt032sp+WKaJ1fwteqWDd4RpAW9OzDgqzMx1QO43qJgBDTfhzjt
+M2Q8YfiGjfBEYpg4kCbacfcV68DEV4z6Ll7rIzzzO7OfWUNL++brD64vKx4z6f46
++sn4nbZTXilpkzi/nmPDVzrNmTSywA8T7Yf0QcBUxks=
+-----END EC PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2 b/regress/unittests/sshkey/testdata/ecdsa_2
new file mode 100644
index 00000000..0f4e844d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2
@@ -0,0 +1,7 @@
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBqBtN7e6Essd3dlsgISViPCXXC0atlNkGtoMgSQdBTKVUfeJOi4lc
+RZaXJdXnqWUqI/KEsH8h8QN4YcB8ugmAcc+gBwYFK4EEACOhgYkDgYYABAHZ2VNy
+oDedBwqsdzY+kkNptc9DrtRCVmO6cULLj+691MhItqVqTMJbTFlI4MnAg9PoGTF/
+0KmLJfy8vSffXGKqqwGKcFNtd1XCo+7Qu9tXbxron9g6Dmu7y8jaLkixcwZwnwLs
+6GmA9qZGuiAfOGV0Gf9/u98sr+vikOa4Ow5JFDTw5g==
+-----END EC PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.fp b/regress/unittests/sshkey/testdata/ecdsa_2.fp
new file mode 100644
index 00000000..581e48ae
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2.fp
@@ -0,0 +1 @@
+SHA256:ed8YniRHA6qCrErCRnzrWxPHxYuA62a+CAFYUVxJgaI
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb
new file mode 100644
index 00000000..e1cc664c
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb
@@ -0,0 +1 @@
+xufag-danul-putub-mokin-pugaz-covid-dofag-nihuz-sysab-genar-zaxyx
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.param.curve b/regress/unittests/sshkey/testdata/ecdsa_2.param.curve
new file mode 100644
index 00000000..617ea2fb
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2.param.curve
@@ -0,0 +1 @@
+secp521r1
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.param.priv b/regress/unittests/sshkey/testdata/ecdsa_2.param.priv
new file mode 100644
index 00000000..dd898d9a
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2.param.priv
@@ -0,0 +1 @@
+01a81b4dedee84b2c777765b202125623c25d70b46ad94d906b683204907414ca5547de24e8b895c45969725d5e7a9652a23f284b07f21f1037861c07cba098071cf
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.param.pub b/regress/unittests/sshkey/testdata/ecdsa_2.param.pub
new file mode 100644
index 00000000..94301c99
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2.param.pub
@@ -0,0 +1 @@
+0401d9d95372a0379d070aac77363e924369b5cf43aed4425663ba7142cb8feebdd4c848b6a56a4cc25b4c5948e0c9c083d3e819317fd0a98b25fcbcbd27df5c62aaab018a70536d7755c2a3eed0bbdb576f1ae89fd83a0e6bbbcbc8da2e48b17306709f02ece86980f6a646ba201f38657419ff7fbbdf2cafebe290e6b83b0e491434f0e6
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.pub b/regress/unittests/sshkey/testdata/ecdsa_2.pub
new file mode 100644
index 00000000..be9d84bf
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAHZ2VNyoDedBwqsdzY+kkNptc9DrtRCVmO6cULLj+691MhItqVqTMJbTFlI4MnAg9PoGTF/0KmLJfy8vSffXGKqqwGKcFNtd1XCo+7Qu9tXbxron9g6Dmu7y8jaLkixcwZwnwLs6GmA9qZGuiAfOGV0Gf9/u98sr+vikOa4Ow5JFDTw5g== ECDSA test key #2
diff --git a/regress/unittests/sshkey/testdata/ecdsa_n b/regress/unittests/sshkey/testdata/ecdsa_n
new file mode 100644
index 00000000..9694f32e
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_n
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
+1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQQMWVuWQ6tb3J0pWG0z70Bjdz2xoETt
+IbeUXHfycFq+QAMNoj2OHf+S8b8m32+mbbarCiSVMIYN/MKReQgppaUHAAAAoFrmmZBa5p
+mQAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlY
+bTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQ
+cAAAAhAPPNyUAnjvFr+eT/7t/IyjuQQd/aLFiTY92LB9gIjyrMAAAAAAECAwQFBgc=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_n_pw b/regress/unittests/sshkey/testdata/ecdsa_n_pw
new file mode 100644
index 00000000..36b7fa78
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_n_pw
@@ -0,0 +1,9 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABC4UwEov5
+z0RrCm7AMCxbuiAAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlz
+dHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvy
+bfb6ZttqsKJJUwhg38wpF5CCmlpQcAAACgbCnAklQTHrf5qiHiMxKYwQJ7k/X9mp4fXD4v
+xUbgNZiXSxN26mn8mC2rH+WA6Lk3CexR/hrtLI2ndpBsYu1h6HhVkOwwm3Kd/PMKArCupW
+l6sYEabrT0EghXR/3aDEZvj79hgKSdu3RpayLvMdbCR8k1cg0/mDmR9hicWfeJ61n/IH05
+tUR268+0BVRW9kDhh/cuv8tVY4L09jCCQ6CpsA==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ed25519_1 b/regress/unittests/sshkey/testdata/ed25519_1
new file mode 100644
index 00000000..6b0ae01c
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQAAAJjnj4Ao54+A
+KAAAAAtzc2gtZWQyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQ
+AAAED3KgoDbjR54V7bdNpfKlQY5m20UK1QaHytkCR+6rZEDFOG6kY7Rf4UtCFvPwKgo/Bz
+tXck2xC4a2WyA34XtIwZAAAAE0VEMjU1MTkgdGVzdCBrZXkgIzEBAg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ed25519_1-cert.fp b/regress/unittests/sshkey/testdata/ed25519_1-cert.fp
new file mode 100644
index 00000000..a9674e2b
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1-cert.fp
@@ -0,0 +1 @@
+SHA256:L3k/oJubblSY0lB9Ulsl7emDMnRPKm/8udf2ccwk560
diff --git a/regress/unittests/sshkey/testdata/ed25519_1-cert.pub b/regress/unittests/sshkey/testdata/ed25519_1-cert.pub
new file mode 100644
index 00000000..649b4e80
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1-cert.pub
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIIxzuxl4z3uwAIslne8Huft+1n1IhHAlNbWZkQyyECCGAAAAIFOG6kY7Rf4UtCFvPwKgo/BztXck2xC4a2WyA34XtIwZAAAAAAAAAAgAAAACAAAABmp1bGl1cwAAABIAAAAFaG9zdDEAAAAFaG9zdDIAAAAANowB8AAAAABNHmBwAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQAAAFMAAAALc3NoLWVkMjU1MTkAAABABGTn+Bmz86Ajk+iqKCSdP5NClsYzn4alJd0V5bizhP0Kumc/HbqQfSt684J1WdSzih+EjvnTgBhK9jTBKb90AQ== ED25519 test key #1
diff --git a/regress/unittests/sshkey/testdata/ed25519_1.fp b/regress/unittests/sshkey/testdata/ed25519_1.fp
new file mode 100644
index 00000000..a9674e2b
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1.fp
@@ -0,0 +1 @@
+SHA256:L3k/oJubblSY0lB9Ulsl7emDMnRPKm/8udf2ccwk560
diff --git a/regress/unittests/sshkey/testdata/ed25519_1.fp.bb b/regress/unittests/sshkey/testdata/ed25519_1.fp.bb
new file mode 100644
index 00000000..309f2daf
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1.fp.bb
@@ -0,0 +1 @@
+xubop-rekyd-bakal-nubuf-pahaf-gicuh-logeb-gocif-petod-galip-fuxux
diff --git a/regress/unittests/sshkey/testdata/ed25519_1.pub b/regress/unittests/sshkey/testdata/ed25519_1.pub
new file mode 100644
index 00000000..e533059e
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFOG6kY7Rf4UtCFvPwKgo/BztXck2xC4a2WyA34XtIwZ ED25519 test key #1
diff --git a/regress/unittests/sshkey/testdata/ed25519_1_pw b/regress/unittests/sshkey/testdata/ed25519_1_pw
new file mode 100644
index 00000000..da94d2b8
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1_pw
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDKT56mBA
+tXIMsWqmuuA2gdAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIFOG6kY7Rf4UtCFv
+PwKgo/BztXck2xC4a2WyA34XtIwZAAAAoC13U47yfUOSZJePNUAwWXuFOk3aOKwPM5PMvK
+0zwRnMZZjgn+tsMAYPwhsT3Mx3h5QzvVGFyFEqsiK7j4vAotD+LVQeBN5TwWbUBx4lnoGs
+3iAfYVDakO/gNvVBDDGOqv5kdCc4cgn5HacjHQLKOAx6KzHe7JFn7uCywMdVVQjlpI6LHb
+mHkaKiVX/C2oiRnsoe17HZ8Fxyt3vd1qNM8BE=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ed25519_2 b/regress/unittests/sshkey/testdata/ed25519_2
new file mode 100644
index 00000000..e4aed639
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_2
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACDPVKyLnm3eZE0lm0IfM3Uy9AsdGSBtozcoCt21blYBCwAAAJix1mBGsdZg
+RgAAAAtzc2gtZWQyNTUxOQAAACDPVKyLnm3eZE0lm0IfM3Uy9AsdGSBtozcoCt21blYBCw
+AAAECZEQHXs18o3DKjhUYaTyt+bUbhqfMeqmsKjYyFvzGVgs9UrIuebd5kTSWbQh8zdTL0
+Cx0ZIG2jNygK3bVuVgELAAAAE0VEMjU1MTkgdGVzdCBrZXkgIzEBAg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ed25519_2.fp b/regress/unittests/sshkey/testdata/ed25519_2.fp
new file mode 100644
index 00000000..04966267
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_2.fp
@@ -0,0 +1 @@
+SHA256:vMbaARqVciRgXyZPNHDo+P5p5WK5yWG1Oo6VC35Bomw
diff --git a/regress/unittests/sshkey/testdata/ed25519_2.fp.bb b/regress/unittests/sshkey/testdata/ed25519_2.fp.bb
new file mode 100644
index 00000000..abba7890
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_2.fp.bb
@@ -0,0 +1 @@
+xuces-bapyb-vikob-zesyv-budod-nupip-kebon-tacyc-fofed-lezic-soxax
diff --git a/regress/unittests/sshkey/testdata/ed25519_2.pub b/regress/unittests/sshkey/testdata/ed25519_2.pub
new file mode 100644
index 00000000..af34236e
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_2.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM9UrIuebd5kTSWbQh8zdTL0Cx0ZIG2jNygK3bVuVgEL ED25519 test key #1
diff --git a/regress/unittests/sshkey/testdata/pw b/regress/unittests/sshkey/testdata/pw
new file mode 100644
index 00000000..8a1dff98
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/pw
@@ -0,0 +1 @@
+mekmitasdigoat
diff --git a/regress/unittests/sshkey/testdata/rsa_1 b/regress/unittests/sshkey/testdata/rsa_1
new file mode 100644
index 00000000..5de3f842
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18u
+d6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKd
+NSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wIDAQAB
+AoGAXyj5mpjmbD+YlxGIWz/zrM4hGsWgd4VteKEJxT6MMI4uzCRpkMd0ck8oHiwZ
+GAI/SwUzIsgtONQuH3AXVsUgghW4Ynn+8ksEv0IZ918WDMDwqvqkyrVzsOsZzqYj
+Pf8DUDKCpwFjnlknJ04yvWBZvVhWtY4OiZ8GV0Ttsu3k+GECQQD1YHfvBb5FdJBv
+Uhde2Il+jaFia8mwVVNNaiD2ECxXx6CzGz54ZLEB9NPVfDUZK8lJ4UJDqelWNh3i
+PF3RefWDAkEA1CVBzAFL4mNwpleVPzrfy69xP3gWOa26MxM/GE6zx9jC7HgQ3KPa
+WKdG/FuHs085aTRDaDLmGcZ8IvMuu7NgKQJAcIOKmxR0Gd8IN7NZugjqixggb0Pj
+mLKXXwESGiJyYtHL0zTj4Uqyi6Ya2GJ66o7UXscmnmYz828fJtTtZBdbRwJBALfi
+C2QvA32Zv/0PEXibKXy996WSC4G3ShwXZKtHHKHvCxY5BDSbehk59VesZrVPyG2e
+NYdOBxD0cIlCzJE56/ECQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/
+h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZs=
+-----END RSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/rsa_1-cert.fp b/regress/unittests/sshkey/testdata/rsa_1-cert.fp
new file mode 100644
index 00000000..79f380a2
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1-cert.fp
@@ -0,0 +1 @@
+SHA256:l6itGumSMcRBBAFteCgmjQBIXqLK/jFGUH3viHX1RmE
diff --git a/regress/unittests/sshkey/testdata/rsa_1-cert.pub b/regress/unittests/sshkey/testdata/rsa_1-cert.pub
new file mode 100644
index 00000000..3bacf3c8
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1-cert.pub
@@ -0,0 +1 @@
+ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg98LhS2EHxLOWCLopZPwHdg/RJXusnkOqQXSc9R7aITkAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wAAAAAAAAAFAAAAAgAAAAZqdWxpdXMAAAASAAAABWhvc3QxAAAABWhvc3QyAAAAADaMAfAAAAAATR5gcAAAAAAAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgU4bqRjtF/hS0IW8/AqCj8HO1dyTbELhrZbIDfhe0jBkAAABTAAAAC3NzaC1lZDI1NTE5AAAAQI3QGlUCzC07KorupxpDkkGy6tniaZ8EvBflzvv+itXWNchGvfUeHmVT6aX0sRqehdz/lR+GmXRoZBhofwh0qAM= RSA test key #1
diff --git a/regress/unittests/sshkey/testdata/rsa_1.fp b/regress/unittests/sshkey/testdata/rsa_1.fp
new file mode 100644
index 00000000..79f380a2
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1.fp
@@ -0,0 +1 @@
+SHA256:l6itGumSMcRBBAFteCgmjQBIXqLK/jFGUH3viHX1RmE
diff --git a/regress/unittests/sshkey/testdata/rsa_1.fp.bb b/regress/unittests/sshkey/testdata/rsa_1.fp.bb
new file mode 100644
index 00000000..45bacd51
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1.fp.bb
@@ -0,0 +1 @@
+xosis-fodod-votot-dibum-ryvac-rediz-naruf-votun-kevis-halis-gexux
diff --git a/regress/unittests/sshkey/testdata/rsa_1.param.n b/regress/unittests/sshkey/testdata/rsa_1.param.n
new file mode 100644
index 00000000..49337121
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1.param.n
@@ -0,0 +1 @@
+00cb5799544edec5ac00ec781fc21a1119ce9a288e3116e72f3e78fbcba6998adcc98c235f2e77abf1ce92b76f064b624552c9f2582341e622e1a176eef232b5bac1bf3881babc0b7d57a1ef4439170852e192bc329d3523354a39610eab916e50c507c913a2a5f2c7596aad779c5f297121438bd2313ebb4ad4d7debba43271fb
diff --git a/regress/unittests/sshkey/testdata/rsa_1.param.p b/regress/unittests/sshkey/testdata/rsa_1.param.p
new file mode 100644
index 00000000..4783d215
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1.param.p
@@ -0,0 +1 @@
+00f56077ef05be4574906f52175ed8897e8da1626bc9b055534d6a20f6102c57c7a0b31b3e7864b101f4d3d57c35192bc949e14243a9e956361de23c5dd179f583
diff --git a/regress/unittests/sshkey/testdata/rsa_1.param.q b/regress/unittests/sshkey/testdata/rsa_1.param.q
new file mode 100644
index 00000000..00fc8a2d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1.param.q
@@ -0,0 +1 @@
+00d42541cc014be26370a657953f3adfcbaf713f781639adba33133f184eb3c7d8c2ec7810dca3da58a746fc5b87b34f396934436832e619c67c22f32ebbb36029
diff --git a/regress/unittests/sshkey/testdata/rsa_1.pub b/regress/unittests/sshkey/testdata/rsa_1.pub
new file mode 100644
index 00000000..23ef872e
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+w== RSA test key #1
diff --git a/regress/unittests/sshkey/testdata/rsa_1_pw b/regress/unittests/sshkey/testdata/rsa_1_pw
new file mode 100644
index 00000000..b4c06745
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1_pw
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,0C3F819F6EEA66A471BAEEDDA8171606
+
+AhQNxgw7Z2un3dpm6KPHF1u5qVvOczm0yiTyPK4U11B3TTRhXOHdzPLAcKMX71Xq
+fmLm2/JIZATUbLTaysLKIQlmAgtpmXoKLv9b90R3AXLophgToZzOLpvlQTCt+y9G
+0E3QQZG/LFy9BLNyw6uD5cy0RHT3FQb5VQDwfBvR/I+K3qWBFLlb7Rw9bCujYczu
+D3bimcDj/k6YkrWVsEa81Ch5RF2RClOYufti6bsvc4xIsB0Kd++vokER+kXFuQqf
+Tl0Jz+SG0kr9QtjVvkhBtSxzJ6/olAosoUySQ5hqsB8iECufBgp1KelXqsHFJQXy
+gCvVmGiivFUinX0rKOuWCHTplsSKQ9BnPSwDAAs8A7ZLcTXcLs/hMQ5r6fmOYfNN
+YthhjZyE2ciJO0lydGJUJMb5aJUak0rl+uINRlYCHTRLVwmCOmpfqz9SfcJb1ieU
+4Us8NR+pXJar4U0+C2wVlNJkAdpL6GvYxN6vp7vLa+BiFwIZOQozswacIZk/ScXm
+QL9rmWug51RCmDeenX46WTEZeB0o0+xi60sDEDhhe4+iNYcJu5L0BJ5lqRFe3I5n
+HRRv1mBEjbF2fDcg/ChYfOXsc4gDivH2nObabeASuMFZyadmXfA8tnXRZf+7Wuy/
+LZGYbM2xLeEyV3ss16WBHuIqexDt04OEZvs0jN90zj6Yv7qKCB975bdOcuKkN2Nn
+n9lA11R2pgsCs6COp9rYiWXkXZeDf3sW6kdcEV+/SzkVsv4JlHcsIzgk4WGVF/E/
+ZkU4J9AvSdJPzEQDM+yszp0eeUow4+SAgpuNTqZiUO/2UUVbsr3qvlYMoCixhFAN
+-----END RSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha1 b/regress/unittests/sshkey/testdata/rsa_1_sha1
new file mode 100644
index 00000000..5de3f842
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1_sha1
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18u
+d6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKd
+NSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wIDAQAB
+AoGAXyj5mpjmbD+YlxGIWz/zrM4hGsWgd4VteKEJxT6MMI4uzCRpkMd0ck8oHiwZ
+GAI/SwUzIsgtONQuH3AXVsUgghW4Ynn+8ksEv0IZ918WDMDwqvqkyrVzsOsZzqYj
+Pf8DUDKCpwFjnlknJ04yvWBZvVhWtY4OiZ8GV0Ttsu3k+GECQQD1YHfvBb5FdJBv
+Uhde2Il+jaFia8mwVVNNaiD2ECxXx6CzGz54ZLEB9NPVfDUZK8lJ4UJDqelWNh3i
+PF3RefWDAkEA1CVBzAFL4mNwpleVPzrfy69xP3gWOa26MxM/GE6zx9jC7HgQ3KPa
+WKdG/FuHs085aTRDaDLmGcZ8IvMuu7NgKQJAcIOKmxR0Gd8IN7NZugjqixggb0Pj
+mLKXXwESGiJyYtHL0zTj4Uqyi6Ya2GJ66o7UXscmnmYz828fJtTtZBdbRwJBALfi
+C2QvA32Zv/0PEXibKXy996WSC4G3ShwXZKtHHKHvCxY5BDSbehk59VesZrVPyG2e
+NYdOBxD0cIlCzJE56/ECQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/
+h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZs=
+-----END RSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha1-cert.pub b/regress/unittests/sshkey/testdata/rsa_1_sha1-cert.pub
new file mode 100644
index 00000000..ff49d759
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1_sha1-cert.pub
@@ -0,0 +1 @@
+ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgy5PGFfSaEuSuXsjvKlMZGXYD0xlnqdZftuW9tMkUYz4AAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wAAAAAAAAABAAAAAQAAAARodWdvAAAAEgAAAAV1c2VyMQAAAAV1c2VyMgAAAAA2i4NgAAAAAE0d4eAAAABEAAAADWZvcmNlLWNvbW1hbmQAAAALAAAABy9iaW4vbHMAAAAOc291cmNlLWFkZHJlc3MAAAAOAAAACjEwLjAuMC4wLzgAAABkAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQD00RRenvxICSYvj54CPiYHM86OT5xwI9XORNH6Zkl3JPCQkAEdQ3hyfhraROaHsSv43wJcKyKrEg5XUZ8fZ/BoKIGU4Rd5AmL9wyPGv2RVY7gWELqXVSpu89R2tQJRmMVMD38CH0wqCTuoZirlKMTen6yfgYuFEpuqar0uOIeAyaQG6/9rVKWK36tcfM7YXx8fmGSN4eK/JhWDDjlo28YJ7ZFF9umh5baZG2Ai/vL3BJ7C3pqaEQNdKj8XqaSoDvFWKfOujk1620Rcuj3W0D0dvp/rH8xz8YkM1dMqGlYIZ4nrF5acB58Nk5FYBjtj1hu4DGEQlWL1Avk1agU4DQLrAAABDwAAAAdzc2gtcnNhAAABAF5BtPY8FbmIekK/zNq6/Lp5agKT5zEVxqAyZKhp75bLRP+kOMZBVB9ZWrekZk6IAVAOCZGQzTsD4mxIQsxBLl8k5hvEWb90/+w9/BzW9ScOGQe+y0COa0QWWR7L3k1S8WX2oAGvtDWOj7Md85nij4ZSU9/QQQFVDF8VilWPSMxUf/3I1fqyDq7AWcZkGk/bFUN6K6RsCSxIPlGmKt0IauyvSMI2IT0XeRT242RngeeUW8vFrn9TXy9YxJRW+cSeLKCuu8agBYyQMXWQ+q39eZZqVYSoo7nFEEhtaLs8d6jzgGkcE9wGJ9KLgfY/mG2vX3gI4IzncKkVJRoeiDzXFIk= RSA test key #1
diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha1.pub b/regress/unittests/sshkey/testdata/rsa_1_sha1.pub
new file mode 100644
index 00000000..23ef872e
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1_sha1.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+w== RSA test key #1
diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha512 b/regress/unittests/sshkey/testdata/rsa_1_sha512
new file mode 100644
index 00000000..5de3f842
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1_sha512
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18u
+d6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKd
+NSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wIDAQAB
+AoGAXyj5mpjmbD+YlxGIWz/zrM4hGsWgd4VteKEJxT6MMI4uzCRpkMd0ck8oHiwZ
+GAI/SwUzIsgtONQuH3AXVsUgghW4Ynn+8ksEv0IZ918WDMDwqvqkyrVzsOsZzqYj
+Pf8DUDKCpwFjnlknJ04yvWBZvVhWtY4OiZ8GV0Ttsu3k+GECQQD1YHfvBb5FdJBv
+Uhde2Il+jaFia8mwVVNNaiD2ECxXx6CzGz54ZLEB9NPVfDUZK8lJ4UJDqelWNh3i
+PF3RefWDAkEA1CVBzAFL4mNwpleVPzrfy69xP3gWOa26MxM/GE6zx9jC7HgQ3KPa
+WKdG/FuHs085aTRDaDLmGcZ8IvMuu7NgKQJAcIOKmxR0Gd8IN7NZugjqixggb0Pj
+mLKXXwESGiJyYtHL0zTj4Uqyi6Ya2GJ66o7UXscmnmYz828fJtTtZBdbRwJBALfi
+C2QvA32Zv/0PEXibKXy996WSC4G3ShwXZKtHHKHvCxY5BDSbehk59VesZrVPyG2e
+NYdOBxD0cIlCzJE56/ECQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/
+h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZs=
+-----END RSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha512-cert.pub b/regress/unittests/sshkey/testdata/rsa_1_sha512-cert.pub
new file mode 100644
index 00000000..47451968
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1_sha512-cert.pub
@@ -0,0 +1 @@
+ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg/bUEmnMYHxlv1N7iXvnYPYdzDjlTRKoaIGEPkaQQQDwAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wAAAAAAAAABAAAAAQAAAARodWdvAAAAEgAAAAV1c2VyMQAAAAV1c2VyMgAAAAA2i4NgAAAAAE0d4eAAAABEAAAADWZvcmNlLWNvbW1hbmQAAAALAAAABy9iaW4vbHMAAAAOc291cmNlLWFkZHJlc3MAAAAOAAAACjEwLjAuMC4wLzgAAABkAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQD00RRenvxICSYvj54CPiYHM86OT5xwI9XORNH6Zkl3JPCQkAEdQ3hyfhraROaHsSv43wJcKyKrEg5XUZ8fZ/BoKIGU4Rd5AmL9wyPGv2RVY7gWELqXVSpu89R2tQJRmMVMD38CH0wqCTuoZirlKMTen6yfgYuFEpuqar0uOIeAyaQG6/9rVKWK36tcfM7YXx8fmGSN4eK/JhWDDjlo28YJ7ZFF9umh5baZG2Ai/vL3BJ7C3pqaEQNdKj8XqaSoDvFWKfOujk1620Rcuj3W0D0dvp/rH8xz8YkM1dMqGlYIZ4nrF5acB58Nk5FYBjtj1hu4DGEQlWL1Avk1agU4DQLrAAABFAAAAAxyc2Etc2hhMi01MTIAAAEA7/GoZsJqrq4xYotsRbpM8arZDjCzT6kohXeD/GVy26s5E/YWXRYCrOMIzSZxjuN5rAaNRW8ffxq14JyI94566Kg2OeoxQ6rK/dTqkk7I1RyypSXunT3I4++RPs1Q+hu9eS/WBzur0/D3dMejhuc3IBg6iB0481I4pGBGcD8/KjQFfhlCuGVXwB1ALk2zfXFT1HYYrs6bYZuQqjgvArnjYJ0do3fTSDC20/ydV4BHnI3fVAY2THVjX45V2ppPadl/rpczaJqW1ZtpnpJkV8Un316stQSD0xLHUDjp89O6d9Yq5S0kDdfwTRJIPm9f2cGNakJwN5qzmmmdDroRKODYcg== RSA test key #1
diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha512.pub b/regress/unittests/sshkey/testdata/rsa_1_sha512.pub
new file mode 100644
index 00000000..23ef872e
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1_sha512.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+w== RSA test key #1
diff --git a/regress/unittests/sshkey/testdata/rsa_2 b/regress/unittests/sshkey/testdata/rsa_2
new file mode 100644
index 00000000..2441d52b
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA9NEUXp78SAkmL4+eAj4mBzPOjk+ccCPVzkTR+mZJdyTwkJAB
+HUN4cn4a2kTmh7Er+N8CXCsiqxIOV1GfH2fwaCiBlOEXeQJi/cMjxr9kVWO4FhC6
+l1UqbvPUdrUCUZjFTA9/Ah9MKgk7qGYq5SjE3p+sn4GLhRKbqmq9LjiHgMmkBuv/
+a1Slit+rXHzO2F8fH5hkjeHivyYVgw45aNvGCe2RRfbpoeW2mRtgIv7y9wSewt6a
+mhEDXSo/F6mkqA7xVinzro5NettEXLo91tA9Hb6f6x/Mc/GJDNXTKhpWCGeJ6xeW
+nAefDZORWAY7Y9YbuAxhEJVi9QL5NWoFOA0C6wIDAQABAoIBAQDtRGVVfwhKWHOl
+zK76xXjdqhwaWJXpKRHiI1jOMawpyKdNtAMgdW+apxUnTXePMurG/HuxEC09VvaH
+MhfhvD6G9BsCS1UQdnuyLRnTWVLIXyjeWcA9QtEpTy8vDSb+Je2xVaNmTybl5qTn
+BH22Mtj6Wg5XWJn7kplDhMdssGTDLsSCMw/rcxe9iT2qOKyltQal23RHzR7SijGp
+QTtBp2SDGhvMZcyGuyMqJ084W8sdJpbyVzdDim2iaZdHlk7uvW2n0HcJ56I6yhIq
+2U8wfgEEwydGVGHgmQNJ/n+SiT/hv6g5ebhDS46X9F9m5CHDwhdr0DrhPBVSsdhl
+1HeJ0+FhAoGBAPuC3uNHToiJis688juKlwc3SQ6ger5ffAg3yaNhEcpHkvOtdZlF
+/CfX94xazMov/YqFwkvpSSdKsX+PeXuaqnb1hPKNYX5t45U9RjB/ox7BIQj/2rPx
+Bfs99UFW9HKP4HsVmLu1xeJg1Pc9iylTK/xrnwfYiZ+H7IGVccizjnqHAoGBAPkv
+n1flAdxBzJH/O0rXoig2EtZsDRMPY51MGDdqVOW14ZOfTVlmu0OSnkSKQm2twfro
+TPDVb2TY3wTRutz8H9yOFW1c1Nz4YOyTb8FmJhE2FWAQ9t8QpwUlhn15if72dS/Y
+22+vP+AYu7wfqGL7QVVEXho5hGjXi053iEvfXBl9AoGAeZISpo1LGphRLgkKlVky
+E1zXxWgwrGB/FYHRx1UeQkZCc+K+Wy4G6kNr9r3VC04TIafx+Lt0jrd+AIibUfG6
+v/GBJ7TLEU+QmAycJskrUaxMiYsSbbPtDjoumDytv8pn2VbhEqqUUg44IqHu6DS5
+qDNlFWfHbgNHgIN6EmcoUXUCgYEAi2G57X4pRjx/4wIy9jAbggaNDuctgQXQoIGZ
+4hVWG49a+CnZKDKweKGgaZI0igjxQhmCQAwC3RP520Y9EbLtV38aOSv93QQJowrt
+Le6nSGVKG4whqrAz3EsbKUA8kiLldbgFNjl+ryjmidnjZEpKRxmQ0XZuu/4k6+Us
+ldQAPjkCgYBwjSm5eDUtK2eEPaBtbJykV05CTv5rn6CKC9L7ZBTkCcdU1hxeqe99
+wb22decnNawGRP1a5cGwqKJPOfkgybJVkdr6aqQW8ClzdFSaenjzs+nVW+T9JTXf
+9lFpIZg5kN/geld3B9B4C99riTM0jg9hbe2RQvpLRTrZbnWMA1XoRw==
+-----END RSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/rsa_2.fp b/regress/unittests/sshkey/testdata/rsa_2.fp
new file mode 100644
index 00000000..4659639d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2.fp
@@ -0,0 +1 @@
+SHA256:NoQh0XBUuYUSWqnzOzOBnfpgJTRWLMj7BlWAb8IbjeE
diff --git a/regress/unittests/sshkey/testdata/rsa_2.fp.bb b/regress/unittests/sshkey/testdata/rsa_2.fp.bb
new file mode 100644
index 00000000..e9d1e4a5
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2.fp.bb
@@ -0,0 +1 @@
+xogit-gupof-mydon-hocep-zuval-feson-rarif-cefar-tobar-ryvap-kuxex
diff --git a/regress/unittests/sshkey/testdata/rsa_2.param.n b/regress/unittests/sshkey/testdata/rsa_2.param.n
new file mode 100644
index 00000000..a669dbf0
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2.param.n
@@ -0,0 +1 @@
+00f4d1145e9efc4809262f8f9e023e260733ce8e4f9c7023d5ce44d1fa66497724f09090011d4378727e1ada44e687b12bf8df025c2b22ab120e57519f1f67f068288194e117790262fdc323c6bf645563b81610ba97552a6ef3d476b5025198c54c0f7f021f4c2a093ba8662ae528c4de9fac9f818b85129baa6abd2e388780c9a406ebff6b54a58adfab5c7cced85f1f1f98648de1e2bf2615830e3968dbc609ed9145f6e9a1e5b6991b6022fef2f7049ec2de9a9a11035d2a3f17a9a4a80ef15629f3ae8e4d7adb445cba3dd6d03d1dbe9feb1fcc73f1890cd5d32a1a56086789eb17969c079f0d939158063b63d61bb80c61109562f502f9356a05380d02eb
diff --git a/regress/unittests/sshkey/testdata/rsa_2.param.p b/regress/unittests/sshkey/testdata/rsa_2.param.p
new file mode 100644
index 00000000..be7c1c36
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2.param.p
@@ -0,0 +1 @@
+00fb82dee3474e88898acebcf23b8a970737490ea07abe5f7c0837c9a36111ca4792f3ad759945fc27d7f78c5accca2ffd8a85c24be949274ab17f8f797b9aaa76f584f28d617e6de3953d46307fa31ec12108ffdab3f105fb3df54156f4728fe07b1598bbb5c5e260d4f73d8b29532bfc6b9f07d8899f87ec819571c8b38e7a87
diff --git a/regress/unittests/sshkey/testdata/rsa_2.param.q b/regress/unittests/sshkey/testdata/rsa_2.param.q
new file mode 100644
index 00000000..6f2c542d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2.param.q
@@ -0,0 +1 @@
+00f92f9f57e501dc41cc91ff3b4ad7a2283612d66c0d130f639d4c18376a54e5b5e1939f4d5966bb43929e448a426dadc1fae84cf0d56f64d8df04d1badcfc1fdc8e156d5cd4dcf860ec936fc166261136156010f6df10a70525867d7989fef6752fd8db6faf3fe018bbbc1fa862fb4155445e1a398468d78b4e77884bdf5c197d
diff --git a/regress/unittests/sshkey/testdata/rsa_2.pub b/regress/unittests/sshkey/testdata/rsa_2.pub
new file mode 100644
index 00000000..3322fbc9
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD00RRenvxICSYvj54CPiYHM86OT5xwI9XORNH6Zkl3JPCQkAEdQ3hyfhraROaHsSv43wJcKyKrEg5XUZ8fZ/BoKIGU4Rd5AmL9wyPGv2RVY7gWELqXVSpu89R2tQJRmMVMD38CH0wqCTuoZirlKMTen6yfgYuFEpuqar0uOIeAyaQG6/9rVKWK36tcfM7YXx8fmGSN4eK/JhWDDjlo28YJ7ZFF9umh5baZG2Ai/vL3BJ7C3pqaEQNdKj8XqaSoDvFWKfOujk1620Rcuj3W0D0dvp/rH8xz8YkM1dMqGlYIZ4nrF5acB58Nk5FYBjtj1hu4DGEQlWL1Avk1agU4DQLr RSA test key #2
diff --git a/regress/unittests/sshkey/testdata/rsa_n b/regress/unittests/sshkey/testdata/rsa_n
new file mode 100644
index 00000000..b8e585e5
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_n
@@ -0,0 +1,16 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcn
+NhAAAAAwEAAQAAAIEAy1eZVE7exawA7HgfwhoRGc6aKI4xFucvPnj7y6aZitzJjCNfLner
+8c6St28GS2JFUsnyWCNB5iLhoXbu8jK1usG/OIG6vAt9V6HvRDkXCFLhkrwynTUjNUo5YQ
+6rkW5QxQfJE6Kl8sdZaq13nF8pcSFDi9IxPrtK1Nfeu6QycfsAAAH4to4I7raOCO4AAAAH
+c3NoLXJzYQAAAIEAy1eZVE7exawA7HgfwhoRGc6aKI4xFucvPnj7y6aZitzJjCNfLner8c
+6St28GS2JFUsnyWCNB5iLhoXbu8jK1usG/OIG6vAt9V6HvRDkXCFLhkrwynTUjNUo5YQ6r
+kW5QxQfJE6Kl8sdZaq13nF8pcSFDi9IxPrtK1Nfeu6QycfsAAAADAQABAAAAgF8o+ZqY5m
+w/mJcRiFs/86zOIRrFoHeFbXihCcU+jDCOLswkaZDHdHJPKB4sGRgCP0sFMyLILTjULh9w
+F1bFIIIVuGJ5/vJLBL9CGfdfFgzA8Kr6pMq1c7DrGc6mIz3/A1AygqcBY55ZJydOMr1gWb
+1YVrWODomfBldE7bLt5PhhAAAAQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/
+h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZsAAABBAPVgd+8FvkV0kG9SF17YiX
+6NoWJrybBVU01qIPYQLFfHoLMbPnhksQH009V8NRkryUnhQkOp6VY2HeI8XdF59YMAAABB
+ANQlQcwBS+JjcKZXlT8638uvcT94FjmtujMTPxhOs8fYwux4ENyj2linRvxbh7NPOWk0Q2
+gy5hnGfCLzLruzYCkAAAAAAQID
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/rsa_n_pw b/regress/unittests/sshkey/testdata/rsa_n_pw
new file mode 100644
index 00000000..dc18373b
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_n_pw
@@ -0,0 +1,17 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABAFw/Wg/V
+I5SAXWj/HJr9qeAAAAEAAAAAEAAACXAAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7F
+rADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu
+7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylx
+IUOL0jE+u0rU1967pDJx+wAAAgD1iSGiMlMJt2VH4kx5yr0wCJS+4UOmX0bxKO7UH5Jcul
+K5eaSe5ZoKE7hTYBaz0K5dRF/0fqLsvVZlE4quDjFLN6Hyavgn2W/QM7SUqBHgRMal9pgH
+LnxX6mFNWJ+4yb7f3bcbVIdgmMm3sT9Xjwaf5xgzNlR2mkUWtFwjyQh6FxUo5apNzqNBwO
+l2Q4xfmyZTp1s++pStQ/su6obXpxnE2Nx5G/D84ZL5iWl+njUy/MvJTazHRbiTSyihU+UA
+mUr5ZNuP3WUYY+h3KVlHpYHJYB7l3AMTKuPMFLhY9V7BJ+DuKPaqBgX4hvRzY0eVQiFr61
+ovjWjvfu1ulx550JqdYCgH2PpP0E89OQne35Cxs9QPThfe8DKojC9YquYh9zmVTvr7kNiE
+Soluk/7oKpQIDaC+/SRk7AJ2e3Cbt1lXyGNn37PuqaaC/apaF/DOD6Yig9aClS7jOUrT96
+56trFAYfHEIKbRCUSMCiM1+x6HOLYf5ROrGE9KxT3kUD9XMsMpTva+cPpHUpbGpXcYE10N
+MyYDz+V5M2/ZoIdEhscJNQ3UnhaZpeEaqcOyNyo90n3Dnaw/WpMDD/kNMGfm8daTaYInnQ
+QnwA2gwlYfpTAqxE71oXgOuGmtA0yqJB4778Xq26Pb+B7/mZZZe6n0FVmiNC+ZG37ZGOw/
+iGL9e2Sxzw==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/tests.c b/regress/unittests/sshkey/tests.c
new file mode 100644
index 00000000..78aa9223
--- /dev/null
+++ b/regress/unittests/sshkey/tests.c
@@ -0,0 +1,22 @@
+/* $OpenBSD: tests.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */
+/*
+ * Regress test for sshbuf.h buffer API
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include "../test_helper/test_helper.h"
+
+void sshkey_tests(void);
+void sshkey_file_tests(void);
+void sshkey_fuzz_tests(void);
+
+void
+tests(void)
+{
+ sshkey_tests();
+ sshkey_file_tests();
+ sshkey_fuzz_tests();
+}
diff --git a/regress/unittests/test_helper/Makefile b/regress/unittests/test_helper/Makefile
new file mode 100644
index 00000000..78026e65
--- /dev/null
+++ b/regress/unittests/test_helper/Makefile
@@ -0,0 +1,15 @@
+# $OpenBSD: Makefile,v 1.3 2016/07/04 18:01:44 guenther Exp $
+
+LIB= test_helper
+SRCS= test_helper.c fuzz.c
+
+NOPROFILE= yes
+NOPIC= yes
+
+# Hack to allow building with SUBDIR in ../../Makefile
+regress: all
+
+install:
+ @echo -n
+
+.include <bsd.lib.mk>
diff --git a/regress/unittests/test_helper/fuzz.c b/regress/unittests/test_helper/fuzz.c
new file mode 100644
index 00000000..78b36654
--- /dev/null
+++ b/regress/unittests/test_helper/fuzz.c
@@ -0,0 +1,438 @@
+/* $OpenBSD: fuzz.c,v 1.8 2015/03/03 20:42:49 djm Exp $ */
+/*
+ * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* Utility functions/framework for fuzz tests */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "test_helper.h"
+#include "atomicio.h"
+
+/* #define FUZZ_DEBUG */
+
+#ifdef FUZZ_DEBUG
+# define FUZZ_DBG(x) do { \
+ printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \
+ printf x; \
+ printf("\n"); \
+ fflush(stdout); \
+ } while (0)
+#else
+# define FUZZ_DBG(x)
+#endif
+
+/* For brevity later */
+typedef unsigned long long fuzz_ullong;
+
+/* For base-64 fuzzing */
+static const char fuzz_b64chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+struct fuzz {
+ /* Fuzz method currently in use */
+ int strategy;
+
+ /* Fuzz methods remaining */
+ int strategies;
+
+ /* Original seed data blob */
+ void *seed;
+ size_t slen;
+
+ /* Current working copy of seed with fuzz mutations applied */
+ u_char *fuzzed;
+
+ /* Used by fuzz methods */
+ size_t o1, o2;
+};
+
+static const char *
+fuzz_ntop(u_int n)
+{
+ switch (n) {
+ case 0:
+ return "NONE";
+ case FUZZ_1_BIT_FLIP:
+ return "FUZZ_1_BIT_FLIP";
+ case FUZZ_2_BIT_FLIP:
+ return "FUZZ_2_BIT_FLIP";
+ case FUZZ_1_BYTE_FLIP:
+ return "FUZZ_1_BYTE_FLIP";
+ case FUZZ_2_BYTE_FLIP:
+ return "FUZZ_2_BYTE_FLIP";
+ case FUZZ_TRUNCATE_START:
+ return "FUZZ_TRUNCATE_START";
+ case FUZZ_TRUNCATE_END:
+ return "FUZZ_TRUNCATE_END";
+ case FUZZ_BASE64:
+ return "FUZZ_BASE64";
+ default:
+ abort();
+ }
+}
+
+static int
+fuzz_fmt(struct fuzz *fuzz, char *s, size_t n)
+{
+ if (fuzz == NULL)
+ return -1;
+
+ switch (fuzz->strategy) {
+ case FUZZ_1_BIT_FLIP:
+ snprintf(s, n, "%s case %zu of %zu (bit: %zu)\n",
+ fuzz_ntop(fuzz->strategy),
+ fuzz->o1, fuzz->slen * 8, fuzz->o1);
+ return 0;
+ case FUZZ_2_BIT_FLIP:
+ snprintf(s, n, "%s case %llu of %llu (bits: %zu, %zu)\n",
+ fuzz_ntop(fuzz->strategy),
+ (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1,
+ ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8,
+ fuzz->o1, fuzz->o2);
+ return 0;
+ case FUZZ_1_BYTE_FLIP:
+ snprintf(s, n, "%s case %zu of %zu (byte: %zu)\n",
+ fuzz_ntop(fuzz->strategy),
+ fuzz->o1, fuzz->slen, fuzz->o1);
+ return 0;
+ case FUZZ_2_BYTE_FLIP:
+ snprintf(s, n, "%s case %llu of %llu (bytes: %zu, %zu)\n",
+ fuzz_ntop(fuzz->strategy),
+ (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1,
+ ((fuzz_ullong)fuzz->slen) * fuzz->slen,
+ fuzz->o1, fuzz->o2);
+ return 0;
+ case FUZZ_TRUNCATE_START:
+ snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
+ fuzz_ntop(fuzz->strategy),
+ fuzz->o1, fuzz->slen, fuzz->o1);
+ return 0;
+ case FUZZ_TRUNCATE_END:
+ snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
+ fuzz_ntop(fuzz->strategy),
+ fuzz->o1, fuzz->slen, fuzz->o1);
+ return 0;
+ case FUZZ_BASE64:
+ assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
+ snprintf(s, n, "%s case %llu of %llu (offset: %zu char: %c)\n",
+ fuzz_ntop(fuzz->strategy),
+ (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2,
+ fuzz->slen * (fuzz_ullong)64, fuzz->o1,
+ fuzz_b64chars[fuzz->o2]);
+ return 0;
+ default:
+ return -1;
+ abort();
+ }
+}
+
+static void
+dump(u_char *p, size_t len)
+{
+ size_t i, j;
+
+ for (i = 0; i < len; i += 16) {
+ fprintf(stderr, "%.4zd: ", i);
+ for (j = i; j < i + 16; j++) {
+ if (j < len)
+ fprintf(stderr, "%02x ", p[j]);
+ else
+ fprintf(stderr, " ");
+ }
+ fprintf(stderr, " ");
+ for (j = i; j < i + 16; j++) {
+ if (j < len) {
+ if (isascii(p[j]) && isprint(p[j]))
+ fprintf(stderr, "%c", p[j]);
+ else
+ fprintf(stderr, ".");
+ }
+ }
+ fprintf(stderr, "\n");
+ }
+}
+
+void
+fuzz_dump(struct fuzz *fuzz)
+{
+ char buf[256];
+
+ if (fuzz_fmt(fuzz, buf, sizeof(buf)) != 0) {
+ fprintf(stderr, "%s: fuzz invalid\n", __func__);
+ abort();
+ }
+ fputs(buf, stderr);
+ fprintf(stderr, "fuzz original %p len = %zu\n", fuzz->seed, fuzz->slen);
+ dump(fuzz->seed, fuzz->slen);
+ fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, fuzz_len(fuzz));
+ dump(fuzz_ptr(fuzz), fuzz_len(fuzz));
+}
+
+static struct fuzz *last_fuzz;
+
+static void
+siginfo(int unused __attribute__((__unused__)))
+{
+ char buf[256];
+
+ test_info(buf, sizeof(buf));
+ atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
+ if (last_fuzz != NULL) {
+ fuzz_fmt(last_fuzz, buf, sizeof(buf));
+ atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
+ }
+}
+
+struct fuzz *
+fuzz_begin(u_int strategies, const void *p, size_t l)
+{
+ struct fuzz *ret = calloc(sizeof(*ret), 1);
+
+ assert(p != NULL);
+ assert(ret != NULL);
+ ret->seed = malloc(l);
+ assert(ret->seed != NULL);
+ memcpy(ret->seed, p, l);
+ ret->slen = l;
+ ret->strategies = strategies;
+
+ assert(ret->slen < SIZE_MAX / 8);
+ assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1)));
+
+ FUZZ_DBG(("begin, ret = %p", ret));
+
+ fuzz_next(ret);
+
+ last_fuzz = ret;
+#ifdef SIGINFO
+ signal(SIGINFO, siginfo);
+#endif
+ signal(SIGUSR1, siginfo);
+
+ return ret;
+}
+
+void
+fuzz_cleanup(struct fuzz *fuzz)
+{
+ FUZZ_DBG(("cleanup, fuzz = %p", fuzz));
+ last_fuzz = NULL;
+#ifdef SIGINFO
+ signal(SIGINFO, SIG_DFL);
+#endif
+ signal(SIGUSR1, SIG_DFL);
+ assert(fuzz != NULL);
+ assert(fuzz->seed != NULL);
+ assert(fuzz->fuzzed != NULL);
+ free(fuzz->seed);
+ free(fuzz->fuzzed);
+ free(fuzz);
+}
+
+static int
+fuzz_strategy_done(struct fuzz *fuzz)
+{
+ FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu",
+ fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen));
+
+ switch (fuzz->strategy) {
+ case FUZZ_1_BIT_FLIP:
+ return fuzz->o1 >= fuzz->slen * 8;
+ case FUZZ_2_BIT_FLIP:
+ return fuzz->o2 >= fuzz->slen * 8;
+ case FUZZ_2_BYTE_FLIP:
+ return fuzz->o2 >= fuzz->slen;
+ case FUZZ_1_BYTE_FLIP:
+ case FUZZ_TRUNCATE_START:
+ case FUZZ_TRUNCATE_END:
+ case FUZZ_BASE64:
+ return fuzz->o1 >= fuzz->slen;
+ default:
+ abort();
+ }
+}
+
+void
+fuzz_next(struct fuzz *fuzz)
+{
+ u_int i;
+
+ FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, "
+ "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy),
+ (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen));
+
+ if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) {
+ /* If we are just starting out, we need to allocate too */
+ if (fuzz->fuzzed == NULL) {
+ FUZZ_DBG(("alloc"));
+ fuzz->fuzzed = calloc(fuzz->slen, 1);
+ }
+ /* Pick next strategy */
+ FUZZ_DBG(("advance"));
+ for (i = 1; i <= FUZZ_MAX; i <<= 1) {
+ if ((fuzz->strategies & i) != 0) {
+ fuzz->strategy = i;
+ break;
+ }
+ }
+ FUZZ_DBG(("selected = %u", fuzz->strategy));
+ if (fuzz->strategy == 0) {
+ FUZZ_DBG(("done, no more strategies"));
+ return;
+ }
+ fuzz->strategies &= ~(fuzz->strategy);
+ fuzz->o1 = fuzz->o2 = 0;
+ }
+
+ assert(fuzz->fuzzed != NULL);
+
+ switch (fuzz->strategy) {
+ case FUZZ_1_BIT_FLIP:
+ assert(fuzz->o1 / 8 < fuzz->slen);
+ memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
+ fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8);
+ fuzz->o1++;
+ break;
+ case FUZZ_2_BIT_FLIP:
+ assert(fuzz->o1 / 8 < fuzz->slen);
+ assert(fuzz->o2 / 8 < fuzz->slen);
+ memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
+ fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8);
+ fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8);
+ fuzz->o1++;
+ if (fuzz->o1 >= fuzz->slen * 8) {
+ fuzz->o1 = 0;
+ fuzz->o2++;
+ }
+ break;
+ case FUZZ_1_BYTE_FLIP:
+ assert(fuzz->o1 < fuzz->slen);
+ memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
+ fuzz->fuzzed[fuzz->o1] ^= 0xff;
+ fuzz->o1++;
+ break;
+ case FUZZ_2_BYTE_FLIP:
+ assert(fuzz->o1 < fuzz->slen);
+ assert(fuzz->o2 < fuzz->slen);
+ memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
+ fuzz->fuzzed[fuzz->o1] ^= 0xff;
+ fuzz->fuzzed[fuzz->o2] ^= 0xff;
+ fuzz->o1++;
+ if (fuzz->o1 >= fuzz->slen) {
+ fuzz->o1 = 0;
+ fuzz->o2++;
+ }
+ break;
+ case FUZZ_TRUNCATE_START:
+ case FUZZ_TRUNCATE_END:
+ assert(fuzz->o1 < fuzz->slen);
+ memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
+ fuzz->o1++;
+ break;
+ case FUZZ_BASE64:
+ assert(fuzz->o1 < fuzz->slen);
+ assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
+ memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
+ fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2];
+ fuzz->o2++;
+ if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) {
+ fuzz->o2 = 0;
+ fuzz->o1++;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, "
+ "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy),
+ (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen));
+}
+
+int
+fuzz_matches_original(struct fuzz *fuzz)
+{
+ if (fuzz_len(fuzz) != fuzz->slen)
+ return 0;
+ return memcmp(fuzz_ptr(fuzz), fuzz->seed, fuzz->slen) == 0;
+}
+
+int
+fuzz_done(struct fuzz *fuzz)
+{
+ FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz,
+ (u_long)fuzz->strategies));
+
+ return fuzz_strategy_done(fuzz) && fuzz->strategies == 0;
+}
+
+size_t
+fuzz_len(struct fuzz *fuzz)
+{
+ assert(fuzz->fuzzed != NULL);
+ switch (fuzz->strategy) {
+ case FUZZ_1_BIT_FLIP:
+ case FUZZ_2_BIT_FLIP:
+ case FUZZ_1_BYTE_FLIP:
+ case FUZZ_2_BYTE_FLIP:
+ case FUZZ_BASE64:
+ return fuzz->slen;
+ case FUZZ_TRUNCATE_START:
+ case FUZZ_TRUNCATE_END:
+ assert(fuzz->o1 <= fuzz->slen);
+ return fuzz->slen - fuzz->o1;
+ default:
+ abort();
+ }
+}
+
+u_char *
+fuzz_ptr(struct fuzz *fuzz)
+{
+ assert(fuzz->fuzzed != NULL);
+ switch (fuzz->strategy) {
+ case FUZZ_1_BIT_FLIP:
+ case FUZZ_2_BIT_FLIP:
+ case FUZZ_1_BYTE_FLIP:
+ case FUZZ_2_BYTE_FLIP:
+ case FUZZ_BASE64:
+ return fuzz->fuzzed;
+ case FUZZ_TRUNCATE_START:
+ assert(fuzz->o1 <= fuzz->slen);
+ return fuzz->fuzzed + fuzz->o1;
+ case FUZZ_TRUNCATE_END:
+ assert(fuzz->o1 <= fuzz->slen);
+ return fuzz->fuzzed;
+ default:
+ abort();
+ }
+}
+
diff --git a/regress/unittests/test_helper/test_helper.c b/regress/unittests/test_helper/test_helper.c
new file mode 100644
index 00000000..9014ce8e
--- /dev/null
+++ b/regress/unittests/test_helper/test_helper.c
@@ -0,0 +1,594 @@
+/* $OpenBSD: test_helper.c,v 1.12 2019/08/02 01:41:24 djm Exp $ */
+/*
+ * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* Utility functions/framework for regress tests */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+
+#include <stdarg.h>
+#include <fcntl.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <signal.h>
+
+#ifdef WITH_OPENSSL
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#endif
+
+#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
+# include <vis.h>
+#endif
+
+#include "entropy.h"
+#include "test_helper.h"
+#include "atomicio.h"
+
+#define TEST_CHECK_INT(r, pred) do { \
+ switch (pred) { \
+ case TEST_EQ: \
+ if (r == 0) \
+ return; \
+ break; \
+ case TEST_NE: \
+ if (r != 0) \
+ return; \
+ break; \
+ case TEST_LT: \
+ if (r < 0) \
+ return; \
+ break; \
+ case TEST_LE: \
+ if (r <= 0) \
+ return; \
+ break; \
+ case TEST_GT: \
+ if (r > 0) \
+ return; \
+ break; \
+ case TEST_GE: \
+ if (r >= 0) \
+ return; \
+ break; \
+ default: \
+ abort(); \
+ } \
+ } while (0)
+
+#define TEST_CHECK(x1, x2, pred) do { \
+ switch (pred) { \
+ case TEST_EQ: \
+ if (x1 == x2) \
+ return; \
+ break; \
+ case TEST_NE: \
+ if (x1 != x2) \
+ return; \
+ break; \
+ case TEST_LT: \
+ if (x1 < x2) \
+ return; \
+ break; \
+ case TEST_LE: \
+ if (x1 <= x2) \
+ return; \
+ break; \
+ case TEST_GT: \
+ if (x1 > x2) \
+ return; \
+ break; \
+ case TEST_GE: \
+ if (x1 >= x2) \
+ return; \
+ break; \
+ default: \
+ abort(); \
+ } \
+ } while (0)
+
+extern char *__progname;
+
+static int verbose_mode = 0;
+static int quiet_mode = 0;
+static char *active_test_name = NULL;
+static u_int test_number = 0;
+static test_onerror_func_t *test_onerror = NULL;
+static void *onerror_ctx = NULL;
+static const char *data_dir = NULL;
+static char subtest_info[512];
+static int fast = 0;
+static int slow = 0;
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+
+ seed_rng();
+#ifdef WITH_OPENSSL
+ ERR_load_CRYPTO_strings();
+#endif
+
+ /* Handle systems without __progname */
+ if (__progname == NULL) {
+ __progname = strrchr(argv[0], '/');
+ if (__progname == NULL || __progname[1] == '\0')
+ __progname = argv[0];
+ else
+ __progname++;
+ if ((__progname = strdup(__progname)) == NULL) {
+ fprintf(stderr, "strdup failed\n");
+ exit(1);
+ }
+ }
+
+ while ((ch = getopt(argc, argv, "Ffvqd:")) != -1) {
+ switch (ch) {
+ case 'F':
+ slow = 1;
+ break;
+ case 'f':
+ fast = 1;
+ break;
+ case 'd':
+ data_dir = optarg;
+ break;
+ case 'q':
+ verbose_mode = 0;
+ quiet_mode = 1;
+ break;
+ case 'v':
+ verbose_mode = 1;
+ quiet_mode = 0;
+ break;
+ default:
+ fprintf(stderr, "Unrecognised command line option\n");
+ fprintf(stderr, "Usage: %s [-v]\n", __progname);
+ exit(1);
+ }
+ }
+ setvbuf(stdout, NULL, _IONBF, 0);
+ if (!quiet_mode)
+ printf("%s: ", __progname);
+ if (verbose_mode)
+ printf("\n");
+
+ tests();
+
+ if (!quiet_mode)
+ printf(" %u tests ok\n", test_number);
+ return 0;
+}
+
+int
+test_is_verbose(void)
+{
+ return verbose_mode;
+}
+
+int
+test_is_quiet(void)
+{
+ return quiet_mode;
+}
+
+int
+test_is_fast(void)
+{
+ return fast;
+}
+
+int
+test_is_slow(void)
+{
+ return slow;
+}
+
+const char *
+test_data_file(const char *name)
+{
+ static char ret[PATH_MAX];
+
+ if (data_dir != NULL)
+ snprintf(ret, sizeof(ret), "%s/%s", data_dir, name);
+ else
+ strlcpy(ret, name, sizeof(ret));
+ if (access(ret, F_OK) != 0) {
+ fprintf(stderr, "Cannot access data file %s: %s\n",
+ ret, strerror(errno));
+ exit(1);
+ }
+ return ret;
+}
+
+void
+test_info(char *s, size_t len)
+{
+ snprintf(s, len, "In test %u: \"%s\"%s%s\n", test_number,
+ active_test_name == NULL ? "<none>" : active_test_name,
+ *subtest_info != '\0' ? " - " : "", subtest_info);
+}
+
+static void
+siginfo(int unused __attribute__((__unused__)))
+{
+ char buf[256];
+
+ test_info(buf, sizeof(buf));
+ atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
+}
+
+void
+test_start(const char *n)
+{
+ assert(active_test_name == NULL);
+ assert((active_test_name = strdup(n)) != NULL);
+ *subtest_info = '\0';
+ if (verbose_mode)
+ printf("test %u - \"%s\": ", test_number, active_test_name);
+ test_number++;
+#ifdef SIGINFO
+ signal(SIGINFO, siginfo);
+#endif
+ signal(SIGUSR1, siginfo);
+}
+
+void
+set_onerror_func(test_onerror_func_t *f, void *ctx)
+{
+ test_onerror = f;
+ onerror_ctx = ctx;
+}
+
+void
+test_done(void)
+{
+ *subtest_info = '\0';
+ assert(active_test_name != NULL);
+ free(active_test_name);
+ active_test_name = NULL;
+ if (verbose_mode)
+ printf("OK\n");
+ else if (!quiet_mode) {
+ printf(".");
+ fflush(stdout);
+ }
+}
+
+void
+test_subtest_info(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(subtest_info, sizeof(subtest_info), fmt, ap);
+ va_end(ap);
+}
+
+void
+ssl_err_check(const char *file, int line)
+{
+#ifdef WITH_OPENSSL
+ long openssl_error = ERR_get_error();
+
+ if (openssl_error == 0)
+ return;
+
+ fprintf(stderr, "\n%s:%d: uncaught OpenSSL error: %s",
+ file, line, ERR_error_string(openssl_error, NULL));
+#else /* WITH_OPENSSL */
+ fprintf(stderr, "\n%s:%d: uncaught OpenSSL error ",
+ file, line);
+#endif /* WITH_OPENSSL */
+ abort();
+}
+
+static const char *
+pred_name(enum test_predicate p)
+{
+ switch (p) {
+ case TEST_EQ:
+ return "EQ";
+ case TEST_NE:
+ return "NE";
+ case TEST_LT:
+ return "LT";
+ case TEST_LE:
+ return "LE";
+ case TEST_GT:
+ return "GT";
+ case TEST_GE:
+ return "GE";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static void
+test_die(void)
+{
+ if (test_onerror != NULL)
+ test_onerror(onerror_ctx);
+ abort();
+}
+
+static void
+test_header(const char *file, int line, const char *a1, const char *a2,
+ const char *name, enum test_predicate pred)
+{
+ fprintf(stderr, "\n%s:%d test #%u \"%s\"%s%s\n",
+ file, line, test_number, active_test_name,
+ *subtest_info != '\0' ? " - " : "", subtest_info);
+ fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n",
+ name, pred_name(pred), a1,
+ a2 != NULL ? ", " : "", a2 != NULL ? a2 : "");
+}
+
+#ifdef WITH_OPENSSL
+void
+assert_bignum(const char *file, int line, const char *a1, const char *a2,
+ const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred)
+{
+ int r = BN_cmp(aa1, aa2);
+
+ TEST_CHECK_INT(r, pred);
+ test_header(file, line, a1, a2, "BIGNUM", pred);
+ fprintf(stderr, "%12s = 0x%s\n", a1, BN_bn2hex(aa1));
+ fprintf(stderr, "%12s = 0x%s\n", a2, BN_bn2hex(aa2));
+ test_die();
+}
+#endif
+
+void
+assert_string(const char *file, int line, const char *a1, const char *a2,
+ const char *aa1, const char *aa2, enum test_predicate pred)
+{
+ int r;
+
+ /* Verify pointers are not NULL */
+ assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
+ assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE);
+
+ r = strcmp(aa1, aa2);
+ TEST_CHECK_INT(r, pred);
+ test_header(file, line, a1, a2, "STRING", pred);
+ fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1));
+ fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2, strlen(aa2));
+ test_die();
+}
+
+static char *
+tohex(const void *_s, size_t l)
+{
+ u_int8_t *s = (u_int8_t *)_s;
+ size_t i, j;
+ const char *hex = "0123456789abcdef";
+ char *r = malloc((l * 2) + 1);
+
+ assert(r != NULL);
+ for (i = j = 0; i < l; i++) {
+ r[j++] = hex[(s[i] >> 4) & 0xf];
+ r[j++] = hex[s[i] & 0xf];
+ }
+ r[j] = '\0';
+ return r;
+}
+
+void
+assert_mem(const char *file, int line, const char *a1, const char *a2,
+ const void *aa1, const void *aa2, size_t l, enum test_predicate pred)
+{
+ int r;
+ char *aa1_tohex = NULL;
+ char *aa2_tohex = NULL;
+
+ if (l == 0)
+ return;
+ /* If length is >0, then verify pointers are not NULL */
+ assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
+ assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE);
+
+ r = memcmp(aa1, aa2, l);
+ TEST_CHECK_INT(r, pred);
+ test_header(file, line, a1, a2, "STRING", pred);
+ aa1_tohex = tohex(aa1, MIN(l, 256));
+ aa2_tohex = tohex(aa2, MIN(l, 256));
+ fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1_tohex, l);
+ fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2_tohex, l);
+ free(aa1_tohex);
+ free(aa2_tohex);
+ test_die();
+}
+
+static int
+memvalcmp(const u_int8_t *s, u_char v, size_t l, size_t *where)
+{
+ size_t i;
+
+ for (i = 0; i < l; i++) {
+ if (s[i] != v) {
+ *where = i;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void
+assert_mem_filled(const char *file, int line, const char *a1,
+ const void *aa1, u_char v, size_t l, enum test_predicate pred)
+{
+ size_t where = -1;
+ int r;
+ char tmp[64];
+ char *aa1_tohex = NULL;
+
+ if (l == 0)
+ return;
+ /* If length is >0, then verify the pointer is not NULL */
+ assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
+
+ r = memvalcmp(aa1, v, l, &where);
+ TEST_CHECK_INT(r, pred);
+ test_header(file, line, a1, NULL, "MEM_ZERO", pred);
+ aa1_tohex = tohex(aa1, MIN(l, 20));
+ fprintf(stderr, "%20s = %s%s (len %zu)\n", a1,
+ aa1_tohex, l > 20 ? "..." : "", l);
+ free(aa1_tohex);
+ snprintf(tmp, sizeof(tmp), "(%s)[%zu]", a1, where);
+ fprintf(stderr, "%20s = 0x%02x (expected 0x%02x)\n", tmp,
+ ((u_char *)aa1)[where], v);
+ test_die();
+}
+
+void
+assert_int(const char *file, int line, const char *a1, const char *a2,
+ int aa1, int aa2, enum test_predicate pred)
+{
+ TEST_CHECK(aa1, aa2, pred);
+ test_header(file, line, a1, a2, "INT", pred);
+ fprintf(stderr, "%12s = %d\n", a1, aa1);
+ fprintf(stderr, "%12s = %d\n", a2, aa2);
+ test_die();
+}
+
+void
+assert_size_t(const char *file, int line, const char *a1, const char *a2,
+ size_t aa1, size_t aa2, enum test_predicate pred)
+{
+ TEST_CHECK(aa1, aa2, pred);
+ test_header(file, line, a1, a2, "SIZE_T", pred);
+ fprintf(stderr, "%12s = %zu\n", a1, aa1);
+ fprintf(stderr, "%12s = %zu\n", a2, aa2);
+ test_die();
+}
+
+void
+assert_u_int(const char *file, int line, const char *a1, const char *a2,
+ u_int aa1, u_int aa2, enum test_predicate pred)
+{
+ TEST_CHECK(aa1, aa2, pred);
+ test_header(file, line, a1, a2, "U_INT", pred);
+ fprintf(stderr, "%12s = %u / 0x%x\n", a1, aa1, aa1);
+ fprintf(stderr, "%12s = %u / 0x%x\n", a2, aa2, aa2);
+ test_die();
+}
+
+void
+assert_long(const char *file, int line, const char *a1, const char *a2,
+ long aa1, long aa2, enum test_predicate pred)
+{
+ TEST_CHECK(aa1, aa2, pred);
+ test_header(file, line, a1, a2, "LONG", pred);
+ fprintf(stderr, "%12s = %ld / 0x%lx\n", a1, aa1, aa1);
+ fprintf(stderr, "%12s = %ld / 0x%lx\n", a2, aa2, aa2);
+ test_die();
+}
+
+void
+assert_long_long(const char *file, int line, const char *a1, const char *a2,
+ long long aa1, long long aa2, enum test_predicate pred)
+{
+ TEST_CHECK(aa1, aa2, pred);
+ test_header(file, line, a1, a2, "LONG LONG", pred);
+ fprintf(stderr, "%12s = %lld / 0x%llx\n", a1, aa1, aa1);
+ fprintf(stderr, "%12s = %lld / 0x%llx\n", a2, aa2, aa2);
+ test_die();
+}
+
+void
+assert_char(const char *file, int line, const char *a1, const char *a2,
+ char aa1, char aa2, enum test_predicate pred)
+{
+ char buf[8];
+
+ TEST_CHECK(aa1, aa2, pred);
+ test_header(file, line, a1, a2, "CHAR", pred);
+ fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1,
+ vis(buf, aa1, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa1);
+ fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1,
+ vis(buf, aa2, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa2);
+ test_die();
+}
+
+void
+assert_u8(const char *file, int line, const char *a1, const char *a2,
+ u_int8_t aa1, u_int8_t aa2, enum test_predicate pred)
+{
+ TEST_CHECK(aa1, aa2, pred);
+ test_header(file, line, a1, a2, "U8", pred);
+ fprintf(stderr, "%12s = 0x%02x %u\n", a1, aa1, aa1);
+ fprintf(stderr, "%12s = 0x%02x %u\n", a2, aa2, aa2);
+ test_die();
+}
+
+void
+assert_u16(const char *file, int line, const char *a1, const char *a2,
+ u_int16_t aa1, u_int16_t aa2, enum test_predicate pred)
+{
+ TEST_CHECK(aa1, aa2, pred);
+ test_header(file, line, a1, a2, "U16", pred);
+ fprintf(stderr, "%12s = 0x%04x %u\n", a1, aa1, aa1);
+ fprintf(stderr, "%12s = 0x%04x %u\n", a2, aa2, aa2);
+ test_die();
+}
+
+void
+assert_u32(const char *file, int line, const char *a1, const char *a2,
+ u_int32_t aa1, u_int32_t aa2, enum test_predicate pred)
+{
+ TEST_CHECK(aa1, aa2, pred);
+ test_header(file, line, a1, a2, "U32", pred);
+ fprintf(stderr, "%12s = 0x%08x %u\n", a1, aa1, aa1);
+ fprintf(stderr, "%12s = 0x%08x %u\n", a2, aa2, aa2);
+ test_die();
+}
+
+void
+assert_u64(const char *file, int line, const char *a1, const char *a2,
+ u_int64_t aa1, u_int64_t aa2, enum test_predicate pred)
+{
+ TEST_CHECK(aa1, aa2, pred);
+ test_header(file, line, a1, a2, "U64", pred);
+ fprintf(stderr, "%12s = 0x%016llx %llu\n", a1,
+ (unsigned long long)aa1, (unsigned long long)aa1);
+ fprintf(stderr, "%12s = 0x%016llx %llu\n", a2,
+ (unsigned long long)aa2, (unsigned long long)aa2);
+ test_die();
+}
+
+void
+assert_ptr(const char *file, int line, const char *a1, const char *a2,
+ const void *aa1, const void *aa2, enum test_predicate pred)
+{
+ TEST_CHECK(aa1, aa2, pred);
+ test_header(file, line, a1, a2, "PTR", pred);
+ fprintf(stderr, "%12s = %p\n", a1, aa1);
+ fprintf(stderr, "%12s = %p\n", a2, aa2);
+ test_die();
+}
+
diff --git a/regress/unittests/test_helper/test_helper.h b/regress/unittests/test_helper/test_helper.h
new file mode 100644
index 00000000..66302201
--- /dev/null
+++ b/regress/unittests/test_helper/test_helper.h
@@ -0,0 +1,326 @@
+/* $OpenBSD: test_helper.h,v 1.9 2018/10/17 23:28:05 djm Exp $ */
+/*
+ * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* Utility functions/framework for regress tests */
+
+#ifndef _TEST_HELPER_H
+#define _TEST_HELPER_H
+
+#include "includes.h"
+
+#include <sys/types.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#ifdef WITH_OPENSSL
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#endif
+
+enum test_predicate {
+ TEST_EQ, TEST_NE, TEST_LT, TEST_LE, TEST_GT, TEST_GE
+};
+typedef void (test_onerror_func_t)(void *);
+
+/* Supplied by test suite */
+void tests(void);
+
+const char *test_data_file(const char *name);
+void test_start(const char *n);
+void test_info(char *s, size_t len);
+void set_onerror_func(test_onerror_func_t *f, void *ctx);
+void test_done(void);
+int test_is_verbose(void);
+int test_is_quiet(void);
+int test_is_fast(void);
+int test_is_slow(void);
+void test_subtest_info(const char *fmt, ...)
+ __attribute__((format(printf, 1, 2)));
+void ssl_err_check(const char *file, int line);
+#ifdef WITH_OPENSSL
+void assert_bignum(const char *file, int line,
+ const char *a1, const char *a2,
+ const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred);
+#endif
+void assert_string(const char *file, int line,
+ const char *a1, const char *a2,
+ const char *aa1, const char *aa2, enum test_predicate pred);
+void assert_mem(const char *file, int line,
+ const char *a1, const char *a2,
+ const void *aa1, const void *aa2, size_t l, enum test_predicate pred);
+void assert_mem_filled(const char *file, int line,
+ const char *a1,
+ const void *aa1, u_char v, size_t l, enum test_predicate pred);
+void assert_int(const char *file, int line,
+ const char *a1, const char *a2,
+ int aa1, int aa2, enum test_predicate pred);
+void assert_size_t(const char *file, int line,
+ const char *a1, const char *a2,
+ size_t aa1, size_t aa2, enum test_predicate pred);
+void assert_u_int(const char *file, int line,
+ const char *a1, const char *a2,
+ u_int aa1, u_int aa2, enum test_predicate pred);
+void assert_long(const char *file, int line,
+ const char *a1, const char *a2,
+ long aa1, long aa2, enum test_predicate pred);
+void assert_long_long(const char *file, int line,
+ const char *a1, const char *a2,
+ long long aa1, long long aa2, enum test_predicate pred);
+void assert_char(const char *file, int line,
+ const char *a1, const char *a2,
+ char aa1, char aa2, enum test_predicate pred);
+void assert_ptr(const char *file, int line,
+ const char *a1, const char *a2,
+ const void *aa1, const void *aa2, enum test_predicate pred);
+void assert_u8(const char *file, int line,
+ const char *a1, const char *a2,
+ u_int8_t aa1, u_int8_t aa2, enum test_predicate pred);
+void assert_u16(const char *file, int line,
+ const char *a1, const char *a2,
+ u_int16_t aa1, u_int16_t aa2, enum test_predicate pred);
+void assert_u32(const char *file, int line,
+ const char *a1, const char *a2,
+ u_int32_t aa1, u_int32_t aa2, enum test_predicate pred);
+void assert_u64(const char *file, int line,
+ const char *a1, const char *a2,
+ u_int64_t aa1, u_int64_t aa2, enum test_predicate pred);
+
+#define TEST_START(n) test_start(n)
+#define TEST_DONE() test_done()
+#define TEST_ONERROR(f, c) set_onerror_func(f, c)
+#define SSL_ERR_CHECK() ssl_err_check(__FILE__, __LINE__)
+
+#define ASSERT_BIGNUM_EQ(a1, a2) \
+ assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+#define ASSERT_STRING_EQ(a1, a2) \
+ assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+#define ASSERT_MEM_EQ(a1, a2, l) \
+ assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_EQ)
+#define ASSERT_MEM_FILLED_EQ(a1, c, l) \
+ assert_mem_filled(__FILE__, __LINE__, #a1, a1, c, l, TEST_EQ)
+#define ASSERT_MEM_ZERO_EQ(a1, l) \
+ assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_EQ)
+#define ASSERT_INT_EQ(a1, a2) \
+ assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+#define ASSERT_SIZE_T_EQ(a1, a2) \
+ assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+#define ASSERT_U_INT_EQ(a1, a2) \
+ assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+#define ASSERT_LONG_EQ(a1, a2) \
+ assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+#define ASSERT_LONG_LONG_EQ(a1, a2) \
+ assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+#define ASSERT_CHAR_EQ(a1, a2) \
+ assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+#define ASSERT_PTR_EQ(a1, a2) \
+ assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+#define ASSERT_U8_EQ(a1, a2) \
+ assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+#define ASSERT_U16_EQ(a1, a2) \
+ assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+#define ASSERT_U32_EQ(a1, a2) \
+ assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+#define ASSERT_U64_EQ(a1, a2) \
+ assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
+
+#define ASSERT_BIGNUM_NE(a1, a2) \
+ assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+#define ASSERT_STRING_NE(a1, a2) \
+ assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+#define ASSERT_MEM_NE(a1, a2, l) \
+ assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_NE)
+#define ASSERT_MEM_ZERO_NE(a1, l) \
+ assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_NE)
+#define ASSERT_INT_NE(a1, a2) \
+ assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+#define ASSERT_SIZE_T_NE(a1, a2) \
+ assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+#define ASSERT_U_INT_NE(a1, a2) \
+ assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+#define ASSERT_LONG_NE(a1, a2) \
+ assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+#define ASSERT_LONG_LONG_NE(a1, a2) \
+ assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+#define ASSERT_CHAR_NE(a1, a2) \
+ assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+#define ASSERT_PTR_NE(a1, a2) \
+ assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+#define ASSERT_U8_NE(a1, a2) \
+ assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+#define ASSERT_U16_NE(a1, a2) \
+ assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+#define ASSERT_U32_NE(a1, a2) \
+ assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+#define ASSERT_U64_NE(a1, a2) \
+ assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
+
+#define ASSERT_BIGNUM_LT(a1, a2) \
+ assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+#define ASSERT_STRING_LT(a1, a2) \
+ assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+#define ASSERT_MEM_LT(a1, a2, l) \
+ assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LT)
+#define ASSERT_INT_LT(a1, a2) \
+ assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+#define ASSERT_SIZE_T_LT(a1, a2) \
+ assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+#define ASSERT_U_INT_LT(a1, a2) \
+ assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+#define ASSERT_LONG_LT(a1, a2) \
+ assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+#define ASSERT_LONG_LONG_LT(a1, a2) \
+ assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+#define ASSERT_CHAR_LT(a1, a2) \
+ assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+#define ASSERT_PTR_LT(a1, a2) \
+ assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+#define ASSERT_U8_LT(a1, a2) \
+ assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+#define ASSERT_U16_LT(a1, a2) \
+ assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+#define ASSERT_U32_LT(a1, a2) \
+ assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+#define ASSERT_U64_LT(a1, a2) \
+ assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
+
+#define ASSERT_BIGNUM_LE(a1, a2) \
+ assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+#define ASSERT_STRING_LE(a1, a2) \
+ assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+#define ASSERT_MEM_LE(a1, a2, l) \
+ assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LE)
+#define ASSERT_INT_LE(a1, a2) \
+ assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+#define ASSERT_SIZE_T_LE(a1, a2) \
+ assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+#define ASSERT_U_INT_LE(a1, a2) \
+ assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+#define ASSERT_LONG_LE(a1, a2) \
+ assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+#define ASSERT_LONG_LONG_LE(a1, a2) \
+ assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+#define ASSERT_CHAR_LE(a1, a2) \
+ assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+#define ASSERT_PTR_LE(a1, a2) \
+ assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+#define ASSERT_U8_LE(a1, a2) \
+ assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+#define ASSERT_U16_LE(a1, a2) \
+ assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+#define ASSERT_U32_LE(a1, a2) \
+ assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+#define ASSERT_U64_LE(a1, a2) \
+ assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
+
+#define ASSERT_BIGNUM_GT(a1, a2) \
+ assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+#define ASSERT_STRING_GT(a1, a2) \
+ assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+#define ASSERT_MEM_GT(a1, a2, l) \
+ assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GT)
+#define ASSERT_INT_GT(a1, a2) \
+ assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+#define ASSERT_SIZE_T_GT(a1, a2) \
+ assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+#define ASSERT_U_INT_GT(a1, a2) \
+ assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+#define ASSERT_LONG_GT(a1, a2) \
+ assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+#define ASSERT_LONG_LONG_GT(a1, a2) \
+ assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+#define ASSERT_CHAR_GT(a1, a2) \
+ assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+#define ASSERT_PTR_GT(a1, a2) \
+ assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+#define ASSERT_U8_GT(a1, a2) \
+ assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+#define ASSERT_U16_GT(a1, a2) \
+ assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+#define ASSERT_U32_GT(a1, a2) \
+ assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+#define ASSERT_U64_GT(a1, a2) \
+ assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
+
+#define ASSERT_BIGNUM_GE(a1, a2) \
+ assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+#define ASSERT_STRING_GE(a1, a2) \
+ assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+#define ASSERT_MEM_GE(a1, a2, l) \
+ assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GE)
+#define ASSERT_INT_GE(a1, a2) \
+ assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+#define ASSERT_SIZE_T_GE(a1, a2) \
+ assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+#define ASSERT_U_INT_GE(a1, a2) \
+ assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+#define ASSERT_LONG_GE(a1, a2) \
+ assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+#define ASSERT_LONG_LONG_GE(a1, a2) \
+ assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+#define ASSERT_CHAR_GE(a1, a2) \
+ assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+#define ASSERT_PTR_GE(a1, a2) \
+ assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+#define ASSERT_U8_GE(a1, a2) \
+ assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+#define ASSERT_U16_GE(a1, a2) \
+ assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+#define ASSERT_U32_GE(a1, a2) \
+ assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+#define ASSERT_U64_GE(a1, a2) \
+ assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
+
+/* Fuzzing support */
+
+struct fuzz;
+#define FUZZ_1_BIT_FLIP 0x00000001 /* Flip one bit at a time */
+#define FUZZ_2_BIT_FLIP 0x00000002 /* Flip two bits at a time */
+#define FUZZ_1_BYTE_FLIP 0x00000004 /* Flip one byte at a time */
+#define FUZZ_2_BYTE_FLIP 0x00000008 /* Flip two bytes at a time */
+#define FUZZ_TRUNCATE_START 0x00000010 /* Truncate from beginning */
+#define FUZZ_TRUNCATE_END 0x00000020 /* Truncate from end */
+#define FUZZ_BASE64 0x00000040 /* Try all base64 chars */
+#define FUZZ_MAX FUZZ_BASE64
+
+/* Start fuzzing a blob of data with selected strategies (bitmask) */
+struct fuzz *fuzz_begin(u_int strategies, const void *p, size_t l);
+
+/* Free a fuzz context */
+void fuzz_cleanup(struct fuzz *fuzz);
+
+/* Prepare the next fuzz case in the series */
+void fuzz_next(struct fuzz *fuzz);
+
+/*
+ * Check whether this fuzz case is identical to the original
+ * This is slow, but useful if the caller needs to ensure that all tests
+ * generated change the input (e.g. when fuzzing signatures).
+ */
+int fuzz_matches_original(struct fuzz *fuzz);
+
+/* Determine whether the current fuzz sequence is exhausted (nonzero = yes) */
+int fuzz_done(struct fuzz *fuzz);
+
+/* Return the length and a pointer to the current fuzzed case */
+size_t fuzz_len(struct fuzz *fuzz);
+u_char *fuzz_ptr(struct fuzz *fuzz);
+
+/* Dump the current fuzz case to stderr */
+void fuzz_dump(struct fuzz *fuzz);
+
+#endif /* _TEST_HELPER_H */
diff --git a/regress/unittests/utf8/Makefile b/regress/unittests/utf8/Makefile
new file mode 100644
index 00000000..f8eec048
--- /dev/null
+++ b/regress/unittests/utf8/Makefile
@@ -0,0 +1,14 @@
+# $OpenBSD: Makefile,v 1.5 2017/12/21 00:41:22 djm Exp $
+
+PROG=test_utf8
+SRCS=tests.c
+
+# From usr.bin/ssh
+SRCS+=utf8.c atomicio.c
+
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG}
+
+.include <bsd.regress.mk>
diff --git a/regress/unittests/utf8/tests.c b/regress/unittests/utf8/tests.c
new file mode 100644
index 00000000..8cf524dd
--- /dev/null
+++ b/regress/unittests/utf8/tests.c
@@ -0,0 +1,104 @@
+/* $OpenBSD: tests.c,v 1.4 2017/02/19 00:11:29 djm Exp $ */
+/*
+ * Regress test for the utf8.h *mprintf() API
+ *
+ * Written by Ingo Schwarze <schwarze@openbsd.org> in 2016
+ * and placed in the public domain.
+ */
+
+#include "includes.h"
+
+#include <locale.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "utf8.h"
+
+static void
+badarg(void)
+{
+ char buf[16];
+ int len, width;
+
+ width = 1;
+ TEST_START("utf8_badarg");
+ len = snmprintf(buf, sizeof(buf), &width, "\377");
+ ASSERT_INT_EQ(len, -1);
+ ASSERT_STRING_EQ(buf, "");
+ ASSERT_INT_EQ(width, 0);
+ TEST_DONE();
+}
+
+static void
+one(int utf8, const char *name, const char *mbs, int width,
+ int wantwidth, int wantlen, const char *wants)
+{
+ char buf[16];
+ int *wp;
+ int len;
+
+ if (wantlen == -2)
+ wantlen = strlen(wants);
+ (void)strlcpy(buf, utf8 ? "utf8_" : "c_", sizeof(buf));
+ (void)strlcat(buf, name, sizeof(buf));
+ TEST_START(buf);
+ wp = wantwidth == -2 ? NULL : &width;
+ len = snmprintf(buf, sizeof(buf), wp, "%s", mbs);
+ ASSERT_INT_EQ(len, wantlen);
+ ASSERT_STRING_EQ(buf, wants);
+ ASSERT_INT_EQ(width, wantwidth);
+ TEST_DONE();
+}
+
+void
+tests(void)
+{
+ char *loc;
+
+ TEST_START("utf8_setlocale");
+ loc = setlocale(LC_CTYPE, "en_US.UTF-8");
+ ASSERT_PTR_NE(loc, NULL);
+ TEST_DONE();
+
+ badarg();
+ one(1, "empty", "", 2, 0, 0, "");
+ one(1, "ascii", "x", -2, -2, -2, "x");
+ one(1, "newline", "a\nb", -2, -2, -2, "a\nb");
+ one(1, "cr", "a\rb", -2, -2, -2, "a\rb");
+ one(1, "tab", "a\tb", -2, -2, -2, "a\tb");
+ one(1, "esc", "\033x", -2, -2, -2, "\\033x");
+ one(1, "inv_badbyte", "\377x", -2, -2, -2, "\\377x");
+ one(1, "inv_nocont", "\341x", -2, -2, -2, "\\341x");
+ one(1, "inv_nolead", "a\200b", -2, -2, -2, "a\\200b");
+ one(1, "sz_ascii", "1234567890123456", -2, -2, 16, "123456789012345");
+ one(1, "sz_esc", "123456789012\033", -2, -2, 16, "123456789012");
+ one(1, "width_ascii", "123", 2, 2, -1, "12");
+ one(1, "width_double", "a\343\201\201", 2, 1, -1, "a");
+ one(1, "double_fit", "a\343\201\201", 3, 3, 4, "a\343\201\201");
+ one(1, "double_spc", "a\343\201\201", 4, 3, 4, "a\343\201\201");
+
+ TEST_START("C_setlocale");
+ loc = setlocale(LC_CTYPE, "C");
+ ASSERT_PTR_NE(loc, NULL);
+ TEST_DONE();
+
+ badarg();
+ one(0, "empty", "", 2, 0, 0, "");
+ one(0, "ascii", "x", -2, -2, -2, "x");
+ one(0, "newline", "a\nb", -2, -2, -2, "a\nb");
+ one(0, "cr", "a\rb", -2, -2, -2, "a\rb");
+ one(0, "tab", "a\tb", -2, -2, -2, "a\tb");
+ one(0, "esc", "\033x", -2, -2, -2, "\\033x");
+ one(0, "inv_badbyte", "\377x", -2, -2, -2, "\\377x");
+ one(0, "inv_nocont", "\341x", -2, -2, -2, "\\341x");
+ one(0, "inv_nolead", "a\200b", -2, -2, -2, "a\\200b");
+ one(0, "sz_ascii", "1234567890123456", -2, -2, 16, "123456789012345");
+ one(0, "sz_esc", "123456789012\033", -2, -2, 16, "123456789012");
+ one(0, "width_ascii", "123", 2, 2, -1, "12");
+ one(0, "width_double", "a\343\201\201", 2, 1, -1, "a");
+ one(0, "double_fit", "a\343\201\201", 7, 5, -1, "a\\343");
+ one(0, "double_spc", "a\343\201\201", 13, 13, 13, "a\\343\\201\\201");
+}
diff --git a/regress/valgrind-unit.sh b/regress/valgrind-unit.sh
new file mode 100755
index 00000000..4143ead4
--- /dev/null
+++ b/regress/valgrind-unit.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+UNIT_BINARY="$1"
+shift
+UNIT_ARGS="$@"
+
+test "x$OBJ" = "x" && OBJ=$PWD
+
+# This mostly replicates the logic in test-exec.sh for running the
+# regress tests under valgrind, except that we unconditionally enable
+# leak checking because the unit tests should be clean.
+VG_LEAK="--leak-check=full"
+VG_TEST=`basename $UNIT_BINARY`
+VG_LOG="$OBJ/valgrind-out/${VG_TEST}.%p"
+VG_OPTS="--track-origins=yes $VG_LEAK --log-file=${VG_LOG}"
+VG_OPTS="$VG_OPTS --trace-children=yes"
+VG_PATH="valgrind"
+if [ "x$VALGRIND_PATH" != "x" ]; then
+ VG_PATH="$VALGRIND_PATH"
+fi
+
+exec $VG_PATH $VG_OPTS $UNIT_BINARY $UNIT_ARGS
diff --git a/regress/yes-head.sh b/regress/yes-head.sh
new file mode 100644
index 00000000..2759eb8c
--- /dev/null
+++ b/regress/yes-head.sh
@@ -0,0 +1,13 @@
+# $OpenBSD: yes-head.sh,v 1.6 2017/04/30 23:34:55 djm Exp $
+# Placed in the Public Domain.
+
+tid="yes pipe head"
+
+lines=`${SSH} -F $OBJ/ssh_proxy thishost 'sh -c "while true;do echo yes;done | _POSIX2_VERSION=199209 head -2000"' | (sleep 3 ; wc -l)`
+if [ $? -ne 0 ]; then
+ fail "yes|head test failed"
+ lines = 0;
+fi
+if [ $lines -ne 2000 ]; then
+ fail "yes|head returns $lines lines instead of 2000"
+fi
diff --git a/rijndael.c b/rijndael.c
index b352a11e..40ab7b1f 100644
--- a/rijndael.c
+++ b/rijndael.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rijndael.c,v 1.19 2014/11/18 22:38:48 mikeb Exp $ */
+/* $OpenBSD: rijndael.c,v 1.20 2015/03/16 11:09:52 djm Exp $ */
/**
* rijndael-alg-fst.c
diff --git a/roaming.h b/roaming.h
deleted file mode 100644
index da069f87..00000000
--- a/roaming.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* $OpenBSD: roaming.h,v 1.6 2011/12/07 05:44:38 djm Exp $ */
-/*
- * Copyright (c) 2004-2009 AppGate Network Security AB
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef ROAMING_H
-#define ROAMING_H
-
-#define DEFAULT_ROAMBUF 65536
-#define MAX_ROAMBUF (2*1024*1024) /* XXX arbitrary */
-#define ROAMING_REQUEST "roaming@appgate.com"
-
-extern int roaming_enabled;
-extern int resume_in_progress;
-
-void request_roaming(void);
-int get_snd_buf_size(void);
-int get_recv_buf_size(void);
-void add_recv_bytes(u_int64_t);
-int wait_for_roaming_reconnect(void);
-void roaming_reply(int, u_int32_t, void *);
-void set_out_buffer_size(size_t);
-ssize_t roaming_write(int, const void *, size_t, int *);
-ssize_t roaming_read(int, void *, size_t, int *);
-size_t roaming_atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
-u_int64_t get_recv_bytes(void);
-u_int64_t get_sent_bytes(void);
-void roam_set_bytes(u_int64_t, u_int64_t);
-void resend_bytes(int, u_int64_t *);
-void calculate_new_key(u_int64_t *, u_int64_t, u_int64_t);
-int resume_kex(void);
-
-#endif /* ROAMING */
diff --git a/roaming_client.c b/roaming_client.c
deleted file mode 100644
index cb132857..00000000
--- a/roaming_client.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/* $OpenBSD: roaming_client.c,v 1.9 2015/01/27 12:54:06 okan Exp $ */
-/*
- * Copyright (c) 2004-2009 AppGate Network Security AB
- *
- * 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 "openbsd-compat/sys-queue.h"
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <signal.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "xmalloc.h"
-#include "buffer.h"
-#include "channels.h"
-#include "cipher.h"
-#include "dispatch.h"
-#include "clientloop.h"
-#include "log.h"
-#include "match.h"
-#include "misc.h"
-#include "packet.h"
-#include "ssh.h"
-#include "key.h"
-#include "kex.h"
-#include "readconf.h"
-#include "roaming.h"
-#include "ssh2.h"
-#include "sshconnect.h"
-#include "digest.h"
-
-/* import */
-extern Options options;
-extern char *host;
-extern struct sockaddr_storage hostaddr;
-extern int session_resumed;
-
-static u_int32_t roaming_id;
-static u_int64_t cookie;
-static u_int64_t lastseenchall;
-static u_int64_t key1, key2, oldkey1, oldkey2;
-
-void
-roaming_reply(int type, u_int32_t seq, void *ctxt)
-{
- if (type == SSH2_MSG_REQUEST_FAILURE) {
- logit("Server denied roaming");
- return;
- }
- verbose("Roaming enabled");
- roaming_id = packet_get_int();
- cookie = packet_get_int64();
- key1 = oldkey1 = packet_get_int64();
- key2 = oldkey2 = packet_get_int64();
- set_out_buffer_size(packet_get_int() + get_snd_buf_size());
- roaming_enabled = 1;
-}
-
-void
-request_roaming(void)
-{
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring(ROAMING_REQUEST);
- packet_put_char(1);
- packet_put_int(get_recv_buf_size());
- packet_send();
- client_register_global_confirm(roaming_reply, NULL);
-}
-
-static void
-roaming_auth_required(void)
-{
- u_char digest[SSH_DIGEST_MAX_LENGTH];
- Buffer b;
- u_int64_t chall, oldchall;
-
- chall = packet_get_int64();
- oldchall = packet_get_int64();
- if (oldchall != lastseenchall) {
- key1 = oldkey1;
- key2 = oldkey2;
- }
- lastseenchall = chall;
-
- buffer_init(&b);
- buffer_put_int64(&b, cookie);
- buffer_put_int64(&b, chall);
- if (ssh_digest_buffer(SSH_DIGEST_SHA1, &b, digest, sizeof(digest)) != 0)
- fatal("%s: ssh_digest_buffer failed", __func__);
- buffer_free(&b);
-
- packet_start(SSH2_MSG_KEX_ROAMING_AUTH);
- packet_put_int64(key1 ^ get_recv_bytes());
- packet_put_raw(digest, ssh_digest_bytes(SSH_DIGEST_SHA1));
- packet_send();
-
- oldkey1 = key1;
- oldkey2 = key2;
- calculate_new_key(&key1, cookie, chall);
- calculate_new_key(&key2, cookie, chall);
-
- debug("Received %llu bytes", (unsigned long long)get_recv_bytes());
- debug("Sent roaming_auth packet");
-}
-
-int
-resume_kex(void)
-{
- /*
- * This should not happen - if the client sends the kex method
- * resume@appgate.com then the kex is done in roaming_resume().
- */
- return 1;
-}
-
-static int
-roaming_resume(void)
-{
- u_int64_t recv_bytes;
- char *str = NULL, *kexlist = NULL, *c;
- int i, type;
- int timeout_ms = options.connection_timeout * 1000;
- u_int len;
- u_int32_t rnd = 0;
-
- resume_in_progress = 1;
-
- /* Exchange banners */
- ssh_exchange_identification(timeout_ms);
- packet_set_nonblocking();
-
- /* Send a kexinit message with resume@appgate.com as only kex algo */
- packet_start(SSH2_MSG_KEXINIT);
- for (i = 0; i < KEX_COOKIE_LEN; i++) {
- if (i % 4 == 0)
- rnd = arc4random();
- packet_put_char(rnd & 0xff);
- rnd >>= 8;
- }
- packet_put_cstring(KEX_RESUME);
- for (i = 1; i < PROPOSAL_MAX; i++) {
- /* kex algorithm added so start with i=1 and not 0 */
- packet_put_cstring(""); /* Not used when we resume */
- }
- packet_put_char(1); /* first kex_packet follows */
- packet_put_int(0); /* reserved */
- packet_send();
-
- /* Assume that resume@appgate.com will be accepted */
- packet_start(SSH2_MSG_KEX_ROAMING_RESUME);
- packet_put_int(roaming_id);
- packet_send();
-
- /* Read the server's kexinit and check for resume@appgate.com */
- if ((type = packet_read()) != SSH2_MSG_KEXINIT) {
- debug("expected kexinit on resume, got %d", type);
- goto fail;
- }
- for (i = 0; i < KEX_COOKIE_LEN; i++)
- (void)packet_get_char();
- kexlist = packet_get_string(&len);
- if (!kexlist
- || (str = match_list(KEX_RESUME, kexlist, NULL)) == NULL) {
- debug("server doesn't allow resume");
- goto fail;
- }
- free(str);
- for (i = 1; i < PROPOSAL_MAX; i++) {
- /* kex algorithm taken care of so start with i=1 and not 0 */
- free(packet_get_string(&len));
- }
- i = packet_get_char(); /* first_kex_packet_follows */
- if (i && (c = strchr(kexlist, ',')))
- *c = 0;
- if (i && strcmp(kexlist, KEX_RESUME)) {
- debug("server's kex guess (%s) was wrong, skipping", kexlist);
- (void)packet_read(); /* Wrong guess - discard packet */
- }
-
- /*
- * Read the ROAMING_AUTH_REQUIRED challenge from the server and
- * send ROAMING_AUTH
- */
- if ((type = packet_read()) != SSH2_MSG_KEX_ROAMING_AUTH_REQUIRED) {
- debug("expected roaming_auth_required, got %d", type);
- goto fail;
- }
- roaming_auth_required();
-
- /* Read ROAMING_AUTH_OK from the server */
- if ((type = packet_read()) != SSH2_MSG_KEX_ROAMING_AUTH_OK) {
- debug("expected roaming_auth_ok, got %d", type);
- goto fail;
- }
- recv_bytes = packet_get_int64() ^ oldkey2;
- debug("Peer received %llu bytes", (unsigned long long)recv_bytes);
- resend_bytes(packet_get_connection_out(), &recv_bytes);
-
- resume_in_progress = 0;
-
- session_resumed = 1; /* Tell clientloop */
-
- return 0;
-
-fail:
- free(kexlist);
- if (packet_get_connection_in() == packet_get_connection_out())
- close(packet_get_connection_in());
- else {
- close(packet_get_connection_in());
- close(packet_get_connection_out());
- }
- return 1;
-}
-
-int
-wait_for_roaming_reconnect(void)
-{
- static int reenter_guard = 0;
- int timeout_ms = options.connection_timeout * 1000;
- int c;
-
- if (reenter_guard != 0)
- fatal("Server refused resume, roaming timeout may be exceeded");
- reenter_guard = 1;
-
- fprintf(stderr, "[connection suspended, press return to resume]");
- fflush(stderr);
- packet_backup_state();
- /* TODO Perhaps we should read from tty here */
- while ((c = fgetc(stdin)) != EOF) {
- if (c == 'Z' - 64) {
- kill(getpid(), SIGTSTP);
- continue;
- }
- if (c != '\n' && c != '\r')
- continue;
-
- if (ssh_connect(host, NULL, &hostaddr, options.port,
- options.address_family, 1, &timeout_ms,
- options.tcp_keep_alive, options.use_privileged_port) == 0 &&
- roaming_resume() == 0) {
- packet_restore_state();
- reenter_guard = 0;
- fprintf(stderr, "[connection resumed]\n");
- fflush(stderr);
- return 0;
- }
-
- fprintf(stderr, "[reconnect failed, press return to retry]");
- fflush(stderr);
- }
- fprintf(stderr, "[exiting]\n");
- fflush(stderr);
- exit(0);
-}
diff --git a/roaming_common.c b/roaming_common.c
deleted file mode 100644
index ea064605..00000000
--- a/roaming_common.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/* $OpenBSD: roaming_common.c,v 1.13 2015/01/27 12:54:06 okan Exp $ */
-/*
- * Copyright (c) 2004-2009 AppGate Network Security AB
- *
- * 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 <sys/uio.h>
-
-#include <errno.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "atomicio.h"
-#include "log.h"
-#include "packet.h"
-#include "xmalloc.h"
-#include "cipher.h"
-#include "buffer.h"
-#include "roaming.h"
-#include "digest.h"
-
-static size_t out_buf_size = 0;
-static char *out_buf = NULL;
-static size_t out_start;
-static size_t out_last;
-
-static u_int64_t write_bytes = 0;
-static u_int64_t read_bytes = 0;
-
-int roaming_enabled = 0;
-int resume_in_progress = 0;
-
-int
-get_snd_buf_size(void)
-{
- int fd = packet_get_connection_out();
- int optval;
- socklen_t optvallen = sizeof(optval);
-
- if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optvallen) != 0)
- optval = DEFAULT_ROAMBUF;
- return optval;
-}
-
-int
-get_recv_buf_size(void)
-{
- int fd = packet_get_connection_in();
- int optval;
- socklen_t optvallen = sizeof(optval);
-
- if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &optval, &optvallen) != 0)
- optval = DEFAULT_ROAMBUF;
- return optval;
-}
-
-void
-set_out_buffer_size(size_t size)
-{
- if (size == 0 || size > MAX_ROAMBUF)
- fatal("%s: bad buffer size %lu", __func__, (u_long)size);
- /*
- * The buffer size can only be set once and the buffer will live
- * as long as the session lives.
- */
- if (out_buf == NULL) {
- out_buf_size = size;
- out_buf = xmalloc(size);
- out_start = 0;
- out_last = 0;
- }
-}
-
-u_int64_t
-get_recv_bytes(void)
-{
- return read_bytes;
-}
-
-void
-add_recv_bytes(u_int64_t num)
-{
- read_bytes += num;
-}
-
-u_int64_t
-get_sent_bytes(void)
-{
- return write_bytes;
-}
-
-void
-roam_set_bytes(u_int64_t sent, u_int64_t recvd)
-{
- read_bytes = recvd;
- write_bytes = sent;
-}
-
-static void
-buf_append(const char *buf, size_t count)
-{
- if (count > out_buf_size) {
- buf += count - out_buf_size;
- count = out_buf_size;
- }
- if (count < out_buf_size - out_last) {
- memcpy(out_buf + out_last, buf, count);
- if (out_start > out_last)
- out_start += count;
- out_last += count;
- } else {
- /* data will wrap */
- size_t chunk = out_buf_size - out_last;
- memcpy(out_buf + out_last, buf, chunk);
- memcpy(out_buf, buf + chunk, count - chunk);
- out_last = count - chunk;
- out_start = out_last + 1;
- }
-}
-
-ssize_t
-roaming_write(int fd, const void *buf, size_t count, int *cont)
-{
- ssize_t ret;
-
- ret = write(fd, buf, count);
- if (ret > 0 && !resume_in_progress) {
- write_bytes += ret;
- if (out_buf_size > 0)
- buf_append(buf, ret);
- }
- if (out_buf_size > 0 &&
- (ret == 0 || (ret == -1 && errno == EPIPE))) {
- if (wait_for_roaming_reconnect() != 0) {
- ret = 0;
- *cont = 1;
- } else {
- ret = -1;
- errno = EAGAIN;
- }
- }
- return ret;
-}
-
-ssize_t
-roaming_read(int fd, void *buf, size_t count, int *cont)
-{
- ssize_t ret = read(fd, buf, count);
- if (ret > 0) {
- if (!resume_in_progress) {
- read_bytes += ret;
- }
- } else if (out_buf_size > 0 &&
- (ret == 0 || (ret == -1 && (errno == ECONNRESET
- || errno == ECONNABORTED || errno == ETIMEDOUT
- || errno == EHOSTUNREACH)))) {
- debug("roaming_read failed for %d ret=%ld errno=%d",
- fd, (long)ret, errno);
- ret = 0;
- if (wait_for_roaming_reconnect() == 0)
- *cont = 1;
- }
- return ret;
-}
-
-size_t
-roaming_atomicio(ssize_t(*f)(int, void*, size_t), int fd, void *buf,
- size_t count)
-{
- size_t ret = atomicio(f, fd, buf, count);
-
- if (f == vwrite && ret > 0 && !resume_in_progress) {
- write_bytes += ret;
- } else if (f == read && ret > 0 && !resume_in_progress) {
- read_bytes += ret;
- }
- return ret;
-}
-
-void
-resend_bytes(int fd, u_int64_t *offset)
-{
- size_t available, needed;
-
- if (out_start < out_last)
- available = out_last - out_start;
- else
- available = out_buf_size;
- needed = write_bytes - *offset;
- debug3("resend_bytes: resend %lu bytes from %llu",
- (unsigned long)needed, (unsigned long long)*offset);
- if (needed > available)
- fatal("Needed to resend more data than in the cache");
- if (out_last < needed) {
- int chunkend = needed - out_last;
- atomicio(vwrite, fd, out_buf + out_buf_size - chunkend,
- chunkend);
- atomicio(vwrite, fd, out_buf, out_last);
- } else {
- atomicio(vwrite, fd, out_buf + (out_last - needed), needed);
- }
-}
-
-/*
- * Caclulate a new key after a reconnect
- */
-void
-calculate_new_key(u_int64_t *key, u_int64_t cookie, u_int64_t challenge)
-{
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- Buffer b;
-
- buffer_init(&b);
- buffer_put_int64(&b, *key);
- buffer_put_int64(&b, cookie);
- buffer_put_int64(&b, challenge);
-
- if (ssh_digest_buffer(SSH_DIGEST_SHA1, &b, hash, sizeof(hash)) != 0)
- fatal("%s: digest_buffer failed", __func__);
-
- buffer_clear(&b);
- buffer_append(&b, hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
- *key = buffer_get_int64(&b);
- buffer_free(&b);
-}
diff --git a/rsa.c b/rsa.c
deleted file mode 100644
index 5ecacef9..00000000
--- a/rsa.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/* $OpenBSD: rsa.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- *
- * Copyright (c) 1999 Niels Provos. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Description of the RSA algorithm can be found e.g. from the following
- * sources:
- *
- * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994.
- *
- * Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to
- * Computer Security. Prentice-Hall, 1989.
- *
- * Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill,
- * 1994.
- *
- * R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications
- * System and Method. US Patent 4,405,829, 1983.
- *
- * Hans Riesel: Prime Numbers and Computer Methods for Factorization.
- * Birkhauser, 1994.
- *
- * The RSA Frequently Asked Questions document by RSA Data Security,
- * Inc., 1995.
- *
- * RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as
- * included below:
- *
- * [gone - had to be deleted - what a pity]
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-
-#include <stdarg.h>
-#include <string.h>
-
-#include "rsa.h"
-#include "log.h"
-#include "ssherr.h"
-
-int
-rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
-{
- u_char *inbuf = NULL, *outbuf = NULL;
- int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR;
-
- if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
- return SSH_ERR_INVALID_ARGUMENT;
-
- olen = BN_num_bytes(key->n);
- if ((outbuf = malloc(olen)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
-
- ilen = BN_num_bytes(in);
- if ((inbuf = malloc(ilen)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- BN_bn2bin(in, inbuf);
-
- if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key,
- RSA_PKCS1_PADDING)) <= 0) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
-
- if (BN_bin2bn(outbuf, len, out) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- r = 0;
-
- out:
- if (outbuf != NULL) {
- explicit_bzero(outbuf, olen);
- free(outbuf);
- }
- if (inbuf != NULL) {
- explicit_bzero(inbuf, ilen);
- free(inbuf);
- }
- return r;
-}
-
-int
-rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
-{
- u_char *inbuf = NULL, *outbuf = NULL;
- int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR;
-
- olen = BN_num_bytes(key->n);
- if ((outbuf = malloc(olen)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
-
- ilen = BN_num_bytes(in);
- if ((inbuf = malloc(ilen)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- BN_bn2bin(in, inbuf);
-
- if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
- RSA_PKCS1_PADDING)) <= 0) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- } else if (BN_bin2bn(outbuf, len, out) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- r = 0;
- out:
- if (outbuf != NULL) {
- explicit_bzero(outbuf, olen);
- free(outbuf);
- }
- if (inbuf != NULL) {
- explicit_bzero(inbuf, ilen);
- free(inbuf);
- }
- return r;
-}
-
-/* calculate p-1 and q-1 */
-int
-rsa_generate_additional_parameters(RSA *rsa)
-{
- BIGNUM *aux = NULL;
- BN_CTX *ctx = NULL;
- int r;
-
- if ((ctx = BN_CTX_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((aux = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
-
- if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) ||
- (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) ||
- (BN_sub(aux, rsa->p, BN_value_one()) == 0) ||
- (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- r = 0;
- out:
- BN_clear_free(aux);
- BN_CTX_free(ctx);
- return r;
-}
-
diff --git a/rsa.h b/rsa.h
deleted file mode 100644
index c476707d..00000000
--- a/rsa.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* $OpenBSD: rsa.h,v 1.17 2014/06/24 01:13:21 djm Exp $ */
-
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * RSA key generation, encryption and decryption.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-
-#ifndef RSA_H
-#define RSA_H
-
-#include <openssl/bn.h>
-#include <openssl/rsa.h>
-
-int rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *);
-int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *);
-int rsa_generate_additional_parameters(RSA *);
-
-#endif /* RSA_H */
diff --git a/sandbox-capsicum.c b/sandbox-capsicum.c
index 655f0d21..e10bad7e 100644
--- a/sandbox-capsicum.c
+++ b/sandbox-capsicum.c
@@ -22,7 +22,7 @@
#include <sys/param.h>
#include <sys/time.h>
#include <sys/resource.h>
-#include <sys/capability.h>
+#include <sys/capsicum.h>
#include <errno.h>
#include <stdarg.h>
diff --git a/sandbox-darwin.c b/sandbox-darwin.c
index 35f0c4d1..59b4d286 100644
--- a/sandbox-darwin.c
+++ b/sandbox-darwin.c
@@ -30,7 +30,8 @@
#include <unistd.h>
#include "log.h"
-#include "sandbox.h"
+#include "ssh-sandbox.h"
+#include "monitor.h"
#include "xmalloc.h"
/* Darwin/OS X sandbox */
diff --git a/sandbox-pledge.c b/sandbox-pledge.c
new file mode 100644
index 00000000..d28fc272
--- /dev/null
+++ b/sandbox-pledge.c
@@ -0,0 +1,77 @@
+/* $OpenBSD: sandbox-pledge.c,v 1.1 2015/10/09 01:37:08 deraadt Exp $ */
+/*
+ * Copyright (c) 2015 Theo de Raadt <deraadt@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#ifdef SANDBOX_PLEDGE
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/syscall.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include "log.h"
+#include "ssh-sandbox.h"
+#include "xmalloc.h"
+
+struct ssh_sandbox {
+ pid_t child_pid;
+};
+
+struct ssh_sandbox *
+ssh_sandbox_init(struct monitor *m)
+{
+ struct ssh_sandbox *box;
+
+ debug3("%s: preparing pledge sandbox", __func__);
+ box = xcalloc(1, sizeof(*box));
+ box->child_pid = 0;
+
+ return box;
+}
+
+void
+ssh_sandbox_child(struct ssh_sandbox *box)
+{
+ if (pledge("stdio", NULL) == -1)
+ fatal("%s: pledge()", __func__);
+}
+
+void
+ssh_sandbox_parent_finish(struct ssh_sandbox *box)
+{
+ free(box);
+ debug3("%s: finished", __func__);
+}
+
+void
+ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid)
+{
+ box->child_pid = child_pid;
+ /* Nothing to do here */
+}
+
+#endif /* SANDBOX_PLEDGE */
diff --git a/sandbox-rlimit.c b/sandbox-rlimit.c
index bba80778..0bff3dfb 100644
--- a/sandbox-rlimit.c
+++ b/sandbox-rlimit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sandbox-rlimit.c,v 1.3 2011/06/23 09:34:13 djm Exp $ */
+/* $OpenBSD: sandbox-rlimit.c,v 1.4 2016/09/12 01:22:38 deraadt Exp $ */
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
@@ -20,7 +20,6 @@
#ifdef SANDBOX_RLIMIT
#include <sys/types.h>
-#include <sys/param.h>
#include <sys/time.h>
#include <sys/resource.h>
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c
index b6f6258f..e0768c06 100644
--- a/sandbox-seccomp-filter.c
+++ b/sandbox-seccomp-filter.c
@@ -42,13 +42,19 @@
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/prctl.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <linux/net.h>
#include <linux/audit.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <elf.h>
#include <asm/unistd.h>
+#ifdef __s390__
+#include <asm/zcrypt.h>
+#endif
#include <errno.h>
#include <signal.h>
@@ -72,13 +78,57 @@
# define SECCOMP_FILTER_FAIL SECCOMP_RET_TRAP
#endif /* SANDBOX_SECCOMP_FILTER_DEBUG */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define ARG_LO_OFFSET 0
+# define ARG_HI_OFFSET sizeof(uint32_t)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+# define ARG_LO_OFFSET sizeof(uint32_t)
+# define ARG_HI_OFFSET 0
+#else
+#error "Unknown endianness"
+#endif
+
/* Simple helpers to avoid manual errors (but larger BPF programs). */
#define SC_DENY(_nr, _errno) \
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 1), \
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO|(_errno))
#define SC_ALLOW(_nr) \
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 1), \
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
+#define SC_ALLOW_ARG(_nr, _arg_nr, _arg_val) \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 6), \
+ /* load and test syscall argument, low word */ \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
+ offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_LO_OFFSET), \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \
+ ((_arg_val) & 0xFFFFFFFF), 0, 3), \
+ /* load and test syscall argument, high word */ \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
+ offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_HI_OFFSET), \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \
+ (((uint32_t)((uint64_t)(_arg_val) >> 32)) & 0xFFFFFFFF), 0, 1), \
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), \
+ /* reload syscall number; all rules expect it in accumulator */ \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
+ offsetof(struct seccomp_data, nr))
+/* Allow if syscall argument contains only values in mask */
+#define SC_ALLOW_ARG_MASK(_nr, _arg_nr, _arg_mask) \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 8), \
+ /* load, mask and test syscall argument, low word */ \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
+ offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_LO_OFFSET), \
+ BPF_STMT(BPF_ALU+BPF_AND+BPF_K, ~((_arg_mask) & 0xFFFFFFFF)), \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 4), \
+ /* load, mask and test syscall argument, high word */ \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
+ offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_HI_OFFSET), \
+ BPF_STMT(BPF_ALU+BPF_AND+BPF_K, \
+ ~(((uint32_t)((uint64_t)(_arg_mask) >> 32)) & 0xFFFFFFFF)), \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 1), \
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), \
+ /* reload syscall number; all rules expect it in accumulator */ \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
+ offsetof(struct seccomp_data, nr))
/* Syscall filtering set for preauth. */
static const struct sock_filter preauth_insns[] = {
@@ -90,45 +140,177 @@ static const struct sock_filter preauth_insns[] = {
/* Load the syscall number for checking. */
BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
offsetof(struct seccomp_data, nr)),
- SC_DENY(open, EACCES),
- SC_DENY(stat, EACCES),
- SC_ALLOW(getpid),
- SC_ALLOW(gettimeofday),
- SC_ALLOW(clock_gettime),
-#ifdef __NR_time /* not defined on EABI ARM */
- SC_ALLOW(time),
-#endif
- SC_ALLOW(read),
- SC_ALLOW(write),
- SC_ALLOW(close),
-#ifdef __NR_shutdown /* not defined on archs that go via socketcall(2) */
- SC_ALLOW(shutdown),
-#endif
- SC_ALLOW(brk),
- SC_ALLOW(poll),
-#ifdef __NR__newselect
- SC_ALLOW(_newselect),
-#else
- SC_ALLOW(select),
+
+ /* Syscalls to non-fatally deny */
+#ifdef __NR_lstat
+ SC_DENY(__NR_lstat, EACCES),
+#endif
+#ifdef __NR_lstat64
+ SC_DENY(__NR_lstat64, EACCES),
+#endif
+#ifdef __NR_fstat
+ SC_DENY(__NR_fstat, EACCES),
+#endif
+#ifdef __NR_fstat64
+ SC_DENY(__NR_fstat64, EACCES),
+#endif
+#ifdef __NR_open
+ SC_DENY(__NR_open, EACCES),
+#endif
+#ifdef __NR_openat
+ SC_DENY(__NR_openat, EACCES),
+#endif
+#ifdef __NR_newfstatat
+ SC_DENY(__NR_newfstatat, EACCES),
+#endif
+#ifdef __NR_stat
+ SC_DENY(__NR_stat, EACCES),
+#endif
+#ifdef __NR_stat64
+ SC_DENY(__NR_stat64, EACCES),
+#endif
+#ifdef __NR_shmget
+ SC_DENY(__NR_shmget, EACCES),
+#endif
+#ifdef __NR_shmat
+ SC_DENY(__NR_shmat, EACCES),
+#endif
+#ifdef __NR_shmdt
+ SC_DENY(__NR_shmdt, EACCES),
+#endif
+#ifdef __NR_ipc
+ SC_DENY(__NR_ipc, EACCES),
+#endif
+
+ /* Syscalls to permit */
+#ifdef __NR_brk
+ SC_ALLOW(__NR_brk),
+#endif
+#ifdef __NR_clock_gettime
+ SC_ALLOW(__NR_clock_gettime),
+#endif
+#ifdef __NR_clock_gettime64
+ SC_ALLOW(__NR_clock_gettime64),
+#endif
+#ifdef __NR_close
+ SC_ALLOW(__NR_close),
+#endif
+#ifdef __NR_exit
+ SC_ALLOW(__NR_exit),
+#endif
+#ifdef __NR_exit_group
+ SC_ALLOW(__NR_exit_group),
+#endif
+#ifdef __NR_futex
+ SC_ALLOW(__NR_futex),
+#endif
+#ifdef __NR_geteuid
+ SC_ALLOW(__NR_geteuid),
+#endif
+#ifdef __NR_geteuid32
+ SC_ALLOW(__NR_geteuid32),
+#endif
+#ifdef __NR_getpgid
+ SC_ALLOW(__NR_getpgid),
#endif
- SC_ALLOW(madvise),
-#ifdef __NR_mmap2 /* EABI ARM only has mmap2() */
- SC_ALLOW(mmap2),
+#ifdef __NR_getpid
+ SC_ALLOW(__NR_getpid),
+#endif
+#ifdef __NR_getrandom
+ SC_ALLOW(__NR_getrandom),
+#endif
+#ifdef __NR_gettimeofday
+ SC_ALLOW(__NR_gettimeofday),
+#endif
+#ifdef __NR_getuid
+ SC_ALLOW(__NR_getuid),
+#endif
+#ifdef __NR_getuid32
+ SC_ALLOW(__NR_getuid32),
+#endif
+#ifdef __NR_madvise
+ SC_ALLOW(__NR_madvise),
#endif
#ifdef __NR_mmap
- SC_ALLOW(mmap),
+ SC_ALLOW_ARG_MASK(__NR_mmap, 2, PROT_READ|PROT_WRITE|PROT_NONE),
+#endif
+#ifdef __NR_mmap2
+ SC_ALLOW_ARG_MASK(__NR_mmap2, 2, PROT_READ|PROT_WRITE|PROT_NONE),
+#endif
+#ifdef __NR_mprotect
+ SC_ALLOW_ARG_MASK(__NR_mprotect, 2, PROT_READ|PROT_WRITE|PROT_NONE),
+#endif
+#ifdef __NR_mremap
+ SC_ALLOW(__NR_mremap),
+#endif
+#ifdef __NR_munmap
+ SC_ALLOW(__NR_munmap),
+#endif
+#ifdef __NR_nanosleep
+ SC_ALLOW(__NR_nanosleep),
+#endif
+#ifdef __NR_clock_nanosleep
+ SC_ALLOW(__NR_clock_nanosleep),
+#endif
+#ifdef __NR_clock_nanosleep_time64
+ SC_ALLOW(__NR_clock_nanosleep_time64),
+#endif
+#ifdef __NR_clock_gettime64
+ SC_ALLOW(__NR_clock_gettime64),
+#endif
+#ifdef __NR__newselect
+ SC_ALLOW(__NR__newselect),
#endif
-#ifdef __dietlibc__
- SC_ALLOW(mremap),
- SC_ALLOW(exit),
+#ifdef __NR_poll
+ SC_ALLOW(__NR_poll),
+#endif
+#ifdef __NR_pselect6
+ SC_ALLOW(__NR_pselect6),
+#endif
+#ifdef __NR_read
+ SC_ALLOW(__NR_read),
#endif
- SC_ALLOW(munmap),
- SC_ALLOW(exit_group),
#ifdef __NR_rt_sigprocmask
- SC_ALLOW(rt_sigprocmask),
-#else
- SC_ALLOW(sigprocmask),
+ SC_ALLOW(__NR_rt_sigprocmask),
+#endif
+#ifdef __NR_select
+ SC_ALLOW(__NR_select),
+#endif
+#ifdef __NR_shutdown
+ SC_ALLOW(__NR_shutdown),
+#endif
+#ifdef __NR_sigprocmask
+ SC_ALLOW(__NR_sigprocmask),
+#endif
+#ifdef __NR_time
+ SC_ALLOW(__NR_time),
#endif
+#ifdef __NR_write
+ SC_ALLOW(__NR_write),
+#endif
+#ifdef __NR_socketcall
+ SC_ALLOW_ARG(__NR_socketcall, 0, SYS_SHUTDOWN),
+ SC_DENY(__NR_socketcall, EACCES),
+#endif
+#if defined(__NR_ioctl) && defined(__s390__)
+ /* Allow ioctls for ICA crypto card on s390 */
+ SC_ALLOW_ARG(__NR_ioctl, 1, Z90STAT_STATUS_MASK),
+ SC_ALLOW_ARG(__NR_ioctl, 1, ICARSAMODEXPO),
+ SC_ALLOW_ARG(__NR_ioctl, 1, ICARSACRT),
+ SC_ALLOW_ARG(__NR_ioctl, 1, ZSECSENDCPRB),
+ /* Allow ioctls for EP11 crypto card on s390 */
+ SC_ALLOW_ARG(__NR_ioctl, 1, ZSENDEP11CPRB),
+#endif
+#if defined(__x86_64__) && defined(__ILP32__) && defined(__X32_SYSCALL_BIT)
+ /*
+ * On Linux x32, the clock_gettime VDSO falls back to the
+ * x86-64 syscall under some circumstances, e.g.
+ * https://bugs.debian.org/849923
+ */
+ SC_ALLOW(__NR_clock_gettime & ~__X32_SYSCALL_BIT),
+#endif
+
+ /* Default deny */
BPF_STMT(BPF_RET+BPF_K, SECCOMP_FILTER_FAIL),
};
diff --git a/sandbox-solaris.c b/sandbox-solaris.c
new file mode 100644
index 00000000..56ddb9a9
--- /dev/null
+++ b/sandbox-solaris.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015 Joyent, Inc
+ * Author: Alex Wilson <alex.wilson@joyent.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#ifdef SANDBOX_SOLARIS
+#ifndef USE_SOLARIS_PRIVS
+# error "--with-solaris-privs must be used with the Solaris sandbox"
+#endif
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_PRIV_H
+# include <priv.h>
+#endif
+
+#include "log.h"
+#include "ssh-sandbox.h"
+#include "xmalloc.h"
+
+struct ssh_sandbox {
+ priv_set_t *pset;
+};
+
+struct ssh_sandbox *
+ssh_sandbox_init(struct monitor *monitor)
+{
+ struct ssh_sandbox *box = NULL;
+
+ box = xcalloc(1, sizeof(*box));
+
+ /* Start with "basic" and drop everything we don't need. */
+ box->pset = solaris_basic_privset();
+
+ if (box->pset == NULL) {
+ free(box);
+ return NULL;
+ }
+
+ /* Drop everything except the ability to use already-opened files */
+ if (priv_delset(box->pset, PRIV_FILE_LINK_ANY) != 0 ||
+#ifdef PRIV_NET_ACCESS
+ priv_delset(box->pset, PRIV_NET_ACCESS) != 0 ||
+#endif
+#ifdef PRIV_DAX_ACCESS
+ priv_delset(box->pset, PRIV_DAX_ACCESS) != 0 ||
+#endif
+#ifdef PRIV_SYS_IB_INFO
+ priv_delset(box->pset, PRIV_SYS_IB_INFO) != 0 ||
+#endif
+ priv_delset(box->pset, PRIV_PROC_EXEC) != 0 ||
+ priv_delset(box->pset, PRIV_PROC_FORK) != 0 ||
+ priv_delset(box->pset, PRIV_PROC_INFO) != 0 ||
+ priv_delset(box->pset, PRIV_PROC_SESSION) != 0) {
+ free(box);
+ return NULL;
+ }
+
+ /* These may not be available on older Solaris-es */
+# if defined(PRIV_FILE_READ) && defined(PRIV_FILE_WRITE)
+ if (priv_delset(box->pset, PRIV_FILE_READ) != 0 ||
+ priv_delset(box->pset, PRIV_FILE_WRITE) != 0) {
+ free(box);
+ return NULL;
+ }
+# endif
+
+ return box;
+}
+
+void
+ssh_sandbox_child(struct ssh_sandbox *box)
+{
+ if (setppriv(PRIV_SET, PRIV_PERMITTED, box->pset) != 0 ||
+ setppriv(PRIV_SET, PRIV_LIMIT, box->pset) != 0 ||
+ setppriv(PRIV_SET, PRIV_INHERITABLE, box->pset) != 0)
+ fatal("setppriv: %s", strerror(errno));
+}
+
+void
+ssh_sandbox_parent_finish(struct ssh_sandbox *box)
+{
+ priv_freeset(box->pset);
+ box->pset = NULL;
+ free(box);
+}
+
+void
+ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid)
+{
+ /* Nothing to do here */
+}
+
+#endif /* SANDBOX_SOLARIS */
diff --git a/sandbox-systrace.c b/sandbox-systrace.c
index f30e7057..e61d581a 100644
--- a/sandbox-systrace.c
+++ b/sandbox-systrace.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sandbox-systrace.c,v 1.14 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: sandbox-systrace.c,v 1.18 2015/10/02 01:39:26 deraadt Exp $ */
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
@@ -36,7 +36,6 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <limits.h>
#include "atomicio.h"
#include "log.h"
@@ -50,7 +49,17 @@ struct sandbox_policy {
/* Permitted syscalls in preauth. Unlisted syscalls get SYSTR_POLICY_KILL */
static const struct sandbox_policy preauth_policy[] = {
- { SYS_open, SYSTR_POLICY_NEVER },
+ { SYS_exit, SYSTR_POLICY_PERMIT },
+#ifdef SYS_kbind
+ { SYS_kbind, SYSTR_POLICY_PERMIT },
+#endif
+
+ { SYS_getpid, SYSTR_POLICY_PERMIT },
+ { SYS_getpgid, SYSTR_POLICY_PERMIT },
+ { SYS_clock_gettime, SYSTR_POLICY_PERMIT },
+ { SYS_gettimeofday, SYSTR_POLICY_PERMIT },
+ { SYS_nanosleep, SYSTR_POLICY_PERMIT },
+ { SYS_sigprocmask, SYSTR_POLICY_PERMIT },
#ifdef SYS_getentropy
/* OpenBSD 5.6 and newer use getentropy(2) to seed arc4random(3). */
@@ -59,26 +68,25 @@ static const struct sandbox_policy preauth_policy[] = {
/* Previous releases used sysctl(3)'s kern.arnd variable. */
{ SYS___sysctl, SYSTR_POLICY_PERMIT },
#endif
-
#ifdef SYS_sendsyslog
- { SYS_sendsyslog, SYSTR_POLICY_PERMIT },
+ { SYS_sendsyslog, SYSTR_POLICY_PERMIT },
#endif
- { SYS_close, SYSTR_POLICY_PERMIT },
- { SYS_exit, SYSTR_POLICY_PERMIT },
- { SYS_getpid, SYSTR_POLICY_PERMIT },
- { SYS_gettimeofday, SYSTR_POLICY_PERMIT },
- { SYS_clock_gettime, SYSTR_POLICY_PERMIT },
+
{ SYS_madvise, SYSTR_POLICY_PERMIT },
{ SYS_mmap, SYSTR_POLICY_PERMIT },
{ SYS_mprotect, SYSTR_POLICY_PERMIT },
{ SYS_mquery, SYSTR_POLICY_PERMIT },
- { SYS_poll, SYSTR_POLICY_PERMIT },
{ SYS_munmap, SYSTR_POLICY_PERMIT },
- { SYS_read, SYSTR_POLICY_PERMIT },
+
+ { SYS_poll, SYSTR_POLICY_PERMIT },
{ SYS_select, SYSTR_POLICY_PERMIT },
- { SYS_shutdown, SYSTR_POLICY_PERMIT },
- { SYS_sigprocmask, SYSTR_POLICY_PERMIT },
+ { SYS_read, SYSTR_POLICY_PERMIT },
{ SYS_write, SYSTR_POLICY_PERMIT },
+ { SYS_shutdown, SYSTR_POLICY_PERMIT },
+ { SYS_close, SYSTR_POLICY_PERMIT },
+
+ { SYS_open, SYSTR_POLICY_NEVER },
+
{ -1, -1 }
};
@@ -97,7 +105,7 @@ ssh_sandbox_init(struct monitor *monitor)
box = xcalloc(1, sizeof(*box));
box->systrace_fd = -1;
box->child_pid = 0;
- box->osigchld = signal(SIGCHLD, SIG_IGN);
+ box->osigchld = ssh_signal(SIGCHLD, SIG_IGN);
return box;
}
@@ -106,7 +114,7 @@ void
ssh_sandbox_child(struct ssh_sandbox *box)
{
debug3("%s: ready", __func__);
- signal(SIGCHLD, box->osigchld);
+ ssh_signal(SIGCHLD, box->osigchld);
if (kill(getpid(), SIGSTOP) != 0)
fatal("%s: kill(%d, SIGSTOP)", __func__, getpid());
debug3("%s: started", __func__);
@@ -125,7 +133,7 @@ ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid,
do {
pid = waitpid(child_pid, &status, WUNTRACED);
} while (pid == -1 && errno == EINTR);
- signal(SIGCHLD, box->osigchld);
+ ssh_signal(SIGCHLD, box->osigchld);
if (!WIFSTOPPED(status)) {
if (WIFSIGNALED(status))
fatal("%s: child terminated with signal %d",
diff --git a/scp.0 b/scp.0
deleted file mode 100644
index 3f309fe0..00000000
--- a/scp.0
+++ /dev/null
@@ -1,164 +0,0 @@
-SCP(1) General Commands Manual SCP(1)
-
-NAME
- scp M-bM-^@M-^S secure copy (remote file copy program)
-
-SYNOPSIS
- scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]
- [-l limit] [-o ssh_option] [-P port] [-S program]
- [[user@]host1:]file1 ... [[user@]host2:]file2
-
-DESCRIPTION
- scp copies files between hosts on a network. It uses ssh(1) for data
- transfer, and uses the same authentication and provides the same security
- as ssh(1). scp will ask for passwords or passphrases if they are needed
- for authentication.
-
- File names may contain a user and host specification to indicate that the
- file is to be copied to/from that host. Local file names can be made
- explicit using absolute or relative pathnames to avoid scp treating file
- names containing M-bM-^@M-^X:M-bM-^@M-^Y as host specifiers. Copies between two remote hosts
- are also permitted.
-
- The options are as follows:
-
- -1 Forces scp to use protocol 1.
-
- -2 Forces scp to use protocol 2.
-
- -3 Copies between two remote hosts are transferred through the local
- host. Without this option the data is copied directly between
- the two remote hosts. Note that this option disables the
- progress meter.
-
- -4 Forces scp to use IPv4 addresses only.
-
- -6 Forces scp to use IPv6 addresses only.
-
- -B Selects batch mode (prevents asking for passwords or
- passphrases).
-
- -C Compression enable. Passes the -C flag to ssh(1) to enable
- compression.
-
- -c cipher
- Selects the cipher to use for encrypting the data transfer. This
- option is directly passed to ssh(1).
-
- -F ssh_config
- Specifies an alternative per-user configuration file for ssh.
- This option is directly passed to ssh(1).
-
- -i identity_file
- Selects the file from which the identity (private key) for public
- key authentication is read. This option is directly passed to
- ssh(1).
-
- -l limit
- Limits the used bandwidth, specified in Kbit/s.
-
- -o ssh_option
- Can be used to pass options to ssh in the format used in
- ssh_config(5). This is useful for specifying options for which
- there is no separate scp command-line flag. For full details of
- the options listed below, and their possible values, see
- ssh_config(5).
-
- AddressFamily
- BatchMode
- BindAddress
- CanonicalDomains
- CanonicalizeFallbackLocal
- CanonicalizeHostname
- CanonicalizeMaxDots
- CanonicalizePermittedCNAMEs
- ChallengeResponseAuthentication
- CheckHostIP
- Cipher
- Ciphers
- Compression
- CompressionLevel
- ConnectionAttempts
- ConnectTimeout
- ControlMaster
- ControlPath
- ControlPersist
- GlobalKnownHostsFile
- GSSAPIAuthentication
- GSSAPIDelegateCredentials
- HashKnownHosts
- Host
- HostbasedAuthentication
- HostbasedKeyTypes
- HostKeyAlgorithms
- HostKeyAlias
- HostName
- IdentityFile
- IdentitiesOnly
- IPQoS
- KbdInteractiveAuthentication
- KbdInteractiveDevices
- KexAlgorithms
- LogLevel
- MACs
- NoHostAuthenticationForLocalhost
- NumberOfPasswordPrompts
- PasswordAuthentication
- PKCS11Provider
- Port
- PreferredAuthentications
- Protocol
- ProxyCommand
- PubkeyAuthentication
- RekeyLimit
- RhostsRSAAuthentication
- RSAAuthentication
- SendEnv
- ServerAliveInterval
- ServerAliveCountMax
- StrictHostKeyChecking
- TCPKeepAlive
- UpdateHostKeys
- UsePrivilegedPort
- User
- UserKnownHostsFile
- VerifyHostKeyDNS
-
- -P port
- Specifies the port to connect to on the remote host. Note that
- this option is written with a capital M-bM-^@M-^XPM-bM-^@M-^Y, because -p is already
- reserved for preserving the times and modes of the file.
-
- -p Preserves modification times, access times, and modes from the
- original file.
-
- -q Quiet mode: disables the progress meter as well as warning and
- diagnostic messages from ssh(1).
-
- -r Recursively copy entire directories. Note that scp follows
- symbolic links encountered in the tree traversal.
-
- -S program
- Name of program to use for the encrypted connection. The program
- must understand ssh(1) options.
-
- -v Verbose mode. Causes scp and ssh(1) to print debugging messages
- about their progress. This is helpful in debugging connection,
- authentication, and configuration problems.
-
-EXIT STATUS
- The scp utility exitsM-BM- 0 on success, andM-BM- >0 if an error occurs.
-
-SEE ALSO
- sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh_config(5),
- sshd(8)
-
-HISTORY
- scp is based on the rcp program in BSD source code from the Regents of
- the University of California.
-
-AUTHORS
- Timo Rinne <tri@iki.fi>
- Tatu Ylonen <ylo@cs.hut.fi>
-
-OpenBSD 5.7 January 30, 2015 OpenBSD 5.7
diff --git a/scp.1 b/scp.1
index 0e84780e..d5f65af4 100644
--- a/scp.1
+++ b/scp.1
@@ -8,39 +8,26 @@
.\"
.\" Created: Sun May 7 00:14:37 1995 ylo
.\"
-.\" $OpenBSD: scp.1,v 1.66 2015/01/30 11:43:14 djm Exp $
+.\" $OpenBSD: scp.1,v 1.89 2020/04/30 18:28:37 jmc Exp $
.\"
-.Dd $Mdocdate: January 30 2015 $
+.Dd $Mdocdate: April 30 2020 $
.Dt SCP 1
.Os
.Sh NAME
.Nm scp
-.Nd secure copy (remote file copy program)
+.Nd OpenSSH secure file copy
.Sh SYNOPSIS
.Nm scp
-.Bk -words
-.Op Fl 12346BCpqrv
+.Op Fl 346BCpqrTv
.Op Fl c Ar cipher
.Op Fl F Ar ssh_config
.Op Fl i Ar identity_file
+.Op Fl J Ar destination
.Op Fl l Ar limit
.Op Fl o Ar ssh_option
.Op Fl P Ar port
.Op Fl S Ar program
-.Sm off
-.Oo
-.Op Ar user No @
-.Ar host1 :
-.Oc Ar file1
-.Sm on
-.Ar ...
-.Sm off
-.Oo
-.Op Ar user No @
-.Ar host2 :
-.Oc Ar file2
-.Sm on
-.Ek
+.Ar source ... target
.Sh DESCRIPTION
.Nm
copies files between hosts on a network.
@@ -53,31 +40,44 @@ same security as
will ask for passwords or passphrases if they are needed for
authentication.
.Pp
-File names may contain a user and host specification to indicate
-that the file is to be copied to/from that host.
+The
+.Ar source
+and
+.Ar target
+may be specified as a local pathname, a remote host with optional path
+in the form
+.Sm off
+.Oo user @ Oc host : Op path ,
+.Sm on
+or a URI in the form
+.Sm off
+.No scp:// Oo user @ Oc host Oo : port Oc Op / path .
+.Sm on
Local file names can be made explicit using absolute or relative pathnames
to avoid
.Nm
treating file names containing
.Sq :\&
as host specifiers.
-Copies between two remote hosts are also permitted.
+.Pp
+When copying between two remote hosts, if the URI format is used, a
+.Ar port
+may only be specified on the
+.Ar target
+if the
+.Fl 3
+option is used.
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl 1
-Forces
-.Nm
-to use protocol 1.
-.It Fl 2
-Forces
-.Nm
-to use protocol 2.
.It Fl 3
Copies between two remote hosts are transferred through the local host.
Without this option the data is copied directly between the two remote
hosts.
-Note that this option disables the progress meter.
+Note that this option disables the progress meter and selects batch mode
+for the second host, since
+.Nm
+cannot ask for passwords or passphrases for both hosts.
.It Fl 4
Forces
.Nm
@@ -110,6 +110,19 @@ Selects the file from which the identity (private key) for public key
authentication is read.
This option is directly passed to
.Xr ssh 1 .
+.It Fl J Ar destination
+Connect to the target host by first making an
+.Nm
+connection to the jump host described by
+.Ar destination
+and then establishing a TCP forwarding to the ultimate destination from
+there.
+Multiple jump hops may be specified separated by comma characters.
+This is a shortcut to specify a
+.Cm ProxyJump
+configuration directive.
+This option is directly passed to
+.Xr ssh 1 .
.It Fl l Ar limit
Limits the used bandwidth, specified in Kbit/s.
.It Fl o Ar ssh_option
@@ -128,17 +141,18 @@ For full details of the options listed below, and their possible values, see
.It AddressFamily
.It BatchMode
.It BindAddress
+.It BindInterface
.It CanonicalDomains
.It CanonicalizeFallbackLocal
.It CanonicalizeHostname
.It CanonicalizeMaxDots
.It CanonicalizePermittedCNAMEs
+.It CASignatureAlgorithms
+.It CertificateFile
.It ChallengeResponseAuthentication
.It CheckHostIP
-.It Cipher
.It Ciphers
.It Compression
-.It CompressionLevel
.It ConnectionAttempts
.It ConnectTimeout
.It ControlMaster
@@ -153,9 +167,10 @@ For full details of the options listed below, and their possible values, see
.It HostbasedKeyTypes
.It HostKeyAlgorithms
.It HostKeyAlias
-.It HostName
-.It IdentityFile
+.It Hostname
.It IdentitiesOnly
+.It IdentityAgent
+.It IdentityFile
.It IPQoS
.It KbdInteractiveAuthentication
.It KbdInteractiveDevices
@@ -168,19 +183,18 @@ For full details of the options listed below, and their possible values, see
.It PKCS11Provider
.It Port
.It PreferredAuthentications
-.It Protocol
.It ProxyCommand
+.It ProxyJump
+.It PubkeyAcceptedKeyTypes
.It PubkeyAuthentication
.It RekeyLimit
-.It RhostsRSAAuthentication
-.It RSAAuthentication
.It SendEnv
.It ServerAliveInterval
.It ServerAliveCountMax
+.It SetEnv
.It StrictHostKeyChecking
.It TCPKeepAlive
.It UpdateHostKeys
-.It UsePrivilegedPort
.It User
.It UserKnownHostsFile
.It VerifyHostKeyDNS
@@ -211,6 +225,16 @@ to use for the encrypted connection.
The program must understand
.Xr ssh 1
options.
+.It Fl T
+Disable strict filename checking.
+By default when copying files from a remote host to a local directory
+.Nm
+checks that the received filenames match those requested on the command-line
+to prevent the remote end from sending unexpected or unwanted files.
+Because of differences in how various operating systems and shells interpret
+filename wildcards, these checks may cause wanted files to be rejected.
+This option disables these checks at the expense of fully trusting that
+the server will not send unexpected filenames.
.It Fl v
Verbose mode.
Causes
diff --git a/scp.c b/scp.c
index 887b014b..b4492a06 100644
--- a/scp.c
+++ b/scp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scp.c,v 1.181 2015/01/16 06:40:12 deraadt Exp $ */
+/* $OpenBSD: scp.c,v 1.210 2020/05/06 20:57:38 djm Exp $ */
/*
* scp - secure remote copy. This is basically patched BSD rcp which
* uses ssh to do the data transfer (instead of using rcmd).
@@ -74,7 +74,6 @@
#include "includes.h"
#include <sys/types.h>
-#include <sys/param.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
@@ -95,10 +94,17 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#ifdef HAVE_FNMATCH_H
+#include <fnmatch.h>
+#endif
#include <limits.h>
+#include <locale.h>
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -109,18 +115,20 @@
#endif
#include "xmalloc.h"
+#include "ssh.h"
#include "atomicio.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "progressmeter.h"
+#include "utf8.h"
extern char *__progname;
#define COPY_BUFLEN 16384
-int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout);
-int do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout);
+int do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout);
+int do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout);
/* Struct for addargs */
arglist args;
@@ -145,6 +153,9 @@ int showprogress = 1;
*/
int throughlocal = 0;
+/* Non-standard port to use for the ssh connection or -1. */
+int sshport = -1;
+
/* This is the program to execute for the secured connection. ("ssh" or -S) */
char *ssh_program = _PATH_SSH_PROGRAM;
@@ -191,7 +202,7 @@ do_local_cmd(arglist *a)
if (verbose_mode) {
fprintf(stderr, "Executing:");
for (i = 0; i < a->num; i++)
- fprintf(stderr, " %s", a->list[i]);
+ fmprintf(stderr, " %s", a->list[i]);
fprintf(stderr, "\n");
}
if ((pid = fork()) == -1)
@@ -204,9 +215,9 @@ do_local_cmd(arglist *a)
}
do_cmd_pid = pid;
- signal(SIGTERM, killchild);
- signal(SIGINT, killchild);
- signal(SIGHUP, killchild);
+ ssh_signal(SIGTERM, killchild);
+ ssh_signal(SIGINT, killchild);
+ ssh_signal(SIGHUP, killchild);
while (waitpid(pid, &status, 0) == -1)
if (errno != EINTR)
@@ -227,36 +238,39 @@ do_local_cmd(arglist *a)
*/
int
-do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
+do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout)
{
int pin[2], pout[2], reserved[2];
if (verbose_mode)
- fprintf(stderr,
+ fmprintf(stderr,
"Executing: program %s host %s, user %s, command %s\n",
ssh_program, host,
remuser ? remuser : "(unspecified)", cmd);
+ if (port == -1)
+ port = sshport;
+
/*
* Reserve two descriptors so that the real pipes won't get
* descriptors 0 and 1 because that will screw up dup2 below.
*/
- if (pipe(reserved) < 0)
+ if (pipe(reserved) == -1)
fatal("pipe: %s", strerror(errno));
/* Create a socket pair for communicating with ssh. */
- if (pipe(pin) < 0)
+ if (pipe(pin) == -1)
fatal("pipe: %s", strerror(errno));
- if (pipe(pout) < 0)
+ if (pipe(pout) == -1)
fatal("pipe: %s", strerror(errno));
/* Free the reserved descriptors. */
close(reserved[0]);
close(reserved[1]);
- signal(SIGTSTP, suspchild);
- signal(SIGTTIN, suspchild);
- signal(SIGTTOU, suspchild);
+ ssh_signal(SIGTSTP, suspchild);
+ ssh_signal(SIGTTIN, suspchild);
+ ssh_signal(SIGTTOU, suspchild);
/* Fork a child to execute the command on the remote host using ssh. */
do_cmd_pid = fork();
@@ -270,6 +284,10 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
close(pout[1]);
replacearg(&args, 0, "%s", ssh_program);
+ if (port != -1) {
+ addargs(&args, "-p");
+ addargs(&args, "%d", port);
+ }
if (remuser != NULL) {
addargs(&args, "-l");
addargs(&args, "%s", remuser);
@@ -289,29 +307,32 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
*fdout = pin[1];
close(pout[1]);
*fdin = pout[0];
- signal(SIGTERM, killchild);
- signal(SIGINT, killchild);
- signal(SIGHUP, killchild);
+ ssh_signal(SIGTERM, killchild);
+ ssh_signal(SIGINT, killchild);
+ ssh_signal(SIGHUP, killchild);
return 0;
}
/*
- * This functions executes a command simlar to do_cmd(), but expects the
+ * This function executes a command similar to do_cmd(), but expects the
* input and output descriptors to be setup by a previous call to do_cmd().
* This way the input and output of two commands can be connected.
*/
int
-do_cmd2(char *host, char *remuser, 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;
if (verbose_mode)
- fprintf(stderr,
+ fmprintf(stderr,
"Executing: 2nd program %s host %s, user %s, command %s\n",
ssh_program, host,
remuser ? remuser : "(unspecified)", cmd);
+ if (port == -1)
+ port = sshport;
+
/* Fork a child to execute the command on the remote host using ssh. */
pid = fork();
if (pid == 0) {
@@ -319,10 +340,15 @@ do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout)
dup2(fdout, 1);
replacearg(&args, 0, "%s", ssh_program);
+ if (port != -1) {
+ addargs(&args, "-p");
+ addargs(&args, "%d", port);
+ }
if (remuser != NULL) {
addargs(&args, "-l");
addargs(&args, "%s", remuser);
}
+ addargs(&args, "-oBatchMode=yes");
addargs(&args, "--");
addargs(&args, "%s", host);
addargs(&args, "%s", cmd);
@@ -348,29 +374,30 @@ BUF *allocbuf(BUF *, int, int);
void lostconn(int);
int okname(char *);
void run_err(const char *,...);
+int note_err(const char *,...);
void verifydir(char *);
struct passwd *pwd;
uid_t userid;
int errs, remin, remout;
-int pflag, iamremote, iamrecursive, targetshouldbedirectory;
+int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
#define CMDNEEDS 64
char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
int response(void);
void rsource(char *, struct stat *);
-void sink(int, char *[]);
+void sink(int, char *[], const char *);
void source(int, char *[]);
void tolocal(int, char *[]);
-void toremote(char *, int, char *[]);
+void toremote(int, char *[]);
void usage(void);
int
main(int argc, char **argv)
{
int ch, fflag, tflag, status, n;
- char *targ, **newargv;
+ char **newargv;
const char *errstr;
extern char *optarg;
extern int optind;
@@ -378,8 +405,12 @@ main(int argc, char **argv)
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
+ seed_rng();
+
+ msetlocale();
+
/* Copy argv, because we modify it */
- newargv = xcalloc(MAX(argc + 1, 1), sizeof(*newargv));
+ newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv));
for (n = 0; n < argc; n++)
newargv[n] = xstrdup(argv[n]);
argv = newargv;
@@ -394,13 +425,20 @@ main(int argc, char **argv)
addargs(&args, "-oForwardAgent=no");
addargs(&args, "-oPermitLocalCommand=no");
addargs(&args, "-oClearAllForwardings=yes");
+ addargs(&args, "-oRemoteCommand=none");
+ addargs(&args, "-oRequestTTY=no");
- fflag = tflag = 0;
- while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1)
+ fflag = Tflag = tflag = 0;
+ while ((ch = getopt(argc, argv,
+ "dfl:prtTvBCc:i:P:q12346S:o:F:J:")) != -1) {
switch (ch) {
/* User-visible flags. */
case '1':
+ fatal("SSH protocol v.1 is no longer supported");
+ break;
case '2':
+ /* Ignored */
+ break;
case '4':
case '6':
case 'C':
@@ -414,16 +452,16 @@ main(int argc, char **argv)
case 'c':
case 'i':
case 'F':
+ case 'J':
addargs(&remote_remote_args, "-%c", ch);
addargs(&remote_remote_args, "%s", optarg);
addargs(&args, "-%c", ch);
addargs(&args, "%s", optarg);
break;
case 'P':
- addargs(&remote_remote_args, "-p");
- addargs(&remote_remote_args, "%s", optarg);
- addargs(&args, "-p");
- addargs(&args, "%s", optarg);
+ sshport = a2port(optarg);
+ if (sshport <= 0)
+ fatal("bad port \"%s\"\n", optarg);
break;
case 'B':
addargs(&remote_remote_args, "-oBatchmode=yes");
@@ -472,9 +510,13 @@ main(int argc, char **argv)
setmode(0, O_BINARY);
#endif
break;
+ case 'T':
+ Tflag = 1;
+ break;
default:
usage();
}
+ }
argc -= optind;
argv += optind;
@@ -484,6 +526,16 @@ main(int argc, char **argv)
if (!isatty(STDOUT_FILENO))
showprogress = 0;
+ if (pflag) {
+ /* Cannot pledge: -p allows setuid/setgid files... */
+ } else {
+ if (pledge("stdio rpath wpath cpath fattr tty proc exec",
+ NULL) == -1) {
+ perror("pledge");
+ exit(1);
+ }
+ }
+
remin = STDIN_FILENO;
remout = STDOUT_FILENO;
@@ -495,7 +547,7 @@ main(int argc, char **argv)
}
if (tflag) {
/* Receive data. */
- sink(argc, argv);
+ sink(argc, argv, NULL);
exit(errs != 0);
}
if (argc < 2)
@@ -511,10 +563,10 @@ main(int argc, char **argv)
iamrecursive ? " -r" : "", pflag ? " -p" : "",
targetshouldbedirectory ? " -d" : "");
- (void) signal(SIGPIPE, lostconn);
+ (void) ssh_signal(SIGPIPE, lostconn);
- if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
- toremote(targ, argc, argv);
+ if (colon(argv[argc - 1])) /* Dest is remote host. */
+ toremote(argc, argv);
else {
if (targetshouldbedirectory)
verifydir(argv[argc - 1]);
@@ -546,6 +598,7 @@ scpio(void *_cnt, size_t s)
off_t *cnt = (off_t *)_cnt;
*cnt += s;
+ refresh_progress_meter(0);
if (limit_kbps > 0)
bandwidth_limit(&bwlimit, s);
return 0;
@@ -569,72 +622,337 @@ do_times(int fd, int verb, const struct stat *sb)
return (response());
}
+static int
+parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp,
+ char **pathp)
+{
+ int r;
+
+ r = parse_uri("scp", uri, userp, hostp, portp, pathp);
+ if (r == 0 && *pathp == NULL)
+ *pathp = xstrdup(".");
+ return r;
+}
+
+/* Appends a string to an array; returns 0 on success, -1 on alloc failure */
+static int
+append(char *cp, char ***ap, size_t *np)
+{
+ char **tmp;
+
+ if ((tmp = reallocarray(*ap, *np + 1, sizeof(*tmp))) == NULL)
+ return -1;
+ tmp[(*np)] = cp;
+ (*np)++;
+ *ap = tmp;
+ return 0;
+}
+
+/*
+ * Finds the start and end of the first brace pair in the pattern.
+ * returns 0 on success or -1 for invalid patterns.
+ */
+static int
+find_brace(const char *pattern, int *startp, int *endp)
+{
+ int i;
+ int in_bracket, brace_level;
+
+ *startp = *endp = -1;
+ in_bracket = brace_level = 0;
+ for (i = 0; i < INT_MAX && *endp < 0 && pattern[i] != '\0'; i++) {
+ switch (pattern[i]) {
+ case '\\':
+ /* skip next character */
+ if (pattern[i + 1] != '\0')
+ i++;
+ break;
+ case '[':
+ in_bracket = 1;
+ break;
+ case ']':
+ in_bracket = 0;
+ break;
+ case '{':
+ if (in_bracket)
+ break;
+ if (pattern[i + 1] == '}') {
+ /* Protect a single {}, for find(1), like csh */
+ i++; /* skip */
+ break;
+ }
+ if (*startp == -1)
+ *startp = i;
+ brace_level++;
+ break;
+ case '}':
+ if (in_bracket)
+ break;
+ if (*startp < 0) {
+ /* Unbalanced brace */
+ return -1;
+ }
+ if (--brace_level <= 0)
+ *endp = i;
+ break;
+ }
+ }
+ /* unbalanced brackets/braces */
+ if (*endp < 0 && (*startp >= 0 || in_bracket))
+ return -1;
+ return 0;
+}
+
+/*
+ * Assembles and records a successfully-expanded pattern, returns -1 on
+ * alloc failure.
+ */
+static int
+emit_expansion(const char *pattern, int brace_start, int brace_end,
+ int sel_start, int sel_end, char ***patternsp, size_t *npatternsp)
+{
+ char *cp;
+ int o = 0, tail_len = strlen(pattern + brace_end + 1);
+
+ if ((cp = malloc(brace_start + (sel_end - sel_start) +
+ tail_len + 1)) == NULL)
+ return -1;
+
+ /* Pattern before initial brace */
+ if (brace_start > 0) {
+ memcpy(cp, pattern, brace_start);
+ o = brace_start;
+ }
+ /* Current braced selection */
+ if (sel_end - sel_start > 0) {
+ memcpy(cp + o, pattern + sel_start,
+ sel_end - sel_start);
+ o += sel_end - sel_start;
+ }
+ /* Remainder of pattern after closing brace */
+ if (tail_len > 0) {
+ memcpy(cp + o, pattern + brace_end + 1, tail_len);
+ o += tail_len;
+ }
+ cp[o] = '\0';
+ if (append(cp, patternsp, npatternsp) != 0) {
+ free(cp);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Expand the first encountered brace in pattern, appending the expanded
+ * patterns it yielded to the *patternsp array.
+ *
+ * Returns 0 on success or -1 on allocation failure.
+ *
+ * Signals whether expansion was performed via *expanded and whether
+ * pattern was invalid via *invalid.
+ */
+static int
+brace_expand_one(const char *pattern, char ***patternsp, size_t *npatternsp,
+ int *expanded, int *invalid)
+{
+ int i;
+ int in_bracket, brace_start, brace_end, brace_level;
+ int sel_start, sel_end;
+
+ *invalid = *expanded = 0;
+
+ if (find_brace(pattern, &brace_start, &brace_end) != 0) {
+ *invalid = 1;
+ return 0;
+ } else if (brace_start == -1)
+ return 0;
+
+ in_bracket = brace_level = 0;
+ for (i = sel_start = brace_start + 1; i < brace_end; i++) {
+ switch (pattern[i]) {
+ case '{':
+ if (in_bracket)
+ break;
+ brace_level++;
+ break;
+ case '}':
+ if (in_bracket)
+ break;
+ brace_level--;
+ break;
+ case '[':
+ in_bracket = 1;
+ break;
+ case ']':
+ in_bracket = 0;
+ break;
+ case '\\':
+ if (i < brace_end - 1)
+ i++; /* skip */
+ break;
+ }
+ if (pattern[i] == ',' || i == brace_end - 1) {
+ if (in_bracket || brace_level > 0)
+ continue;
+ /* End of a selection, emit an expanded pattern */
+
+ /* Adjust end index for last selection */
+ sel_end = (i == brace_end - 1) ? brace_end : i;
+ if (emit_expansion(pattern, brace_start, brace_end,
+ sel_start, sel_end, patternsp, npatternsp) != 0)
+ return -1;
+ /* move on to the next selection */
+ sel_start = i + 1;
+ continue;
+ }
+ }
+ if (in_bracket || brace_level > 0) {
+ *invalid = 1;
+ return 0;
+ }
+ /* success */
+ *expanded = 1;
+ return 0;
+}
+
+/* Expand braces from pattern. Returns 0 on success, -1 on failure */
+static int
+brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp)
+{
+ char *cp, *cp2, **active = NULL, **done = NULL;
+ size_t i, nactive = 0, ndone = 0;
+ int ret = -1, invalid = 0, expanded = 0;
+
+ *patternsp = NULL;
+ *npatternsp = 0;
+
+ /* Start the worklist with the original pattern */
+ if ((cp = strdup(pattern)) == NULL)
+ return -1;
+ if (append(cp, &active, &nactive) != 0) {
+ free(cp);
+ return -1;
+ }
+ while (nactive > 0) {
+ cp = active[nactive - 1];
+ nactive--;
+ if (brace_expand_one(cp, &active, &nactive,
+ &expanded, &invalid) == -1) {
+ free(cp);
+ goto fail;
+ }
+ if (invalid)
+ fatal("%s: invalid brace pattern \"%s\"", __func__, cp);
+ if (expanded) {
+ /*
+ * Current entry expanded to new entries on the
+ * active list; discard the progenitor pattern.
+ */
+ free(cp);
+ continue;
+ }
+ /*
+ * Pattern did not expand; append the finename component to
+ * the completed list
+ */
+ if ((cp2 = strrchr(cp, '/')) != NULL)
+ *cp2++ = '\0';
+ else
+ cp2 = cp;
+ if (append(xstrdup(cp2), &done, &ndone) != 0) {
+ free(cp);
+ goto fail;
+ }
+ free(cp);
+ }
+ /* success */
+ *patternsp = done;
+ *npatternsp = ndone;
+ done = NULL;
+ ndone = 0;
+ ret = 0;
+ fail:
+ for (i = 0; i < nactive; i++)
+ free(active[i]);
+ free(active);
+ for (i = 0; i < ndone; i++)
+ free(done[i]);
+ free(done);
+ return ret;
+}
+
void
-toremote(char *targ, int argc, char **argv)
+toremote(int argc, char **argv)
{
- char *bp, *host, *src, *suser, *thost, *tuser, *arg;
+ char *suser = NULL, *host = NULL, *src = NULL;
+ char *bp, *tuser, *thost, *targ;
+ int sport = -1, tport = -1;
arglist alist;
- int i;
+ int i, r;
u_int j;
memset(&alist, '\0', sizeof(alist));
alist.list = NULL;
- *targ++ = 0;
- if (*targ == 0)
- targ = ".";
-
- arg = xstrdup(argv[argc - 1]);
- if ((thost = strrchr(arg, '@'))) {
- /* user@host */
- *thost++ = 0;
- tuser = arg;
- if (*tuser == '\0')
- tuser = NULL;
- } else {
- thost = arg;
- tuser = NULL;
+ /* Parse target */
+ r = parse_scp_uri(argv[argc - 1], &tuser, &thost, &tport, &targ);
+ if (r == -1) {
+ fmprintf(stderr, "%s: invalid uri\n", argv[argc - 1]);
+ ++errs;
+ goto out;
+ }
+ if (r != 0) {
+ if (parse_user_host_path(argv[argc - 1], &tuser, &thost,
+ &targ) == -1) {
+ fmprintf(stderr, "%s: invalid target\n", argv[argc - 1]);
+ ++errs;
+ goto out;
+ }
}
-
if (tuser != NULL && !okname(tuser)) {
- free(arg);
- return;
+ ++errs;
+ goto out;
}
+ /* Parse source files */
for (i = 0; i < argc - 1; i++) {
- src = colon(argv[i]);
- if (src && throughlocal) { /* extended remote to remote */
- *src++ = 0;
- if (*src == 0)
- src = ".";
- host = strrchr(argv[i], '@');
- if (host) {
- *host++ = 0;
- host = cleanhostname(host);
- suser = argv[i];
- if (*suser == '\0')
- suser = pwd->pw_name;
- else if (!okname(suser))
- continue;
- } else {
- host = cleanhostname(argv[i]);
- suser = NULL;
- }
+ free(suser);
+ free(host);
+ free(src);
+ r = parse_scp_uri(argv[i], &suser, &host, &sport, &src);
+ if (r == -1) {
+ fmprintf(stderr, "%s: invalid uri\n", argv[i]);
+ ++errs;
+ continue;
+ }
+ if (r != 0) {
+ parse_user_host_path(argv[i], &suser, &host, &src);
+ }
+ if (suser != NULL && !okname(suser)) {
+ ++errs;
+ continue;
+ }
+ if (host && throughlocal) { /* extended remote to remote */
xasprintf(&bp, "%s -f %s%s", cmd,
*src == '-' ? "-- " : "", src);
- if (do_cmd(host, suser, bp, &remin, &remout) < 0)
+ if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0)
exit(1);
free(bp);
- host = cleanhostname(thost);
xasprintf(&bp, "%s -t %s%s", cmd,
*targ == '-' ? "-- " : "", targ);
- if (do_cmd2(host, tuser, bp, remin, remout) < 0)
+ 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 (src) { /* standard remote to remote */
+ } else if (host) { /* standard remote to remote */
+ if (tport != -1 && tport != SSH_DEFAULT_PORT) {
+ /* This would require the remote support URIs */
+ fatal("target port not supported with two "
+ "remote hosts without the -3 option");
+ }
+
freeargs(&alist);
addargs(&alist, "%s", ssh_program);
addargs(&alist, "-x");
@@ -644,23 +962,14 @@ toremote(char *targ, int argc, char **argv)
addargs(&alist, "%s",
remote_remote_args.list[j]);
}
- *src++ = 0;
- if (*src == 0)
- src = ".";
- host = strrchr(argv[i], '@');
-
- if (host) {
- *host++ = 0;
- host = cleanhostname(host);
- suser = argv[i];
- if (*suser == '\0')
- suser = pwd->pw_name;
- else if (!okname(suser))
- continue;
+
+ if (sport != -1) {
+ addargs(&alist, "-p");
+ addargs(&alist, "%d", sport);
+ }
+ if (suser) {
addargs(&alist, "-l");
addargs(&alist, "%s", suser);
- } else {
- host = cleanhostname(argv[i]);
}
addargs(&alist, "--");
addargs(&alist, "%s", host);
@@ -675,8 +984,7 @@ toremote(char *targ, int argc, char **argv)
if (remin == -1) {
xasprintf(&bp, "%s -t %s%s", cmd,
*targ == '-' ? "-- " : "", targ);
- host = cleanhostname(thost);
- if (do_cmd(host, tuser, bp, &remin,
+ if (do_cmd(thost, tuser, tport, bp, &remin,
&remout) < 0)
exit(1);
if (response() < 0)
@@ -686,21 +994,42 @@ toremote(char *targ, int argc, char **argv)
source(1, argv + i);
}
}
- free(arg);
+out:
+ free(tuser);
+ free(thost);
+ free(targ);
+ free(suser);
+ free(host);
+ free(src);
}
void
tolocal(int argc, char **argv)
{
- char *bp, *host, *src, *suser;
+ char *bp, *host = NULL, *src = NULL, *suser = NULL;
arglist alist;
- int i;
+ int i, r, sport = -1;
memset(&alist, '\0', sizeof(alist));
alist.list = NULL;
for (i = 0; i < argc - 1; i++) {
- if (!(src = colon(argv[i]))) { /* Local to local. */
+ free(suser);
+ free(host);
+ free(src);
+ r = parse_scp_uri(argv[i], &suser, &host, &sport, &src);
+ if (r == -1) {
+ fmprintf(stderr, "%s: invalid uri\n", argv[i]);
+ ++errs;
+ continue;
+ }
+ if (r != 0)
+ parse_user_host_path(argv[i], &suser, &host, &src);
+ if (suser != NULL && !okname(suser)) {
+ ++errs;
+ continue;
+ }
+ if (!host) { /* Local to local. */
freeargs(&alist);
addargs(&alist, "%s", _PATH_CP);
if (iamrecursive)
@@ -714,31 +1043,22 @@ tolocal(int argc, char **argv)
++errs;
continue;
}
- *src++ = 0;
- if (*src == 0)
- src = ".";
- if ((host = strrchr(argv[i], '@')) == NULL) {
- host = argv[i];
- suser = NULL;
- } else {
- *host++ = 0;
- suser = argv[i];
- if (*suser == '\0')
- suser = pwd->pw_name;
- }
- host = cleanhostname(host);
+ /* Remote to local. */
xasprintf(&bp, "%s -f %s%s",
cmd, *src == '-' ? "-- " : "", src);
- if (do_cmd(host, suser, bp, &remin, &remout) < 0) {
+ if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0) {
free(bp);
++errs;
continue;
}
free(bp);
- sink(1, argv + argc - 1);
+ sink(1, argv + argc - 1, src);
(void) close(remin);
remin = remout = -1;
}
+ free(suser);
+ free(host);
+ free(src);
}
void
@@ -750,7 +1070,7 @@ source(int argc, char **argv)
off_t i, statbytes;
size_t amt, nr;
int fd = -1, haderr, indx;
- char *last, *name, buf[2048], encname[PATH_MAX];
+ char *last, *name, buf[PATH_MAX + 128], encname[PATH_MAX];
int len;
for (indx = 0; indx < argc; ++indx) {
@@ -759,13 +1079,13 @@ source(int argc, char **argv)
len = strlen(name);
while (len > 1 && name[len-1] == '/')
name[--len] = '\0';
- if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) < 0)
+ if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) == -1)
goto syserr;
if (strchr(name, '\n') != NULL) {
strnvis(encname, name, sizeof(encname), VIS_NL);
name = encname;
}
- if (fstat(fd, &stb) < 0) {
+ if (fstat(fd, &stb) == -1) {
syserr: run_err("%s: %s", name, strerror(errno));
goto next;
}
@@ -800,9 +1120,8 @@ syserr: run_err("%s: %s", name, strerror(errno));
snprintf(buf, sizeof buf, "C%04o %lld %s\n",
(u_int) (stb.st_mode & FILEMODEMASK),
(long long)stb.st_size, last);
- if (verbose_mode) {
- fprintf(stderr, "Sending file modes: %s", buf);
- }
+ if (verbose_mode)
+ fmprintf(stderr, "Sending file modes: %s", buf);
(void) atomicio(vwrite, remout, buf, strlen(buf));
if (response() < 0)
goto next;
@@ -838,11 +1157,9 @@ next: if (fd != -1) {
haderr = errno;
}
unset_nonblock(remout);
- if (showprogress)
- stop_progress_meter();
if (fd != -1) {
- if (close(fd) < 0 && !haderr)
+ if (close(fd) == -1 && !haderr)
haderr = errno;
fd = -1;
}
@@ -851,6 +1168,8 @@ next: if (fd != -1) {
else
run_err("%s: %s", name, strerror(haderr));
(void) response();
+ if (showprogress)
+ stop_progress_meter();
}
}
@@ -866,7 +1185,7 @@ rsource(char *name, struct stat *statp)
return;
}
last = strrchr(name, '/');
- if (last == 0)
+ if (last == NULL)
last = name;
else
last++;
@@ -879,7 +1198,7 @@ rsource(char *name, struct stat *statp)
(void) snprintf(path, sizeof path, "D%04o %d %.1024s\n",
(u_int) (statp->st_mode & FILEMODEMASK), 0, last);
if (verbose_mode)
- fprintf(stderr, "Entering directory: %s", path);
+ fmprintf(stderr, "Entering directory: %s", path);
(void) atomicio(vwrite, remout, path, strlen(path));
if (response() < 0) {
closedir(dirp);
@@ -903,14 +1222,16 @@ rsource(char *name, struct stat *statp)
(void) response();
}
+#define TYPE_OVERFLOW(type, val) \
+ ((sizeof(type) == 4 && (val) > INT32_MAX) || \
+ (sizeof(type) == 8 && (val) > INT64_MAX) || \
+ (sizeof(type) != 4 && sizeof(type) != 8))
+
void
-sink(int argc, char **argv)
+sink(int argc, char **argv, const char *src)
{
static BUF buffer;
struct stat stb;
- enum {
- YES, NO, DISPLAYED
- } wrerr;
BUF *bp;
off_t i;
size_t j, count;
@@ -918,14 +1239,19 @@ sink(int argc, char **argv)
mode_t mode, omode, mask;
off_t size, statbytes;
unsigned long long ull;
- int setimes, targisdir, wrerrno = 0;
- char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
+ int setimes, targisdir, wrerr;
+ char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
+ char **patterns = NULL;
+ size_t n, npatterns = 0;
struct timeval tv[2];
#define atime tv[0]
#define mtime tv[1]
#define SCREWUP(str) { why = str; goto screwup; }
+ if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0))
+ SCREWUP("Unexpected off_t/time_t size");
+
setimes = targisdir = 0;
mask = umask(0);
if (!pflag)
@@ -941,10 +1267,18 @@ sink(int argc, char **argv)
(void) atomicio(vwrite, remout, "", 1);
if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
targisdir = 1;
+ if (src != NULL && !iamrecursive && !Tflag) {
+ /*
+ * Prepare to try to restrict incoming filenames to match
+ * the requested destination file glob.
+ */
+ if (brace_expand(src, &patterns, &npatterns) != 0)
+ fatal("%s: could not expand pattern", __func__);
+ }
for (first = 1;; first = 0) {
cp = buf;
if (atomicio(read, remin, cp, 1) != 1)
- return;
+ goto done;
if (*cp++ == '\n')
SCREWUP("unexpected <newline>");
do {
@@ -954,12 +1288,15 @@ sink(int argc, char **argv)
} while (cp < &buf[sizeof(buf) - 1] && ch != '\n');
*cp = 0;
if (verbose_mode)
- fprintf(stderr, "Sink: %s", buf);
+ fmprintf(stderr, "Sink: %s", buf);
if (buf[0] == '\01' || buf[0] == '\02') {
- if (iamremote == 0)
+ if (iamremote == 0) {
+ (void) snmprintf(visbuf, sizeof(visbuf),
+ NULL, "%s", buf + 1);
(void) atomicio(vwrite, STDERR_FILENO,
- buf + 1, strlen(buf + 1));
+ visbuf, strlen(visbuf));
+ }
if (buf[0] == '\02')
exit(1);
++errs;
@@ -967,7 +1304,7 @@ sink(int argc, char **argv)
}
if (buf[0] == 'E') {
(void) atomicio(vwrite, remout, "", 1);
- return;
+ goto done;
}
if (ch == '\n')
*--cp = 0;
@@ -981,8 +1318,7 @@ sink(int argc, char **argv)
ull = strtoull(cp, &cp, 10);
if (!cp || *cp++ != ' ')
SCREWUP("mtime.sec not delimited");
- if ((time_t)ull < 0 ||
- (unsigned long long)(time_t)ull != ull)
+ if (TYPE_OVERFLOW(time_t, ull))
setimes = 0; /* out of range */
mtime.tv_sec = ull;
mtime.tv_usec = strtol(cp, &cp, 10);
@@ -994,8 +1330,7 @@ sink(int argc, char **argv)
ull = strtoull(cp, &cp, 10);
if (!cp || *cp++ != ' ')
SCREWUP("atime.sec not delimited");
- if ((time_t)ull < 0 ||
- (unsigned long long)(time_t)ull != ull)
+ if (TYPE_OVERFLOW(time_t, ull))
setimes = 0; /* out of range */
atime.tv_sec = ull;
atime.tv_usec = strtol(cp, &cp, 10);
@@ -1025,17 +1360,33 @@ sink(int argc, char **argv)
SCREWUP("bad mode");
mode = (mode << 3) | (*cp - '0');
}
+ if (!pflag)
+ mode &= ~mask;
if (*cp++ != ' ')
SCREWUP("mode not delimited");
- for (size = 0; isdigit((unsigned char)*cp);)
- size = size * 10 + (*cp++ - '0');
- if (*cp++ != ' ')
+ if (!isdigit((unsigned char)*cp))
+ SCREWUP("size not present");
+ ull = strtoull(cp, &cp, 10);
+ if (!cp || *cp++ != ' ')
SCREWUP("size not delimited");
- if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) {
+ if (TYPE_OVERFLOW(off_t, ull))
+ SCREWUP("size out of range");
+ size = (off_t)ull;
+
+ if (*cp == '\0' || strchr(cp, '/') != NULL ||
+ strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {
run_err("error: unexpected filename: %s", cp);
exit(1);
}
+ if (npatterns > 0) {
+ for (n = 0; n < npatterns; n++) {
+ if (fnmatch(patterns[n], cp, 0) == 0)
+ break;
+ }
+ if (n >= npatterns)
+ SCREWUP("filename does not match request");
+ }
if (targisdir) {
static char *namebuf;
static size_t cursize;
@@ -1069,16 +1420,14 @@ sink(int argc, char **argv)
/* Handle copying from a read-only
directory */
mod_flag = 1;
- if (mkdir(np, mode | S_IRWXU) < 0)
+ if (mkdir(np, mode | S_IRWXU) == -1)
goto bad;
}
vect[0] = xstrdup(np);
- sink(1, vect);
+ sink(1, vect, src);
if (setimes) {
setimes = 0;
- if (utimes(vect[0], tv) < 0)
- run_err("%s: set times: %s",
- vect[0], strerror(errno));
+ (void) utimes(vect[0], tv);
}
if (mod_flag)
(void) chmod(vect[0], mode);
@@ -1087,7 +1436,7 @@ sink(int argc, char **argv)
}
omode = mode;
mode |= S_IWUSR;
- if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
+ if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) {
bad: run_err("%s: %s", np, strerror(errno));
continue;
}
@@ -1097,8 +1446,13 @@ bad: run_err("%s: %s", np, strerror(errno));
continue;
}
cp = bp->buf;
- wrerr = NO;
+ wrerr = 0;
+ /*
+ * NB. do not use run_err() unless immediately followed by
+ * exit() below as it may send a spurious reply that might
+ * desyncronise us from the peer. Use note_err() instead.
+ */
statbytes = 0;
if (showprogress)
start_progress_meter(curfile, size, &statbytes);
@@ -1123,11 +1477,12 @@ bad: run_err("%s: %s", np, strerror(errno));
if (count == bp->cnt) {
/* Keep reading so we stay sync'd up. */
- if (wrerr == NO) {
+ if (!wrerr) {
if (atomicio(vwrite, ofd, bp->buf,
count) != count) {
- wrerr = YES;
- wrerrno = errno;
+ note_err("%s: %s", np,
+ strerror(errno));
+ wrerr = 1;
}
}
count = 0;
@@ -1135,18 +1490,14 @@ bad: run_err("%s: %s", np, strerror(errno));
}
}
unset_nonblock(remin);
- if (showprogress)
- stop_progress_meter();
- if (count != 0 && wrerr == NO &&
+ if (count != 0 && !wrerr &&
atomicio(vwrite, ofd, bp->buf, count) != count) {
- wrerr = YES;
- wrerrno = errno;
- }
- if (wrerr == NO && (!exists || S_ISREG(stb.st_mode)) &&
- ftruncate(ofd, size) != 0) {
- run_err("%s: truncate: %s", np, strerror(errno));
- wrerr = DISPLAYED;
+ note_err("%s: %s", np, strerror(errno));
+ wrerr = 1;
}
+ if (!wrerr && (!exists || S_ISREG(stb.st_mode)) &&
+ ftruncate(ofd, size) != 0)
+ note_err("%s: truncate: %s", np, strerror(errno));
if (pflag) {
if (exists || omode != mode)
#ifdef HAVE_FCHMOD
@@ -1154,9 +1505,8 @@ bad: run_err("%s: %s", np, strerror(errno));
#else /* HAVE_FCHMOD */
if (chmod(np, omode)) {
#endif /* HAVE_FCHMOD */
- run_err("%s: set mode: %s",
+ note_err("%s: set mode: %s",
np, strerror(errno));
- wrerr = DISPLAYED;
}
} else {
if (!exists && omode != mode)
@@ -1165,36 +1515,35 @@ bad: run_err("%s: %s", np, strerror(errno));
#else /* HAVE_FCHMOD */
if (chmod(np, omode & ~mask)) {
#endif /* HAVE_FCHMOD */
- run_err("%s: set mode: %s",
+ note_err("%s: set mode: %s",
np, strerror(errno));
- wrerr = DISPLAYED;
}
}
- if (close(ofd) == -1) {
- wrerr = YES;
- wrerrno = errno;
- }
+ if (close(ofd) == -1)
+ note_err(np, "%s: close: %s", np, strerror(errno));
(void) response();
- if (setimes && wrerr == NO) {
+ if (showprogress)
+ stop_progress_meter();
+ if (setimes && !wrerr) {
setimes = 0;
- if (utimes(np, tv) < 0) {
- run_err("%s: set times: %s",
+ if (utimes(np, tv) == -1) {
+ note_err("%s: set times: %s",
np, strerror(errno));
- wrerr = DISPLAYED;
}
}
- switch (wrerr) {
- case YES:
- run_err("%s: %s", np, strerror(wrerrno));
- break;
- case NO:
+ /* If no error was noted then signal success for this file */
+ if (note_err(NULL) == 0)
(void) atomicio(vwrite, remout, "", 1);
- break;
- case DISPLAYED:
- break;
- }
}
+done:
+ for (n = 0; n < npatterns; n++)
+ free(patterns[n]);
+ free(patterns);
+ return;
screwup:
+ for (n = 0; n < npatterns; n++)
+ free(patterns[n]);
+ free(patterns);
run_err("protocol error: %s", why);
exit(1);
}
@@ -1202,7 +1551,7 @@ screwup:
int
response(void)
{
- char ch, *cp, resp, rbuf[2048];
+ char ch, *cp, resp, rbuf[2048], visbuf[2048];
if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp))
lostconn(0);
@@ -1222,8 +1571,13 @@ response(void)
*cp++ = ch;
} while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');
- if (!iamremote)
- (void) atomicio(vwrite, STDERR_FILENO, rbuf, cp - rbuf);
+ if (!iamremote) {
+ cp[-1] = '\0';
+ (void) snmprintf(visbuf, sizeof(visbuf),
+ NULL, "%s\n", rbuf);
+ (void) atomicio(vwrite, STDERR_FILENO,
+ visbuf, strlen(visbuf));
+ }
++errs;
if (resp == 1)
return (-1);
@@ -1236,9 +1590,9 @@ void
usage(void)
{
(void) fprintf(stderr,
- "usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
- " [-l limit] [-o ssh_option] [-P port] [-S program]\n"
- " [[user@]host1:]file1 ... [[user@]host2:]file2\n");
+ "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");
exit(1);
}
@@ -1261,12 +1615,44 @@ run_err(const char *fmt,...)
if (!iamremote) {
va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
+ vfmprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
}
}
+/*
+ * Notes a sink error for sending at the end of a file transfer. Returns 0 if
+ * no error has been noted or -1 otherwise. Use note_err(NULL) to flush
+ * any active error at the end of the transfer.
+ */
+int
+note_err(const char *fmt, ...)
+{
+ static char *emsg;
+ va_list ap;
+
+ /* Replay any previously-noted error */
+ if (fmt == NULL) {
+ if (emsg == NULL)
+ return 0;
+ run_err("%s", emsg);
+ free(emsg);
+ emsg = NULL;
+ return -1;
+ }
+
+ errs++;
+ /* Prefer first-noted error */
+ if (emsg != NULL)
+ return -1;
+
+ va_start(ap, fmt);
+ vasnmprintf(&emsg, INT_MAX, NULL, fmt, ap);
+ va_end(ap);
+ return -1;
+}
+
void
verifydir(char *cp)
{
@@ -1307,7 +1693,7 @@ okname(char *cp0)
} while (*++cp);
return (1);
-bad: fprintf(stderr, "%s: invalid user name\n", cp0);
+bad: fmprintf(stderr, "%s: invalid user name\n", cp0);
return (0);
}
@@ -1318,11 +1704,11 @@ allocbuf(BUF *bp, int fd, int blksize)
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
struct stat stb;
- if (fstat(fd, &stb) < 0) {
+ if (fstat(fd, &stb) == -1) {
run_err("fstat: %s", strerror(errno));
return (0);
}
- size = roundup(stb.st_blksize, blksize);
+ size = ROUNDUP(stb.st_blksize, blksize);
if (size == 0)
size = blksize;
#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */
@@ -1330,11 +1716,7 @@ allocbuf(BUF *bp, int fd, int blksize)
#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
if (bp->cnt >= size)
return (bp);
- if (bp->buf == NULL)
- bp->buf = xmalloc(size);
- else
- bp->buf = xrealloc(bp->buf, 1, size);
- memset(bp->buf, 0, size);
+ bp->buf = xrecallocarray(bp->buf, bp->cnt, size, 1);
bp->cnt = size;
return (bp);
}
diff --git a/servconf.c b/servconf.c
index d75239f9..f1850312 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: servconf.c,v 1.260 2015/02/02 01:57:44 deraadt Exp $ */
+/* $OpenBSD: servconf.c,v 1.363 2020/04/17 03:30:05 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -15,10 +15,16 @@
#include <sys/types.h>
#include <sys/socket.h>
+#ifdef __OpenBSD__
+#include <sys/sysctl.h>
+#endif
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
+#ifdef HAVE_NET_ROUTE_H
+#include <net/route.h>
+#endif
#include <ctype.h>
#include <netdb.h>
@@ -34,18 +40,23 @@
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
+#ifdef USE_SYSTEM_GLOB
+# include <glob.h>
+#else
+# include "openbsd-compat/glob.h"
+#endif
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
#include "log.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "pathnames.h"
#include "cipher.h"
-#include "key.h"
+#include "sshkey.h"
#include "kex.h"
#include "mac.h"
#include "match.h"
@@ -53,21 +64,27 @@
#include "groupaccess.h"
#include "canohost.h"
#include "packet.h"
+#include "ssherr.h"
#include "hostfile.h"
#include "auth.h"
#include "myproposal.h"
#include "digest.h"
-#ifdef ANDROID
+#if defined(ANDROID)
#include <cutils/properties.h>
#endif
-static void add_listen_addr(ServerOptions *, char *, int);
-static void add_one_listen_addr(ServerOptions *, char *, int);
+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,
+ struct connection_info *connectinfo, int flags, int *activep, int depth);
/* Use of privilege separation or not */
extern int use_privsep;
-extern Buffer cfg;
+extern struct sshbuf *cfg;
/* Initializes the server options to their default values. */
@@ -82,15 +99,17 @@ initialize_server_options(ServerOptions *options)
/* Standard Options */
options->num_ports = 0;
options->ports_from_cmdline = 0;
+ options->queued_listen_addrs = NULL;
+ options->num_queued_listens = 0;
options->listen_addrs = NULL;
+ options->num_listen_addrs = 0;
options->address_family = -1;
+ options->routing_domain = NULL;
options->num_host_key_files = 0;
options->num_host_cert_files = 0;
options->host_key_agent = NULL;
options->pid_file = NULL;
- options->server_key_bits = -1;
options->login_grace_time = -1;
- options->key_regeneration_time = -1;
options->permit_root_login = PERMIT_NOT_SET;
options->ignore_rhosts = -1;
options->ignore_user_known_hosts = -1;
@@ -106,12 +125,12 @@ 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->rhosts_rsa_authentication = -1;
options->hostbased_authentication = -1;
options->hostbased_uses_name_from_packet_only = -1;
options->hostbased_key_types = NULL;
- options->rsa_authentication = -1;
+ options->hostkeyalgorithms = NULL;
options->pubkey_authentication = -1;
+ options->pubkey_auth_options = -1;
options->pubkey_key_types = NULL;
options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1;
@@ -119,12 +138,13 @@ initialize_server_options(ServerOptions *options)
options->kerberos_get_afs_token = -1;
options->gss_authentication=-1;
options->gss_cleanup_creds = -1;
+ options->gss_strict_acceptor = -1;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->challenge_response_authentication = -1;
options->permit_empty_passwd = -1;
options->permit_user_env = -1;
- options->use_login = -1;
+ options->permit_user_env_whitelist = NULL;
options->compression = -1;
options->rekey_limit = -1;
options->rekey_interval = -1;
@@ -138,7 +158,7 @@ initialize_server_options(ServerOptions *options)
options->ciphers = NULL;
options->macs = NULL;
options->kex_algorithms = NULL;
- options->protocol = SSH_PROTO_UNKNOWN;
+ options->ca_sign_algorithms = NULL;
options->fwd_opts.gateway_ports = -1;
options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
options->fwd_opts.streamlocal_bind_unlink = -1;
@@ -154,19 +174,26 @@ initialize_server_options(ServerOptions *options)
options->client_alive_count_max = -1;
options->num_authkeys_files = 0;
options->num_accept_env = 0;
+ options->num_setenv = 0;
options->permit_tun = -1;
- options->num_permitted_opens = -1;
+ options->permitted_opens = NULL;
+ options->permitted_listens = NULL;
options->adm_forced_command = NULL;
options->chroot_directory = NULL;
options->authorized_keys_command = NULL;
options->authorized_keys_command_user = NULL;
options->revoked_keys_file = NULL;
+ options->sk_provider = NULL;
options->trusted_user_ca_keys = NULL;
options->authorized_principals_file = NULL;
+ options->authorized_principals_command = NULL;
+ options->authorized_principals_command_user = NULL;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
options->version_addendum = NULL;
options->fingerprint_hash = -1;
+ options->disable_forwarding = -1;
+ options->expose_userauth_info = -1;
}
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
@@ -176,51 +203,136 @@ option_clear_or_none(const char *o)
return o == NULL || strcasecmp(o, "none") == 0;
}
+static void
+assemble_algorithms(ServerOptions *o)
+{
+ char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
+ char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
+ int r;
+
+ all_cipher = cipher_alg_list(',', 0);
+ all_mac = mac_alg_list(',');
+ all_kex = kex_alg_list(',');
+ all_key = sshkey_alg_list(0, 0, 1, ',');
+ all_sig = sshkey_alg_list(0, 1, 1, ',');
+ /* remove unsupported algos from default lists */
+ def_cipher = match_filter_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);
+#define ASSEMBLE(what, defaults, all) \
+ do { \
+ if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
+ fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \
+ } while (0)
+ ASSEMBLE(ciphers, 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(ca_sign_algorithms, def_sig, all_sig);
+#undef ASSEMBLE
+ free(all_cipher);
+ free(all_mac);
+ free(all_kex);
+ free(all_key);
+ free(all_sig);
+ free(def_cipher);
+ free(def_mac);
+ free(def_kex);
+ free(def_key);
+ free(def_sig);
+}
+
+static 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",
+ &options->host_key_files, &options->host_key_file_userprovided,
+ &options->num_host_key_files, apath, userprovided);
+ free(apath);
+}
+
+void
+servconf_add_hostcert(const char *file, const int line,
+ ServerOptions *options, const char *path)
+{
+ char *apath = derelativise_path(path);
+
+ array_append(file, line, "HostCertificate",
+ &options->host_cert_files, &options->num_host_cert_files, apath);
+ free(apath);
+}
+
void
fill_default_server_options(ServerOptions *options)
{
- int i;
+ u_int i;
/* Portable-specific options */
if (options->use_pam == -1)
options->use_pam = 0;
/* Standard Options */
- if (options->protocol == SSH_PROTO_UNKNOWN)
- options->protocol = SSH_PROTO_2;
if (options->num_host_key_files == 0) {
/* fill default hostkeys for protocols */
- if (options->protocol & SSH_PROTO_1)
- options->host_key_files[options->num_host_key_files++] =
- _PATH_HOST_KEY_FILE;
- if (options->protocol & SSH_PROTO_2) {
- options->host_key_files[options->num_host_key_files++] =
- _PATH_HOST_RSA_KEY_FILE;
- options->host_key_files[options->num_host_key_files++] =
- _PATH_HOST_DSA_KEY_FILE;
+ servconf_add_hostkey("[default]", 0, options,
+ _PATH_HOST_RSA_KEY_FILE, 0);
#ifdef OPENSSL_HAS_ECC
- options->host_key_files[options->num_host_key_files++] =
- _PATH_HOST_ECDSA_KEY_FILE;
+ servconf_add_hostkey("[default]", 0, options,
+ _PATH_HOST_ECDSA_KEY_FILE, 0);
#endif
- options->host_key_files[options->num_host_key_files++] =
- _PATH_HOST_ED25519_KEY_FILE;
- }
+ servconf_add_hostkey("[default]", 0, options,
+ _PATH_HOST_ED25519_KEY_FILE, 0);
+#ifdef WITH_XMSS
+ servconf_add_hostkey("[default]", 0, options,
+ _PATH_HOST_XMSS_KEY_FILE, 0);
+#endif /* WITH_XMSS */
}
/* No certificates by default */
if (options->num_ports == 0)
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
+ if (options->address_family == -1)
+ options->address_family = AF_UNSPEC;
if (options->listen_addrs == NULL)
- add_listen_addr(options, NULL, 0);
+ add_listen_addr(options, NULL, NULL, 0);
if (options->pid_file == NULL)
options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE);
- if (options->server_key_bits == -1)
- options->server_key_bits = 1024;
if (options->login_grace_time == -1)
options->login_grace_time = 120;
- if (options->key_regeneration_time == -1)
- options->key_regeneration_time = 3600;
if (options->permit_root_login == PERMIT_NOT_SET)
- options->permit_root_login = PERMIT_YES;
+ options->permit_root_login = PERMIT_NO_PASSWD;
if (options->ignore_rhosts == -1)
options->ignore_rhosts = 1;
if (options->ignore_user_known_hosts == -1)
@@ -249,20 +361,14 @@ fill_default_server_options(ServerOptions *options)
options->log_facility = SYSLOG_FACILITY_AUTH;
if (options->log_level == SYSLOG_LEVEL_NOT_SET)
options->log_level = SYSLOG_LEVEL_INFO;
- if (options->rhosts_rsa_authentication == -1)
- options->rhosts_rsa_authentication = 0;
if (options->hostbased_authentication == -1)
options->hostbased_authentication = 0;
if (options->hostbased_uses_name_from_packet_only == -1)
options->hostbased_uses_name_from_packet_only = 0;
- if (options->hostbased_key_types == NULL)
- options->hostbased_key_types = xstrdup("*");
- if (options->rsa_authentication == -1)
- options->rsa_authentication = 1;
if (options->pubkey_authentication == -1)
options->pubkey_authentication = 1;
- if (options->pubkey_key_types == NULL)
- options->pubkey_key_types = xstrdup("*");
+ if (options->pubkey_auth_options == -1)
+ options->pubkey_auth_options = 0;
if (options->kerberos_authentication == -1)
options->kerberos_authentication = 0;
if (options->kerberos_or_local_passwd == -1)
@@ -275,6 +381,8 @@ fill_default_server_options(ServerOptions *options)
options->gss_authentication = 0;
if (options->gss_cleanup_creds == -1)
options->gss_cleanup_creds = 1;
+ if (options->gss_strict_acceptor == -1)
+ options->gss_strict_acceptor = 1;
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
@@ -283,12 +391,17 @@ fill_default_server_options(ServerOptions *options)
options->challenge_response_authentication = 1;
if (options->permit_empty_passwd == -1)
options->permit_empty_passwd = 0;
- if (options->permit_user_env == -1)
+ if (options->permit_user_env == -1) {
options->permit_user_env = 0;
- if (options->use_login == -1)
- options->use_login = 0;
+ options->permit_user_env_whitelist = NULL;
+ }
if (options->compression == -1)
+#ifdef WITH_ZLIB
options->compression = COMP_DELAYED;
+#else
+ options->compression = COMP_NONE;
+#endif
+
if (options->rekey_limit == -1)
options->rekey_limit = 0;
if (options->rekey_interval == -1)
@@ -318,17 +431,21 @@ 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) {
- options->authorized_keys_files[options->num_authkeys_files++] =
- xstrdup(_PATH_SSH_USER_PERMITTED_KEYS);
- options->authorized_keys_files[options->num_authkeys_files++] =
- xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2);
+ array_append("[default]", 0, "AuthorizedKeysFiles",
+ &options->authorized_keys_files,
+ &options->num_authkeys_files,
+ _PATH_SSH_USER_PERMITTED_KEYS);
+ array_append("[default]", 0, "AuthorizedKeysFiles",
+ &options->authorized_keys_files,
+ &options->num_authkeys_files,
+ _PATH_SSH_USER_PERMITTED_KEYS2);
}
if (options->permit_tun == -1)
options->permit_tun = SSH_TUNMODE_NO;
if (options->ip_qos_interactive == -1)
- options->ip_qos_interactive = IPTOS_LOWDELAY;
+ options->ip_qos_interactive = IPTOS_DSCP_AF21;
if (options->ip_qos_bulk == -1)
- options->ip_qos_bulk = IPTOS_THROUGHPUT;
+ options->ip_qos_bulk = IPTOS_DSCP_CS1;
if (options->version_addendum == NULL)
options->version_addendum = xstrdup("");
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
@@ -337,9 +454,18 @@ fill_default_server_options(ServerOptions *options)
options->fwd_opts.streamlocal_bind_unlink = 0;
if (options->fingerprint_hash == -1)
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
- /* Turn privilege separation on by default */
+ if (options->disable_forwarding == -1)
+ options->disable_forwarding = 0;
+ if (options->expose_userauth_info == -1)
+ options->expose_userauth_info = 0;
+ if (options->sk_provider == NULL)
+ options->sk_provider = xstrdup("internal");
+
+ assemble_algorithms(options);
+
+ /* Turn privilege separation and sandboxing on by default */
if (use_privsep == -1)
- use_privsep = PRIVSEP_NOSANDBOX;
+ use_privsep = PRIVSEP_ON;
#define CLEAR_ON_NONE(v) \
do { \
@@ -353,12 +479,26 @@ fill_default_server_options(ServerOptions *options)
CLEAR_ON_NONE(options->banner);
CLEAR_ON_NONE(options->trusted_user_ca_keys);
CLEAR_ON_NONE(options->revoked_keys_file);
+ CLEAR_ON_NONE(options->sk_provider);
+ CLEAR_ON_NONE(options->authorized_principals_file);
+ CLEAR_ON_NONE(options->adm_forced_command);
+ CLEAR_ON_NONE(options->chroot_directory);
+ CLEAR_ON_NONE(options->routing_domain);
+ CLEAR_ON_NONE(options->host_key_agent);
for (i = 0; i < options->num_host_key_files; i++)
CLEAR_ON_NONE(options->host_key_files[i]);
for (i = 0; i < options->num_host_cert_files; i++)
CLEAR_ON_NONE(options->host_cert_files[i]);
#undef CLEAR_ON_NONE
+ /* Similar handling for AuthenticationMethods=any */
+ if (options->num_auth_methods == 1 &&
+ strcmp(options->auth_methods[0], "any") == 0) {
+ free(options->auth_methods[0]);
+ options->auth_methods[0] = NULL;
+ options->num_auth_methods = 0;
+ }
+
#ifndef HAVE_MMAP
if (use_privsep && options->compression == 1) {
error("This platform does not support both privilege "
@@ -367,7 +507,6 @@ fill_default_server_options(ServerOptions *options)
options->compression = 0;
}
#endif
-
}
/* Keyword tokens. */
@@ -376,41 +515,45 @@ typedef enum {
/* Portable-specific options */
sUsePAM,
/* Standard Options */
- sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime,
- sKeyRegenerationTime, sPermitRootLogin, sLogFacility, sLogLevel,
+ sPort, sHostKeyFile, sLoginGraceTime,
+ sPermitRootLogin, sLogFacility, sLogLevel,
sRhostsRSAAuthentication, sRSAAuthentication,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
- sKerberosGetAFSToken,
- sKerberosTgtPassing, sChallengeResponseAuthentication,
+ sKerberosGetAFSToken, sChallengeResponseAuthentication,
sPasswordAuthentication, sKbdInteractiveAuthentication,
sListenAddress, sAddressFamily,
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive,
- sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
+ sPermitUserEnvironment, sAllowTcpForwarding, sCompression,
sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
- sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
+ sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes,
sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,
sBanner, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
+ sHostKeyAlgorithms,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
- sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
- sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
+ sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
+ sAcceptEnv, sSetEnv, sPermitTunnel,
+ sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
- sHostCertificate,
+ sHostCertificate, sInclude,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
- sKexAlgorithms, sIPQoS, sVersionAddendum,
+ sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
+ sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum,
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
sStreamLocalBindMask, sStreamLocalBindUnlink,
- sAllowStreamLocalForwarding, sFingerprintHash,
- sDeprecated, sUnsupported
+ sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
+ sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
+ sDeprecated, sIgnore, sUnsupported
} ServerOpCodes;
-#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
-#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
-#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
+#define SSHCFG_GLOBAL 0x01 /* allowed in main section of config */
+#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
+#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
+#define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */
/* Textual representation of the tokens. */
static struct {
@@ -431,20 +574,22 @@ static struct {
{ "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
{ "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL },
{ "pidfile", sPidFile, SSHCFG_GLOBAL },
- { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
+ { "serverkeybits", sDeprecated, SSHCFG_GLOBAL },
{ "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
- { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
+ { "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL },
{ "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
{ "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
- { "loglevel", sLogLevel, SSHCFG_GLOBAL },
+ { "loglevel", sLogLevel, SSHCFG_ALL },
{ "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
- { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
+ { "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL },
{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
{ "hostbasedacceptedkeytypes", sHostbasedAcceptedKeyTypes, SSHCFG_ALL },
- { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
+ { "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL },
+ { "rsaauthentication", sDeprecated, SSHCFG_ALL },
{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
{ "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL },
+ { "pubkeyauthoptions", sPubkeyAuthOptions, SSHCFG_ALL },
{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
#ifdef KRB5
{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
@@ -466,20 +611,26 @@ static struct {
#ifdef GSSAPI
{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
+ { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
#else
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
+ { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
#endif
{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
- { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
+ { "skeyauthentication", sDeprecated, SSHCFG_GLOBAL },
{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
{ "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
{ "printmotd", sPrintMotd, SSHCFG_GLOBAL },
+#ifdef DISABLE_LASTLOG
+ { "printlastlog", sUnsupported, SSHCFG_GLOBAL },
+#else
{ "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
- { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
+#endif
+ { "ignorerhosts", sIgnoreRhosts, SSHCFG_ALL },
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
{ "x11forwarding", sX11Forwarding, SSHCFG_ALL },
{ "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
@@ -488,7 +639,7 @@ static struct {
{ "strictmodes", sStrictModes, SSHCFG_GLOBAL },
{ "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
{ "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
- { "uselogin", sUseLogin, SSHCFG_GLOBAL },
+ { "uselogin", sDeprecated, SSHCFG_GLOBAL },
{ "compression", sCompression, SSHCFG_GLOBAL },
{ "rekeylimit", sRekeyLimit, SSHCFG_ALL },
{ "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
@@ -501,7 +652,7 @@ static struct {
{ "denygroups", sDenyGroups, SSHCFG_ALL },
{ "ciphers", sCiphers, SSHCFG_GLOBAL },
{ "macs", sMacs, SSHCFG_GLOBAL },
- { "protocol", sProtocol, SSHCFG_GLOBAL },
+ { "protocol", sIgnore, SSHCFG_GLOBAL },
{ "gatewayports", sGatewayPorts, SSHCFG_ALL },
{ "subsystem", sSubsystem, SSHCFG_GLOBAL },
{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
@@ -511,17 +662,19 @@ static struct {
{ "usedns", sUseDNS, SSHCFG_GLOBAL },
{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
- { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
- { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
+ { "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL },
+ { "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL },
{ "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
{ "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
- { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
+ { "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL},
{ "acceptenv", sAcceptEnv, SSHCFG_ALL },
+ { "setenv", sSetEnv, SSHCFG_ALL },
{ "permittunnel", sPermitTunnel, SSHCFG_ALL },
{ "permittty", sPermitTTY, SSHCFG_ALL },
{ "permituserrc", sPermitUserRC, SSHCFG_ALL },
{ "match", sMatch, SSHCFG_ALL },
{ "permitopen", sPermitOpen, SSHCFG_ALL },
+ { "permitlisten", sPermitListen, SSHCFG_ALL },
{ "forcecommand", sForceCommand, SSHCFG_ALL },
{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
@@ -529,15 +682,23 @@ static struct {
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
+ { "include", sInclude, SSHCFG_ALL },
{ "ipqos", sIPQoS, SSHCFG_ALL },
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
+ { "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL },
+ { "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL },
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
+ { "disableforwarding", sDisableForwarding, SSHCFG_ALL },
+ { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
+ { "rdomain", sRDomain, SSHCFG_ALL },
+ { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
+ { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
{ NULL, sBadOption, 0 }
};
@@ -552,6 +713,20 @@ static struct {
{ -1, NULL }
};
+/* Returns an opcode name from its number */
+
+static const char *
+lookup_opcode_name(ServerOpCodes code)
+{
+ u_int i;
+
+ for (i = 0; keywords[i].name != NULL; i++)
+ if (keywords[i].opcode == code)
+ return(keywords[i].name);
+ return "UNKNOWN";
+}
+
+
/*
* Returns the number of the token pointed to by cp or sBadOption.
*/
@@ -581,7 +756,7 @@ derelativise_path(const char *path)
if (strcasecmp(path, "none") == 0)
return xstrdup("none");
expanded = tilde_expand_filename(path, getuid());
- if (*expanded == '/')
+ if (path_absolute(expanded))
return expanded;
if (getcwd(cwd, sizeof(cwd)) == NULL)
fatal("%s: getcwd: %s", __func__, strerror(errno));
@@ -591,27 +766,51 @@ derelativise_path(const char *path)
}
static void
-add_listen_addr(ServerOptions *options, char *addr, int port)
+add_listen_addr(ServerOptions *options, const char *addr,
+ const char *rdomain, int port)
{
u_int i;
- if (options->num_ports == 0)
- options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
- if (options->address_family == -1)
- options->address_family = AF_UNSPEC;
- if (port == 0)
- for (i = 0; i < options->num_ports; i++)
- add_one_listen_addr(options, addr, options->ports[i]);
- else
- add_one_listen_addr(options, addr, port);
+ if (port > 0)
+ add_one_listen_addr(options, addr, rdomain, port);
+ else {
+ for (i = 0; i < options->num_ports; i++) {
+ add_one_listen_addr(options, addr, rdomain,
+ options->ports[i]);
+ }
+ }
}
static void
-add_one_listen_addr(ServerOptions *options, char *addr, int port)
+add_one_listen_addr(ServerOptions *options, const char *addr,
+ const char *rdomain, int port)
{
struct addrinfo hints, *ai, *aitop;
char strport[NI_MAXSERV];
int gaierr;
+ u_int i;
+
+ /* Find listen_addrs entry for this rdomain */
+ for (i = 0; i < options->num_listen_addrs; i++) {
+ if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL)
+ break;
+ if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL)
+ continue;
+ if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0)
+ break;
+ }
+ if (i >= options->num_listen_addrs) {
+ /* No entry for this rdomain; allocate one */
+ if (i >= INT_MAX)
+ fatal("%s: too many listen addresses", __func__);
+ options->listen_addrs = xrecallocarray(options->listen_addrs,
+ options->num_listen_addrs, options->num_listen_addrs + 1,
+ sizeof(*options->listen_addrs));
+ i = options->num_listen_addrs++;
+ if (rdomain != NULL)
+ options->listen_addrs[i].rdomain = xstrdup(rdomain);
+ }
+ /* options->listen_addrs[i] points to the addresses for this rdomain */
memset(&hints, 0, sizeof(hints));
hints.ai_family = options->address_family;
@@ -624,21 +823,158 @@ add_one_listen_addr(ServerOptions *options, char *addr, int port)
ssh_gai_strerror(gaierr));
for (ai = aitop; ai->ai_next; ai = ai->ai_next)
;
- ai->ai_next = options->listen_addrs;
- options->listen_addrs = aitop;
+ ai->ai_next = options->listen_addrs[i].addrs;
+ options->listen_addrs[i].addrs = aitop;
+}
+
+/* Returns nonzero if the routing domain name is valid */
+static int
+valid_rdomain(const char *name)
+{
+#if defined(HAVE_SYS_VALID_RDOMAIN)
+ return sys_valid_rdomain(name);
+#elif defined(__OpenBSD__)
+ const char *errstr;
+ long long num;
+ struct rt_tableinfo info;
+ int mib[6];
+ size_t miblen = sizeof(mib);
+
+ if (name == NULL)
+ return 1;
+
+ num = strtonum(name, 0, 255, &errstr);
+ if (errstr != NULL)
+ return 0;
+
+ /* Check whether the table actually exists */
+ memset(mib, 0, sizeof(mib));
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[4] = NET_RT_TABLE;
+ mib[5] = (int)num;
+ if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1)
+ return 0;
+
+ return 1;
+#else /* defined(__OpenBSD__) */
+ error("Routing domains are not supported on this platform");
+ return 0;
+#endif
+}
+
+/*
+ * Queue a ListenAddress to be processed once we have all of the Ports
+ * and AddressFamily options.
+ */
+static void
+queue_listen_addr(ServerOptions *options, const char *addr,
+ const char *rdomain, int port)
+{
+ struct queued_listenaddr *qla;
+
+ options->queued_listen_addrs = xrecallocarray(
+ options->queued_listen_addrs,
+ options->num_queued_listens, options->num_queued_listens + 1,
+ sizeof(*options->queued_listen_addrs));
+ qla = &options->queued_listen_addrs[options->num_queued_listens++];
+ qla->addr = xstrdup(addr);
+ qla->port = port;
+ qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain);
+}
+
+/*
+ * Process queued (text) ListenAddress entries.
+ */
+static void
+process_queued_listen_addrs(ServerOptions *options)
+{
+ u_int i;
+ struct queued_listenaddr *qla;
+
+ if (options->num_ports == 0)
+ options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
+ if (options->address_family == -1)
+ options->address_family = AF_UNSPEC;
+
+ for (i = 0; i < options->num_queued_listens; i++) {
+ qla = &options->queued_listen_addrs[i];
+ add_listen_addr(options, qla->addr, qla->rdomain, qla->port);
+ free(qla->addr);
+ free(qla->rdomain);
+ }
+ free(options->queued_listen_addrs);
+ options->queued_listen_addrs = NULL;
+ options->num_queued_listens = 0;
+}
+
+/*
+ * Inform channels layer of permitopen options for a single forwarding
+ * direction (local/remote).
+ */
+static void
+process_permitopen_list(struct ssh *ssh, ServerOpCodes opcode,
+ char **opens, u_int num_opens)
+{
+ u_int i;
+ int port;
+ char *host, *arg, *oarg, ch;
+ int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE;
+ const char *what = lookup_opcode_name(opcode);
+
+ channel_clear_permission(ssh, FORWARD_ADM, where);
+ if (num_opens == 0)
+ return; /* permit any */
+
+ /* handle keywords: "any" / "none" */
+ if (num_opens == 1 && strcmp(opens[0], "any") == 0)
+ return;
+ if (num_opens == 1 && strcmp(opens[0], "none") == 0) {
+ channel_disable_admin(ssh, where);
+ return;
+ }
+ /* Otherwise treat it as a list of permitted host:port */
+ for (i = 0; i < num_opens; i++) {
+ oarg = arg = xstrdup(opens[i]);
+ ch = '\0';
+ host = hpdelim2(&arg, &ch);
+ if (host == NULL || ch == '/')
+ fatal("%s: missing host in %s", __func__, what);
+ host = cleanhostname(host);
+ if (arg == NULL || ((port = permitopen_port(arg)) < 0))
+ fatal("%s: bad port number in %s", __func__, what);
+ /* Send it to channels layer */
+ channel_add_permission(ssh, FORWARD_ADM,
+ where, host, port);
+ free(oarg);
+ }
+}
+
+/*
+ * Inform channels layer of permitopen options from configuration.
+ */
+void
+process_permitopen(struct ssh *ssh, ServerOptions *options)
+{
+ process_permitopen_list(ssh, sPermitOpen,
+ options->permitted_opens, options->num_permitted_opens);
+ process_permitopen_list(ssh, sPermitListen,
+ options->permitted_listens,
+ options->num_permitted_listens);
}
struct connection_info *
-get_connection_info(int populate, int use_dns)
+get_connection_info(struct ssh *ssh, int populate, int use_dns)
{
static struct connection_info ci;
- if (!populate)
+ if (ssh == NULL || !populate)
return &ci;
- ci.host = get_canonical_hostname(use_dns);
- ci.address = get_remote_ipaddr();
- ci.laddress = get_local_ipaddr(packet_get_connection_in());
- ci.lport = get_local_port();
+ ci.host = auth_get_canonical_hostname(ssh, use_dns);
+ ci.address = ssh_remote_ipaddr(ssh);
+ ci.laddress = ssh_local_ipaddr(ssh);
+ ci.lport = ssh_local_port(ssh);
+ ci.rdomain = ssh_packet_rdomain_in(ssh);
return &ci;
}
@@ -658,7 +994,7 @@ get_connection_info(int populate, int use_dns)
* options set are copied into the main server config.
*
* Potential additions/improvements:
- * - Add Match support for pre-kex directives, eg Protocol, Ciphers.
+ * - Add Match support for pre-kex directives, eg. Ciphers.
*
* - Add a Tag directive (idea from David Leonard) ala pf, eg:
* Match Address 192.168.0.*
@@ -703,6 +1039,13 @@ out:
return result;
}
+static void
+match_test_missing_fatal(const char *criteria, const char *attrib)
+{
+ fatal("'Match %s' in configuration but '%s' not in connection "
+ "test specification.", criteria, attrib);
+}
+
/*
* All of the attributes on a single Match line are ANDed together, so we need
* to check every attribute and set the result to zero if any attribute does
@@ -713,7 +1056,6 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
{
int result = 1, attributes = 0, port;
char *arg, *attrib, *cp = *condition;
- size_t len;
if (ci == NULL)
debug3("checking syntax for 'Match %s'", cp);
@@ -740,22 +1082,25 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
error("Missing Match criteria for %s", attrib);
return -1;
}
- len = strlen(arg);
if (strcasecmp(attrib, "user") == 0) {
- if (ci == NULL || ci->user == NULL) {
+ if (ci == NULL || (ci->test && ci->user == NULL)) {
result = 0;
continue;
}
- if (match_pattern_list(ci->user, arg, len, 0) != 1)
+ if (ci->user == NULL)
+ match_test_missing_fatal("User", "user");
+ if (match_usergroup_pattern_list(ci->user, arg) != 1)
result = 0;
else
debug("user %.100s matched 'User %.100s' at "
"line %d", ci->user, arg, line);
} else if (strcasecmp(attrib, "group") == 0) {
- if (ci == NULL || ci->user == NULL) {
+ if (ci == NULL || (ci->test && ci->user == NULL)) {
result = 0;
continue;
}
+ if (ci->user == NULL)
+ match_test_missing_fatal("Group", "user");
switch (match_cfg_line_group(arg, line, ci->user)) {
case -1:
return -1;
@@ -763,20 +1108,24 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
result = 0;
}
} else if (strcasecmp(attrib, "host") == 0) {
- if (ci == NULL || ci->host == NULL) {
+ if (ci == NULL || (ci->test && ci->host == NULL)) {
result = 0;
continue;
}
- if (match_hostname(ci->host, arg, len) != 1)
+ if (ci->host == NULL)
+ match_test_missing_fatal("Host", "host");
+ if (match_hostname(ci->host, arg) != 1)
result = 0;
else
debug("connection from %.100s matched 'Host "
"%.100s' at line %d", ci->host, arg, line);
} else if (strcasecmp(attrib, "address") == 0) {
- if (ci == NULL || ci->address == NULL) {
+ if (ci == NULL || (ci->test && ci->address == NULL)) {
result = 0;
continue;
}
+ if (ci->address == NULL)
+ match_test_missing_fatal("Address", "addr");
switch (addr_match_list(ci->address, arg)) {
case 1:
debug("connection from %.100s matched 'Address "
@@ -790,10 +1139,13 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
return -1;
}
} else if (strcasecmp(attrib, "localaddress") == 0){
- if (ci == NULL || ci->laddress == NULL) {
+ if (ci == NULL || (ci->test && ci->laddress == NULL)) {
result = 0;
continue;
}
+ if (ci->laddress == NULL)
+ match_test_missing_fatal("LocalAddress",
+ "laddr");
switch (addr_match_list(ci->laddress, arg)) {
case 1:
debug("connection from %.100s matched "
@@ -813,10 +1165,12 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
arg);
return -1;
}
- if (ci == NULL || ci->lport == 0) {
+ if (ci == NULL || (ci->test && ci->lport == -1)) {
result = 0;
continue;
}
+ if (ci->lport == 0)
+ match_test_missing_fatal("LocalPort", "lport");
/* TODO support port lists */
if (port == ci->lport)
debug("connection from %.100s matched "
@@ -824,6 +1178,18 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
ci->laddress, port, line);
else
result = 0;
+ } else if (strcasecmp(attrib, "rdomain") == 0) {
+ if (ci == NULL || (ci->test && ci->rdomain == NULL)) {
+ result = 0;
+ continue;
+ }
+ if (ci->rdomain == NULL)
+ match_test_missing_fatal("RDomain", "rdomain");
+ if (match_pattern_list(ci->rdomain, arg, 0) != 1)
+ result = 0;
+ else
+ debug("user %.100s matched 'RDomain %.100s' at "
+ "line %d", ci->rdomain, arg, line);
} else {
error("Unsupported Match attribute %s", attrib);
return -1;
@@ -846,6 +1212,17 @@ struct multistate {
char *key;
int value;
};
+static const struct multistate multistate_flag[] = {
+ { "yes", 1 },
+ { "no", 0 },
+ { NULL, -1 }
+};
+static const struct multistate multistate_ignore_rhosts[] = {
+ { "yes", IGNORE_RHOSTS_YES },
+ { "no", IGNORE_RHOSTS_NO },
+ { "shosts-only", IGNORE_RHOSTS_SHOSTS },
+ { NULL, -1 }
+};
static const struct multistate multistate_addressfamily[] = {
{ "inet", AF_INET },
{ "inet6", AF_INET6 },
@@ -854,14 +1231,17 @@ static const struct multistate multistate_addressfamily[] = {
};
static const struct multistate multistate_permitrootlogin[] = {
{ "without-password", PERMIT_NO_PASSWD },
+ { "prohibit-password", PERMIT_NO_PASSWD },
{ "forced-commands-only", PERMIT_FORCED_ONLY },
{ "yes", PERMIT_YES },
{ "no", PERMIT_NO },
{ NULL, -1 }
};
static const struct multistate multistate_compression[] = {
+#ifdef WITH_ZLIB
+ { "yes", COMP_DELAYED },
{ "delayed", COMP_DELAYED },
- { "yes", COMP_ZLIB },
+#endif
{ "no", COMP_NONE },
{ NULL, -1 }
};
@@ -871,13 +1251,6 @@ static const struct multistate multistate_gatewayports[] = {
{ "no", 0 },
{ NULL, -1 }
};
-static const struct multistate multistate_privsep[] = {
- { "yes", PRIVSEP_NOSANDBOX },
- { "sandbox", PRIVSEP_ON },
- { "nosandbox", PRIVSEP_NOSANDBOX },
- { "no", PRIVSEP_OFF },
- { NULL, -1 }
-};
static const struct multistate multistate_tcpfwd[] = {
{ "yes", FORWARD_ALLOW },
{ "all", FORWARD_ALLOW },
@@ -887,20 +1260,33 @@ static const struct multistate multistate_tcpfwd[] = {
{ NULL, -1 }
};
-int
-process_server_config_line(ServerOptions *options, char *line,
+static int
+process_server_config_line_depth(ServerOptions *options, char *line,
const char *filename, int linenum, int *activep,
- struct connection_info *connectinfo)
+ struct connection_info *connectinfo, int inc_flags, int depth,
+ struct include_list *includes)
{
- char *cp, **charptr, *arg, *p;
- int cmdline = 0, *intptr, value, value2, n, port;
+ char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p;
+ int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found;
SyslogFacility *log_facility_ptr;
LogLevel *log_level_ptr;
ServerOpCodes opcode;
- u_int i, flags = 0;
+ u_int i, *uintptr, uvalue, flags = 0;
size_t len;
long long val64;
const struct multistate *multistate_ptr;
+ const char *errstr;
+ struct include_item *item;
+ glob_t gbuf;
+
+ /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
+ if ((len = strlen(line)) == 0)
+ return 0;
+ for (len--; len > 0; len--) {
+ if (strchr(WHITESPACE "\f", line[len]) == NULL)
+ break;
+ line[len] = '\0';
+ }
cp = line;
if ((arg = strdelim(&cp)) == NULL)
@@ -918,7 +1304,7 @@ process_server_config_line(ServerOptions *options, char *line,
cmdline = 1;
activep = &cmdline;
}
- if (*activep && opcode != sMatch)
+ if (*activep && opcode != sMatch && opcode != sInclude)
debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
if (connectinfo == NULL) {
@@ -944,9 +1330,6 @@ process_server_config_line(ServerOptions *options, char *line,
/* ignore ports from configfile if cmdline specifies ports */
if (options->ports_from_cmdline)
return 0;
- if (options->listen_addrs != NULL)
- fatal("%s line %d: ports must be specified before "
- "ListenAddress.", filename, linenum);
if (options->num_ports >= MAX_PORTS)
fatal("%s line %d: too many ports.",
filename, linenum);
@@ -960,18 +1343,6 @@ process_server_config_line(ServerOptions *options, char *line,
filename, linenum);
break;
- case sServerKeyBits:
- intptr = &options->server_key_bits;
- parse_int:
- arg = strdelim(&cp);
- if (!arg || *arg == '\0')
- fatal("%s line %d: missing integer value.",
- filename, linenum);
- value = atoi(arg);
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
-
case sLoginGraceTime:
intptr = &options->login_grace_time;
parse_time:
@@ -982,14 +1353,10 @@ process_server_config_line(ServerOptions *options, char *line,
if ((value = convtime(arg)) == -1)
fatal("%s line %d: invalid time value.",
filename, linenum);
- if (*intptr == -1)
+ if (*activep && *intptr == -1)
*intptr = value;
break;
- case sKeyRegenerationTime:
- intptr = &options->key_regeneration_time;
- goto parse_time;
-
case sListenAddress:
arg = strdelim(&cp);
if (arg == NULL || *arg == '\0')
@@ -998,29 +1365,41 @@ process_server_config_line(ServerOptions *options, char *line,
/* check for bare IPv6 address: no "[]" and 2 or more ":" */
if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
&& strchr(p+1, ':') != NULL) {
- add_listen_addr(options, arg, 0);
- break;
- }
- p = hpdelim(&arg);
- if (p == NULL)
- fatal("%s line %d: bad address:port usage",
- filename, linenum);
- p = cleanhostname(p);
- if (arg == NULL)
port = 0;
- else if ((port = a2port(arg)) <= 0)
- fatal("%s line %d: bad port number", filename, linenum);
+ p = arg;
+ } else {
+ arg2 = NULL;
+ ch = '\0';
+ p = hpdelim2(&arg, &ch);
+ if (p == NULL || ch == '/')
+ fatal("%s line %d: bad address:port usage",
+ filename, linenum);
+ p = cleanhostname(p);
+ if (arg == NULL)
+ port = 0;
+ else if ((port = a2port(arg)) <= 0)
+ fatal("%s line %d: bad port number",
+ filename, linenum);
+ }
+ /* Optional routing table */
+ arg2 = NULL;
+ if ((arg = strdelim(&cp)) != NULL) {
+ if (strcmp(arg, "rdomain") != 0 ||
+ (arg2 = strdelim(&cp)) == NULL)
+ fatal("%s line %d: bad ListenAddress syntax",
+ filename, linenum);
+ if (!valid_rdomain(arg2))
+ fatal("%s line %d: bad routing domain",
+ filename, linenum);
+ }
- add_listen_addr(options, p, port);
+ queue_listen_addr(options, p, arg2, port);
break;
case sAddressFamily:
intptr = &options->address_family;
multistate_ptr = multistate_addressfamily;
- if (options->listen_addrs != NULL)
- fatal("%s line %d: address family must be specified "
- "before ListenAddress.", filename, linenum);
parse_multistate:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
@@ -1041,21 +1420,13 @@ process_server_config_line(ServerOptions *options, char *line,
break;
case sHostKeyFile:
- intptr = &options->num_host_key_files;
- if (*intptr >= MAX_HOSTKEYS)
- fatal("%s line %d: too many host keys specified (max %d).",
- filename, linenum, MAX_HOSTKEYS);
- charptr = &options->host_key_files[*intptr];
- parse_filename:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
- if (*activep && *charptr == NULL) {
- *charptr = derelativise_path(arg);
- /* increase optional counter */
- if (intptr != NULL)
- *intptr = *intptr + 1;
+ if (*activep) {
+ servconf_add_hostkey(filename, linenum,
+ options, arg, 1);
}
break;
@@ -1071,18 +1442,28 @@ process_server_config_line(ServerOptions *options, char *line,
break;
case sHostCertificate:
- intptr = &options->num_host_cert_files;
- if (*intptr >= MAX_HOSTKEYS)
- fatal("%s line %d: too many host certificates "
- "specified (max %d).", filename, linenum,
- MAX_HOSTCERTS);
- charptr = &options->host_cert_files[*intptr];
- goto parse_filename;
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing file name.",
+ filename, linenum);
+ if (*activep)
+ servconf_add_hostcert(filename, linenum, options, arg);
break;
case sPidFile:
charptr = &options->pid_file;
- goto parse_filename;
+ parse_filename:
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing file name.",
+ filename, linenum);
+ if (*activep && *charptr == NULL) {
+ *charptr = derelativise_path(arg);
+ /* increase optional counter */
+ if (intptr != NULL)
+ *intptr = *intptr + 1;
+ }
+ break;
case sPermitRootLogin:
intptr = &options->permit_root_login;
@@ -1091,30 +1472,14 @@ process_server_config_line(ServerOptions *options, char *line,
case sIgnoreRhosts:
intptr = &options->ignore_rhosts;
- parse_flag:
- arg = strdelim(&cp);
- if (!arg || *arg == '\0')
- fatal("%s line %d: missing yes/no argument.",
- filename, linenum);
- value = 0; /* silence compiler */
- if (strcmp(arg, "yes") == 0)
- value = 1;
- else if (strcmp(arg, "no") == 0)
- value = 0;
- else
- fatal("%s line %d: Bad yes/no argument: %s",
- filename, linenum, arg);
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
+ multistate_ptr = multistate_ignore_rhosts;
+ goto parse_multistate;
case sIgnoreUserKnownHosts:
intptr = &options->ignore_user_known_hosts;
- goto parse_flag;
-
- case sRhostsRSAAuthentication:
- intptr = &options->rhosts_rsa_authentication;
- goto parse_flag;
+ parse_flag:
+ multistate_ptr = multistate_flag;
+ goto parse_multistate;
case sHostbasedAuthentication:
intptr = &options->hostbased_authentication;
@@ -1131,16 +1496,22 @@ process_server_config_line(ServerOptions *options, char *line,
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.",
filename, linenum);
- if (!sshkey_names_valid2(arg, 1))
+ if (*arg != '-' &&
+ !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
+ arg + 1 : arg, 1))
fatal("%s line %d: Bad key types '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
- case sRSAAuthentication:
- intptr = &options->rsa_authentication;
- goto parse_flag;
+ case sHostKeyAlgorithms:
+ charptr = &options->hostkeyalgorithms;
+ goto parse_keytypes;
+
+ case sCASignatureAlgorithms:
+ charptr = &options->ca_sign_algorithms;
+ goto parse_keytypes;
case sPubkeyAuthentication:
intptr = &options->pubkey_authentication;
@@ -1150,6 +1521,24 @@ process_server_config_line(ServerOptions *options, char *line,
charptr = &options->pubkey_key_types;
goto parse_keytypes;
+ case sPubkeyAuthOptions:
+ intptr = &options->pubkey_auth_options;
+ value = 0;
+ while ((arg = strdelim(&cp)) && *arg != '\0') {
+ if (strcasecmp(arg, "none") == 0)
+ continue;
+ if (strcasecmp(arg, "touch-required") == 0)
+ value |= PUBKEYAUTH_TOUCH_REQUIRED;
+ else {
+ fatal("%s line %d: unsupported "
+ "PubkeyAuthOptions option %s",
+ filename, linenum, arg);
+ }
+ }
+ if (*activep && *intptr == -1)
+ *intptr = value;
+ break;
+
case sKerberosAuthentication:
intptr = &options->kerberos_authentication;
goto parse_flag;
@@ -1174,6 +1563,10 @@ process_server_config_line(ServerOptions *options, char *line,
intptr = &options->gss_cleanup_creds;
goto parse_flag;
+ case sGssStrictAcceptor:
+ intptr = &options->gss_strict_acceptor;
+ goto parse_flag;
+
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
@@ -1200,7 +1593,14 @@ process_server_config_line(ServerOptions *options, char *line,
case sX11DisplayOffset:
intptr = &options->x11_display_offset;
- goto parse_int;
+ parse_int:
+ arg = strdelim(&cp);
+ if ((errstr = atoi_err(arg, &value)) != NULL)
+ fatal("%s line %d: integer value %s.",
+ filename, linenum, errstr);
+ if (*activep && *intptr == -1)
+ *intptr = value;
+ break;
case sX11UseLocalhost:
intptr = &options->x11_use_localhost;
@@ -1232,11 +1632,29 @@ process_server_config_line(ServerOptions *options, char *line,
case sPermitUserEnvironment:
intptr = &options->permit_user_env;
- goto parse_flag;
-
- case sUseLogin:
- intptr = &options->use_login;
- goto parse_flag;
+ charptr = &options->permit_user_env_whitelist;
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing argument.",
+ filename, linenum);
+ value = 0;
+ p = NULL;
+ if (strcmp(arg, "yes") == 0)
+ value = 1;
+ else if (strcmp(arg, "no") == 0)
+ value = 0;
+ else {
+ /* Pattern-list specified */
+ value = 1;
+ p = xstrdup(arg);
+ }
+ if (*activep && *intptr == -1) {
+ *intptr = value;
+ *charptr = p;
+ p = NULL;
+ }
+ free(p);
+ break;
case sCompression:
intptr = &options->compression;
@@ -1254,16 +1672,12 @@ process_server_config_line(ServerOptions *options, char *line,
if (scan_scaled(arg, &val64) == -1)
fatal("%.200s line %d: Bad number '%s': %s",
filename, linenum, arg, strerror(errno));
- /* check for too-large or too-small limits */
- if (val64 > UINT_MAX)
- fatal("%.200s line %d: RekeyLimit too large",
- filename, linenum);
if (val64 != 0 && val64 < 16)
fatal("%.200s line %d: RekeyLimit too small",
filename, linenum);
}
if (*activep && options->rekey_limit == -1)
- options->rekey_limit = (u_int32_t)val64;
+ options->rekey_limit = val64;
if (cp != NULL) { /* optional rekey interval present */
if (strcmp(cp, "none") == 0) {
(void)strdelim(&cp); /* discard */
@@ -1301,7 +1715,7 @@ process_server_config_line(ServerOptions *options, char *line,
if (value == SYSLOG_LEVEL_NOT_SET)
fatal("%.200s line %d: unsupported log level '%s'",
filename, linenum, arg ? arg : "<NONE>");
- if (*log_level_ptr == -1)
+ if (*activep && *log_level_ptr == -1)
*log_level_ptr = (LogLevel) value;
break;
@@ -1319,56 +1733,53 @@ process_server_config_line(ServerOptions *options, char *line,
intptr = &options->allow_agent_forwarding;
goto parse_flag;
- case sUsePrivilegeSeparation:
- intptr = &use_privsep;
- multistate_ptr = multistate_privsep;
- goto parse_multistate;
+ case sDisableForwarding:
+ intptr = &options->disable_forwarding;
+ goto parse_flag;
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
- if (options->num_allow_users >= MAX_ALLOW_USERS)
- fatal("%s line %d: too many allow users.",
- filename, linenum);
+ if (match_user(NULL, NULL, NULL, arg) == -1)
+ fatal("%s line %d: invalid AllowUsers pattern: "
+ "\"%.100s\"", filename, linenum, arg);
if (!*activep)
continue;
- options->allow_users[options->num_allow_users++] =
- xstrdup(arg);
+ array_append(filename, linenum, "AllowUsers",
+ &options->allow_users, &options->num_allow_users,
+ arg);
}
break;
case sDenyUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
- if (options->num_deny_users >= MAX_DENY_USERS)
- fatal("%s line %d: too many deny users.",
- filename, linenum);
+ if (match_user(NULL, NULL, NULL, arg) == -1)
+ fatal("%s line %d: invalid DenyUsers pattern: "
+ "\"%.100s\"", filename, linenum, arg);
if (!*activep)
continue;
- options->deny_users[options->num_deny_users++] =
- xstrdup(arg);
+ array_append(filename, linenum, "DenyUsers",
+ &options->deny_users, &options->num_deny_users,
+ arg);
}
break;
case sAllowGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
- if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
- fatal("%s line %d: too many allow groups.",
- filename, linenum);
if (!*activep)
continue;
- options->allow_groups[options->num_allow_groups++] =
- xstrdup(arg);
+ array_append(filename, linenum, "AllowGroups",
+ &options->allow_groups, &options->num_allow_groups,
+ arg);
}
break;
case sDenyGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
- if (options->num_deny_groups >= MAX_DENY_GROUPS)
- fatal("%s line %d: too many deny groups.",
- filename, linenum);
if (!*activep)
continue;
- options->deny_groups[options->num_deny_groups++] =
- xstrdup(arg);
+ array_append(filename, linenum, "DenyGroups",
+ &options->deny_groups, &options->num_deny_groups,
+ arg);
}
break;
@@ -1376,7 +1787,8 @@ process_server_config_line(ServerOptions *options, char *line,
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
- if (!ciphers_valid(arg))
+ if (*arg != '-' &&
+ !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->ciphers == NULL)
@@ -1387,7 +1799,8 @@ process_server_config_line(ServerOptions *options, char *line,
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
- if (!mac_valid(arg))
+ if (*arg != '-' &&
+ !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 mac spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->macs == NULL)
@@ -1399,26 +1812,15 @@ process_server_config_line(ServerOptions *options, char *line,
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.",
filename, linenum);
- if (!kex_names_valid(arg))
+ if (*arg != '-' &&
+ !kex_names_valid(*arg == '+' || *arg == '^' ?
+ arg + 1 : arg))
fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->kex_algorithms == NULL)
options->kex_algorithms = xstrdup(arg);
break;
- case sProtocol:
- intptr = &options->protocol;
- arg = strdelim(&cp);
- if (!arg || *arg == '\0')
- fatal("%s line %d: Missing argument.", filename, linenum);
- value = proto_spec(arg);
- if (value == SSH_PROTO_UNKNOWN)
- fatal("%s line %d: Bad protocol spec '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
- if (*intptr == SSH_PROTO_UNKNOWN)
- *intptr = value;
- break;
-
case sSubsystem:
if (options->num_subsystems >= MAX_SUBSYSTEMS) {
fatal("%s line %d: too many subsystems defined.",
@@ -1448,7 +1850,7 @@ process_server_config_line(ServerOptions *options, char *line,
len = strlen(p) + 1;
while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
len += 1 + strlen(arg);
- p = xrealloc(p, 1, len);
+ p = xreallocarray(p, 1, len);
strlcat(p, " ", len);
strlcat(p, arg, len);
}
@@ -1499,14 +1901,12 @@ process_server_config_line(ServerOptions *options, char *line,
case sAuthorizedKeysFile:
if (*activep && options->num_authkeys_files == 0) {
while ((arg = strdelim(&cp)) && *arg != '\0') {
- if (options->num_authkeys_files >=
- MAX_AUTHKEYS_FILES)
- fatal("%s line %d: "
- "too many authorized keys files.",
- filename, linenum);
- options->authorized_keys_files[
- options->num_authkeys_files++] =
- tilde_expand_filename(arg, getuid());
+ arg = tilde_expand_filename(arg, getuid());
+ array_append(filename, linenum,
+ "AuthorizedKeysFile",
+ &options->authorized_keys_files,
+ &options->num_authkeys_files, arg);
+ free(arg);
}
}
return 0;
@@ -1538,13 +1938,24 @@ process_server_config_line(ServerOptions *options, char *line,
if (strchr(arg, '=') != NULL)
fatal("%s line %d: Invalid environment name.",
filename, linenum);
- if (options->num_accept_env >= MAX_ACCEPT_ENV)
- fatal("%s line %d: too many allow env.",
- filename, linenum);
if (!*activep)
continue;
- options->accept_env[options->num_accept_env++] =
- xstrdup(arg);
+ array_append(filename, linenum, "AcceptEnv",
+ &options->accept_env, &options->num_accept_env,
+ arg);
+ }
+ break;
+
+ case sSetEnv:
+ uvalue = options->num_setenv;
+ while ((arg = strdelimw(&cp)) && *arg != '\0') {
+ if (strchr(arg, '=') == NULL)
+ fatal("%s line %d: Invalid environment.",
+ filename, linenum);
+ if (!*activep || uvalue != 0)
+ continue;
+ array_append(filename, linenum, "SetEnv",
+ &options->setenv, &options->num_setenv, arg);
}
break;
@@ -1563,10 +1974,100 @@ process_server_config_line(ServerOptions *options, char *line,
if (value == -1)
fatal("%s line %d: Bad yes/point-to-point/ethernet/"
"no argument: %s", filename, linenum, arg);
- if (*intptr == -1)
+ if (*activep && *intptr == -1)
*intptr = value;
break;
+ case sInclude:
+ if (cmdline) {
+ fatal("Include directive not supported as a "
+ "command-line option");
+ }
+ value = 0;
+ while ((arg2 = strdelim(&cp)) != NULL && *arg2 != '\0') {
+ value++;
+ found = 0;
+ if (*arg2 != '/' && *arg2 != '~') {
+ xasprintf(&arg, "%s/%s", SSHDIR, arg2);
+ } else
+ arg = xstrdup(arg2);
+
+ /*
+ * Don't let included files clobber the containing
+ * file's Match state.
+ */
+ oactive = *activep;
+
+ /* consult cache of include files */
+ TAILQ_FOREACH(item, includes, entry) {
+ if (strcmp(item->selector, arg) != 0)
+ continue;
+ if (item->filename != NULL) {
+ parse_server_config_depth(options,
+ item->filename, item->contents,
+ includes, connectinfo,
+ (oactive ? 0 : SSHCFG_NEVERMATCH),
+ activep, depth + 1);
+ }
+ found = 1;
+ *activep = oactive;
+ }
+ if (found != 0) {
+ free(arg);
+ continue;
+ }
+
+ /* requested glob was not in cache */
+ debug2("%s line %d: new include %s",
+ filename, linenum, arg);
+ if ((r = glob(arg, 0, NULL, &gbuf)) != 0) {
+ if (r != GLOB_NOMATCH) {
+ fatal("%s line %d: include \"%s\" "
+ "glob failed", filename,
+ linenum, arg);
+ }
+ /*
+ * If no entry matched then record a
+ * placeholder to skip later glob calls.
+ */
+ debug2("%s line %d: no match for %s",
+ filename, linenum, arg);
+ item = xcalloc(1, sizeof(*item));
+ item->selector = strdup(arg);
+ TAILQ_INSERT_TAIL(includes,
+ item, entry);
+ }
+ if (gbuf.gl_pathc > INT_MAX)
+ fatal("%s: too many glob results", __func__);
+ 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__);
+ }
+ load_server_config(item->filename,
+ item->contents);
+ parse_server_config_depth(options,
+ item->filename, item->contents,
+ includes, connectinfo,
+ (oactive ? 0 : SSHCFG_NEVERMATCH),
+ activep, depth + 1);
+ *activep = oactive;
+ TAILQ_INSERT_TAIL(includes, item, entry);
+ }
+ globfree(&gbuf);
+ free(arg);
+ }
+ if (value == 0) {
+ fatal("%s line %d: Include missing filename argument",
+ filename, linenum);
+ }
+ break;
+
case sMatch:
if (cmdline)
fatal("Match directive not supported as a command-line "
@@ -1575,48 +2076,68 @@ process_server_config_line(ServerOptions *options, char *line,
if (value < 0)
fatal("%s line %d: Bad Match condition", filename,
linenum);
- *activep = value;
+ *activep = (inc_flags & SSHCFG_NEVERMATCH) ? 0 : value;
break;
+ case sPermitListen:
case sPermitOpen:
+ if (opcode == sPermitListen) {
+ uintptr = &options->num_permitted_listens;
+ chararrayptr = &options->permitted_listens;
+ } else {
+ uintptr = &options->num_permitted_opens;
+ chararrayptr = &options->permitted_opens;
+ }
arg = strdelim(&cp);
if (!arg || *arg == '\0')
- fatal("%s line %d: missing PermitOpen specification",
- filename, linenum);
- n = options->num_permitted_opens; /* modified later */
- if (strcmp(arg, "any") == 0) {
- if (*activep && n == -1) {
- channel_clear_adm_permitted_opens();
- options->num_permitted_opens = 0;
- }
- break;
- }
- if (strcmp(arg, "none") == 0) {
- if (*activep && n == -1) {
- options->num_permitted_opens = 1;
- channel_disable_adm_local_opens();
+ fatal("%s line %d: missing %s specification",
+ filename, linenum, lookup_opcode_name(opcode));
+ uvalue = *uintptr; /* modified later */
+ if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
+ if (*activep && uvalue == 0) {
+ *uintptr = 1;
+ *chararrayptr = xcalloc(1,
+ sizeof(**chararrayptr));
+ (*chararrayptr)[0] = xstrdup(arg);
}
break;
}
- if (*activep && n == -1)
- channel_clear_adm_permitted_opens();
for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
- p = hpdelim(&arg);
- if (p == NULL)
- fatal("%s line %d: missing host in PermitOpen",
- filename, linenum);
- p = cleanhostname(p);
- if (arg == NULL || ((port = permitopen_port(arg)) < 0))
- fatal("%s line %d: bad port number in "
- "PermitOpen", filename, linenum);
- if (*activep && n == -1)
- options->num_permitted_opens =
- channel_add_adm_permitted_opens(p, port);
+ if (opcode == sPermitListen &&
+ strchr(arg, ':') == NULL) {
+ /*
+ * Allow bare port number for PermitListen
+ * to indicate a wildcard listen host.
+ */
+ xasprintf(&arg2, "*:%s", arg);
+ } else {
+ arg2 = xstrdup(arg);
+ ch = '\0';
+ p = hpdelim2(&arg, &ch);
+ if (p == NULL || ch == '/') {
+ fatal("%s line %d: missing host in %s",
+ filename, linenum,
+ lookup_opcode_name(opcode));
+ }
+ p = cleanhostname(p);
+ }
+ if (arg == NULL ||
+ ((port = permitopen_port(arg)) < 0)) {
+ fatal("%s line %d: bad port number in %s",
+ filename, linenum,
+ lookup_opcode_name(opcode));
+ }
+ if (*activep && uvalue == 0) {
+ array_append(filename, linenum,
+ lookup_opcode_name(opcode),
+ chararrayptr, uintptr, arg2);
+ }
+ free(arg2);
}
break;
case sForceCommand:
- if (cp == NULL)
+ if (cp == NULL || *cp == '\0')
fatal("%.200s line %d: Missing argument.", filename,
linenum);
len = strspn(cp, WHITESPACE);
@@ -1643,6 +2164,21 @@ process_server_config_line(ServerOptions *options, char *line,
charptr = &options->revoked_keys_file;
goto parse_filename;
+ case sSecurityKeyProvider:
+ charptr = &options->sk_provider;
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing file name.",
+ filename, linenum);
+ if (*activep && *charptr == NULL) {
+ *charptr = strcasecmp(arg, "internal") == 0 ?
+ xstrdup(arg) : derelativise_path(arg);
+ /* increase optional counter */
+ if (intptr != NULL)
+ *intptr = *intptr + 1;
+ }
+ break;
+
case sIPQoS:
arg = strdelim(&cp);
if ((value = parse_ipqos(arg)) == -1)
@@ -1661,7 +2197,7 @@ process_server_config_line(ServerOptions *options, char *line,
break;
case sVersionAddendum:
- if (cp == NULL)
+ if (cp == NULL || *cp == '\0')
fatal("%.200s line %d: Missing argument.", filename,
linenum);
len = strspn(cp, WHITESPACE);
@@ -1701,20 +2237,67 @@ process_server_config_line(ServerOptions *options, char *line,
*charptr = xstrdup(arg);
break;
+ case sAuthorizedPrincipalsCommand:
+ if (cp == NULL)
+ fatal("%.200s line %d: Missing argument.", filename,
+ linenum);
+ len = strspn(cp, WHITESPACE);
+ if (*activep &&
+ options->authorized_principals_command == NULL) {
+ if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)
+ fatal("%.200s line %d: "
+ "AuthorizedPrincipalsCommand must be "
+ "an absolute path", filename, linenum);
+ options->authorized_principals_command =
+ xstrdup(cp + len);
+ }
+ return 0;
+
+ case sAuthorizedPrincipalsCommandUser:
+ charptr = &options->authorized_principals_command_user;
+
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing "
+ "AuthorizedPrincipalsCommandUser argument.",
+ filename, linenum);
+ if (*activep && *charptr == NULL)
+ *charptr = xstrdup(arg);
+ break;
+
case sAuthenticationMethods:
- if (*activep && options->num_auth_methods == 0) {
+ 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 (options->num_auth_methods >=
- MAX_AUTH_METHODS)
- fatal("%s line %d: "
- "too many authentication methods.",
+ 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);
- if (auth2_methods_valid(arg, 0) != 0)
+ } else if (auth2_methods_valid(arg, 0) != 0) {
fatal("%s line %d: invalid "
"authentication method list.",
filename, linenum);
- options->auth_methods[
- options->num_auth_methods++] = xstrdup(arg);
+ }
+ value2 = 1;
+ if (!*activep)
+ continue;
+ array_append(filename, linenum,
+ "AuthenticationMethods",
+ &options->auth_methods,
+ &options->num_auth_methods, arg);
+ }
+ if (value2 == 0) {
+ fatal("%s line %d: no AuthenticationMethods "
+ "specified", filename, linenum);
}
}
return 0;
@@ -1722,13 +2305,14 @@ process_server_config_line(ServerOptions *options, char *line,
case sStreamLocalBindMask:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
- fatal("%s line %d: missing StreamLocalBindMask argument.",
- filename, linenum);
+ fatal("%s line %d: missing StreamLocalBindMask "
+ "argument.", filename, linenum);
/* Parse mode in octal format */
value = strtol(arg, &p, 8);
if (arg == p || value < 0 || value > 0777)
fatal("%s line %d: Bad mask.", filename, linenum);
- options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
+ if (*activep)
+ options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
break;
case sStreamLocalBindUnlink:
@@ -1747,16 +2331,35 @@ process_server_config_line(ServerOptions *options, char *line,
options->fingerprint_hash = value;
break;
- case sDeprecated:
- logit("%s line %d: Deprecated option %s",
- filename, linenum, arg);
- while (arg)
- arg = strdelim(&cp);
+ case sExposeAuthInfo:
+ intptr = &options->expose_userauth_info;
+ goto parse_flag;
+
+ case sRDomain:
+#if !defined(__OpenBSD__) && !defined(HAVE_SYS_SET_PROCESS_RDOMAIN)
+ fatal("%s line %d: setting RDomain not supported on this "
+ "platform.", filename, linenum);
+#endif
+ charptr = &options->routing_domain;
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing argument.",
+ filename, linenum);
+ if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 &&
+ !valid_rdomain(arg))
+ fatal("%s line %d: bad routing domain",
+ filename, linenum);
+ if (*activep && *charptr == NULL)
+ *charptr = xstrdup(arg);
break;
+ case sDeprecated:
+ case sIgnore:
case sUnsupported:
- logit("%s line %d: Unsupported option %s",
- filename, linenum, arg);
+ do_log2(opcode == sIgnore ?
+ SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO,
+ "%s line %d: %s option %s", filename, linenum,
+ opcode == sUnsupported ? "Unsupported" : "Deprecated", arg);
while (arg)
arg = strdelim(&cp);
break;
@@ -1771,25 +2374,34 @@ process_server_config_line(ServerOptions *options, char *line,
return 0;
}
+int
+process_server_config_line(ServerOptions *options, char *line,
+ const char *filename, int linenum, int *activep,
+ struct connection_info *connectinfo, struct include_list *includes)
+{
+ return process_server_config_line_depth(options, line, filename,
+ linenum, activep, connectinfo, 0, 0, includes);
+}
+
+
/* Reads the server configuration file. */
void
-load_server_config(const char *filename, Buffer *conf)
+load_server_config(const char *filename, struct sshbuf *conf)
{
- char line[4096], *cp;
+ char *line = NULL, *cp;
+ size_t linesize = 0;
FILE *f;
- int lineno = 0;
+ int r, lineno = 0;
debug2("%s: filename %s", __func__, filename);
if ((f = fopen(filename, "r")) == NULL) {
perror(filename);
exit(1);
}
- buffer_clear(conf);
- while (fgets(line, sizeof(line), f)) {
+ sshbuf_reset(conf);
+ while (getline(&line, &linesize, f) != -1) {
lineno++;
- if (strlen(line) == sizeof(line) - 1)
- fatal("%s line %d too long", filename, lineno);
/*
* Trim out comments and strip whitespace
* NB - preserve newlines, they are needed to reproduce
@@ -1798,17 +2410,19 @@ load_server_config(const char *filename, Buffer *conf)
if ((cp = strchr(line, '#')) != NULL)
memcpy(cp, "\n", 2);
cp = line + strspn(line, " \t\r");
-
- buffer_append(conf, cp, strlen(cp));
+ if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
- buffer_append(conf, "\0", 1);
+ free(line);
+ if ((r = sshbuf_put_u8(conf, 0)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
fclose(f);
- debug2("%s: done config len = %d", __func__, buffer_len(conf));
+ debug2("%s: done config len = %zu", __func__, sshbuf_len(conf));
}
void
parse_server_match_config(ServerOptions *options,
- struct connection_info *connectinfo)
+ struct include_list *includes, struct connection_info *connectinfo)
{
ServerOptions mo;
#if defined(ANDROID)
@@ -1816,7 +2430,8 @@ parse_server_match_config(ServerOptions *options,
#endif
initialize_server_options(&mo);
- parse_server_config(&mo, "reprocess config", &cfg, connectinfo);
+ parse_server_config(&mo, "reprocess config", cfg, includes,
+ connectinfo);
#if defined(ANDROID)
/* Allow root login if ro.debuggable is set. */
property_get("ro.debuggable", value, "");
@@ -1840,6 +2455,8 @@ int parse_server_match_testspec(struct connection_info *ci, char *spec)
ci->user = xstrdup(p + 5);
} else if (strncmp(p, "laddr=", 6) == 0) {
ci->laddress = xstrdup(p + 6);
+ } else if (strncmp(p, "rdomain=", 8) == 0) {
+ ci->rdomain = xstrdup(p + 8);
} else if (strncmp(p, "lport=", 6) == 0) {
ci->lport = a2port(p + 6);
if (ci->lport == -1) {
@@ -1857,24 +2474,11 @@ int parse_server_match_testspec(struct connection_info *ci, char *spec)
}
/*
- * returns 1 for a complete spec, 0 for partial spec and -1 for an
- * empty spec.
- */
-int server_match_spec_complete(struct connection_info *ci)
-{
- if (ci->user && ci->host && ci->address)
- return 1; /* complete */
- if (!ci->user && !ci->host && !ci->address)
- return -1; /* empty */
- return 0; /* partial */
-}
-
-/*
* Copy any supported values that are set.
*
* If the preauth flag is set, we do not bother copying the string or
* array values that are not used pre-authentication, because any that we
- * do use must be explictly sent in mm_getpwnamallow().
+ * do use must be explicitly sent in mm_getpwnamallow().
*/
void
copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
@@ -1886,20 +2490,24 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_INTOPT(password_authentication);
M_CP_INTOPT(gss_authentication);
- M_CP_INTOPT(rsa_authentication);
M_CP_INTOPT(pubkey_authentication);
+ M_CP_INTOPT(pubkey_auth_options);
M_CP_INTOPT(kerberos_authentication);
M_CP_INTOPT(hostbased_authentication);
M_CP_INTOPT(hostbased_uses_name_from_packet_only);
M_CP_INTOPT(kbd_interactive_authentication);
M_CP_INTOPT(permit_root_login);
M_CP_INTOPT(permit_empty_passwd);
+ M_CP_INTOPT(ignore_rhosts);
M_CP_INTOPT(allow_tcp_forwarding);
M_CP_INTOPT(allow_streamlocal_forwarding);
M_CP_INTOPT(allow_agent_forwarding);
+ M_CP_INTOPT(disable_forwarding);
+ M_CP_INTOPT(expose_userauth_info);
M_CP_INTOPT(permit_tun);
M_CP_INTOPT(fwd_opts.gateway_ports);
+ M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink);
M_CP_INTOPT(x11_display_offset);
M_CP_INTOPT(x11_forwarding);
M_CP_INTOPT(x11_use_localhost);
@@ -1907,10 +2515,23 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_INTOPT(permit_user_rc);
M_CP_INTOPT(max_sessions);
M_CP_INTOPT(max_authtries);
+ M_CP_INTOPT(client_alive_count_max);
+ M_CP_INTOPT(client_alive_interval);
M_CP_INTOPT(ip_qos_interactive);
M_CP_INTOPT(ip_qos_bulk);
M_CP_INTOPT(rekey_limit);
M_CP_INTOPT(rekey_interval);
+ M_CP_INTOPT(log_level);
+
+ /*
+ * The bind_mask is a mode_t that may be unsigned, so we can't use
+ * M_CP_INTOPT - it does a signed comparison that causes compiler
+ * warnings.
+ */
+ if (src->fwd_opts.streamlocal_bind_mask != (mode_t)-1) {
+ dst->fwd_opts.streamlocal_bind_mask =
+ src->fwd_opts.streamlocal_bind_mask;
+ }
/* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */
#define M_CP_STROPT(n) do {\
@@ -1919,16 +2540,25 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
dst->n = src->n; \
} \
} while(0)
-#define M_CP_STRARRAYOPT(n, num_n) do {\
- if (src->num_n != 0) { \
- for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \
- dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \
+#define M_CP_STRARRAYOPT(s, num_s) do {\
+ u_int i; \
+ if (src->num_s != 0) { \
+ for (i = 0; i < dst->num_s; i++) \
+ free(dst->s[i]); \
+ free(dst->s); \
+ dst->s = xcalloc(src->num_s, sizeof(*dst->s)); \
+ for (i = 0; i < src->num_s; i++) \
+ dst->s[i] = xstrdup(src->s[i]); \
+ dst->num_s = src->num_s; \
} \
} while(0)
/* See comment in servconf.h */
COPY_MATCH_STRING_OPTS();
+ /* Arguments that accept '+...' need to be expanded */
+ assemble_algorithms(dst);
+
/*
* The only things that should be below this point are string options
* which are only used after authentication.
@@ -1936,35 +2566,61 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
if (preauth)
return;
+ /* These options may be "none" to clear a global setting */
M_CP_STROPT(adm_forced_command);
+ if (option_clear_or_none(dst->adm_forced_command)) {
+ free(dst->adm_forced_command);
+ dst->adm_forced_command = NULL;
+ }
M_CP_STROPT(chroot_directory);
+ if (option_clear_or_none(dst->chroot_directory)) {
+ free(dst->chroot_directory);
+ dst->chroot_directory = NULL;
+ }
}
#undef M_CP_INTOPT
#undef M_CP_STROPT
#undef M_CP_STRARRAYOPT
+#define SERVCONF_MAX_DEPTH 16
void
-parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
- struct connection_info *connectinfo)
+parse_server_config_depth(ServerOptions *options, const char *filename,
+ struct sshbuf *conf, struct include_list *includes,
+ struct connection_info *connectinfo, int flags, int *activep, int depth)
{
- int active, linenum, bad_options = 0;
+ int linenum, bad_options = 0;
char *cp, *obuf, *cbuf;
- debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
+ if (depth < 0 || depth > SERVCONF_MAX_DEPTH)
+ fatal("Too many recursive configuration includes");
+
+ debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf));
- obuf = cbuf = xstrdup(buffer_ptr(conf));
- active = connectinfo ? 0 : 1;
+ if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL)
+ fatal("%s: sshbuf_dup_string failed", __func__);
linenum = 1;
while ((cp = strsep(&cbuf, "\n")) != NULL) {
- if (process_server_config_line(options, cp, filename,
- linenum++, &active, connectinfo) != 0)
+ if (process_server_config_line_depth(options, cp,
+ filename, linenum++, activep, connectinfo, flags,
+ depth, includes) != 0)
bad_options++;
}
free(obuf);
if (bad_options > 0)
fatal("%s: terminating, %d bad configuration options",
filename, bad_options);
+ process_queued_listen_addrs(options);
+}
+
+void
+parse_server_config(ServerOptions *options, const char *filename,
+ struct sshbuf *conf, struct include_list *includes,
+ struct connection_info *connectinfo)
+{
+ int active = connectinfo ? 0 : 1;
+ parse_server_config_depth(options, filename, conf, includes,
+ connectinfo, 0, &active, 0);
}
static const char *
@@ -1993,25 +2649,14 @@ fmt_intarg(ServerOpCodes code, int val)
return fmt_multistate_int(val, multistate_gatewayports);
case sCompression:
return fmt_multistate_int(val, multistate_compression);
- case sUsePrivilegeSeparation:
- return fmt_multistate_int(val, multistate_privsep);
case sAllowTcpForwarding:
return fmt_multistate_int(val, multistate_tcpfwd);
case sAllowStreamLocalForwarding:
return fmt_multistate_int(val, multistate_tcpfwd);
+ case sIgnoreRhosts:
+ return fmt_multistate_int(val, multistate_ignore_rhosts);
case sFingerprintHash:
return ssh_digest_alg_name(val);
- case sProtocol:
- switch (val) {
- case SSH_PROTO_1:
- return "1";
- case SSH_PROTO_2:
- return "2";
- case (SSH_PROTO_1|SSH_PROTO_2):
- return "2,1";
- default:
- return "UNKNOWN";
- }
default:
switch (val) {
case 0:
@@ -2024,21 +2669,16 @@ fmt_intarg(ServerOpCodes code, int val)
}
}
-static const char *
-lookup_opcode_name(ServerOpCodes code)
+static void
+dump_cfg_int(ServerOpCodes code, int val)
{
- u_int i;
-
- for (i = 0; keywords[i].name != NULL; i++)
- if (keywords[i].opcode == code)
- return(keywords[i].name);
- return "UNKNOWN";
+ printf("%s %d\n", lookup_opcode_name(code), val);
}
static void
-dump_cfg_int(ServerOpCodes code, int val)
+dump_cfg_oct(ServerOpCodes code, int val)
{
- printf("%s %d\n", lookup_opcode_name(code), val);
+ printf("%s 0%o\n", lookup_opcode_name(code), val);
}
static void
@@ -2050,8 +2690,6 @@ dump_cfg_fmtint(ServerOpCodes code, int val)
static void
dump_cfg_string(ServerOpCodes code, const char *val)
{
- if (val == NULL)
- return;
printf("%s %s\n", lookup_opcode_name(code),
val == NULL ? "none" : val);
}
@@ -2070,64 +2708,91 @@ dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
{
u_int i;
+ if (count <= 0 && code != sAuthenticationMethods)
+ return;
printf("%s", lookup_opcode_name(code));
for (i = 0; i < count; i++)
printf(" %s", vals[i]);
+ if (code == sAuthenticationMethods && count == 0)
+ printf(" any");
printf("\n");
}
+static char *
+format_listen_addrs(struct listenaddr *la)
+{
+ int r;
+ struct addrinfo *ai;
+ char addr[NI_MAXHOST], port[NI_MAXSERV];
+ char *laddr1 = xstrdup(""), *laddr2 = NULL;
+
+ /*
+ * ListenAddress must be after Port. add_one_listen_addr pushes
+ * addresses onto a stack, so to maintain ordering we need to
+ * print these in reverse order.
+ */
+ for (ai = la->addrs; ai; ai = ai->ai_next) {
+ if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
+ sizeof(addr), port, sizeof(port),
+ NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
+ error("getnameinfo: %.100s", ssh_gai_strerror(r));
+ continue;
+ }
+ laddr2 = laddr1;
+ if (ai->ai_family == AF_INET6) {
+ xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s",
+ addr, port,
+ la->rdomain == NULL ? "" : " rdomain ",
+ la->rdomain == NULL ? "" : la->rdomain,
+ laddr2);
+ } else {
+ xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s",
+ addr, port,
+ la->rdomain == NULL ? "" : " rdomain ",
+ la->rdomain == NULL ? "" : la->rdomain,
+ laddr2);
+ }
+ free(laddr2);
+ }
+ return laddr1;
+}
+
void
dump_config(ServerOptions *o)
{
+ char *s;
u_int i;
- int ret;
- struct addrinfo *ai;
- char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL;
/* these are usually at the top of the config */
for (i = 0; i < o->num_ports; i++)
printf("port %d\n", o->ports[i]);
- dump_cfg_fmtint(sProtocol, o->protocol);
dump_cfg_fmtint(sAddressFamily, o->address_family);
- /* ListenAddress must be after Port */
- for (ai = o->listen_addrs; ai; ai = ai->ai_next) {
- if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
- sizeof(addr), port, sizeof(port),
- NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
- error("getnameinfo failed: %.100s",
- (ret != EAI_SYSTEM) ? gai_strerror(ret) :
- strerror(errno));
- } else {
- if (ai->ai_family == AF_INET6)
- printf("listenaddress [%s]:%s\n", addr, port);
- else
- printf("listenaddress %s:%s\n", addr, port);
- }
+ for (i = 0; i < o->num_listen_addrs; i++) {
+ s = format_listen_addrs(&o->listen_addrs[i]);
+ printf("%s", s);
+ free(s);
}
/* integer arguments */
#ifdef USE_PAM
- dump_cfg_int(sUsePAM, o->use_pam);
+ dump_cfg_fmtint(sUsePAM, o->use_pam);
#endif
- dump_cfg_int(sServerKeyBits, o->server_key_bits);
dump_cfg_int(sLoginGraceTime, o->login_grace_time);
- dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time);
dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
dump_cfg_int(sMaxAuthTries, o->max_authtries);
dump_cfg_int(sMaxSessions, o->max_sessions);
dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
+ dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
/* formatted integer arguments */
dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
- dump_cfg_fmtint(sRhostsRSAAuthentication, o->rhosts_rsa_authentication);
dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
o->hostbased_uses_name_from_packet_only);
- dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication);
dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
#ifdef KRB5
dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
@@ -2147,7 +2812,9 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sChallengeResponseAuthentication,
o->challenge_response_authentication);
dump_cfg_fmtint(sPrintMotd, o->print_motd);
+#ifndef DISABLE_LASTLOG
dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
+#endif
dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
dump_cfg_fmtint(sPermitTTY, o->permit_tty);
@@ -2155,38 +2822,45 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sStrictModes, o->strict_modes);
dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
- dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
- dump_cfg_fmtint(sUseLogin, o->use_login);
dump_cfg_fmtint(sCompression, o->compression);
dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
dump_cfg_fmtint(sUseDNS, o->use_dns);
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
+ dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding);
+ dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding);
dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
- dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
+ dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
+ dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
/* string arguments */
dump_cfg_string(sPidFile, o->pid_file);
dump_cfg_string(sXAuthLocation, o->xauth_location);
- dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT);
- dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC);
+ dump_cfg_string(sCiphers, o->ciphers);
+ dump_cfg_string(sMacs, o->macs);
dump_cfg_string(sBanner, o->banner);
dump_cfg_string(sForceCommand, o->adm_forced_command);
dump_cfg_string(sChrootDirectory, o->chroot_directory);
dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
+ dump_cfg_string(sSecurityKeyProvider, o->sk_provider);
dump_cfg_string(sAuthorizedPrincipalsFile,
o->authorized_principals_file);
- dump_cfg_string(sVersionAddendum, o->version_addendum);
+ dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0'
+ ? "none" : o->version_addendum);
dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
+ dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command);
+ dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user);
dump_cfg_string(sHostKeyAgent, o->host_key_agent);
- dump_cfg_string(sKexAlgorithms,
- o->kex_algorithms ? o->kex_algorithms : KEX_SERVER_KEX);
- dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types ?
- o->hostbased_key_types : KEX_DEFAULT_PK_ALG);
- dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ?
- o->pubkey_key_types : KEX_DEFAULT_PK_ALG);
+ dump_cfg_string(sKexAlgorithms, o->kex_algorithms);
+ dump_cfg_string(sCASignatureAlgorithms, o->ca_sign_algorithms);
+ dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types);
+ dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms);
+ dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types);
+#if defined(__OpenBSD__) || defined(HAVE_SYS_SET_PROCESS_RDOMAIN)
+ dump_cfg_string(sRDomain, o->routing_domain);
+#endif
/* string arguments requiring a lookup */
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
@@ -2197,13 +2871,14 @@ dump_config(ServerOptions *o)
o->authorized_keys_files);
dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
o->host_key_files);
- dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files,
+ dump_cfg_strarray(sHostCertificate, o->num_host_cert_files,
o->host_cert_files);
dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
+ dump_cfg_strarray(sSetEnv, o->num_setenv, o->setenv);
dump_cfg_strarray_oneline(sAuthenticationMethods,
o->num_auth_methods, o->auth_methods);
@@ -2215,18 +2890,49 @@ dump_config(ServerOptions *o)
printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
o->max_startups_rate, o->max_startups);
- for (i = 0; tunmode_desc[i].val != -1; i++)
+ s = NULL;
+ for (i = 0; tunmode_desc[i].val != -1; i++) {
if (tunmode_desc[i].val == o->permit_tun) {
s = tunmode_desc[i].text;
break;
}
+ }
dump_cfg_string(sPermitTunnel, s);
printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
printf("%s\n", iptos2str(o->ip_qos_bulk));
- printf("rekeylimit %lld %d\n", (long long)o->rekey_limit,
+ printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit,
o->rekey_interval);
- channel_print_adm_permitted_opens();
+ printf("permitopen");
+ if (o->num_permitted_opens == 0)
+ printf(" any");
+ else {
+ for (i = 0; i < o->num_permitted_opens; i++)
+ printf(" %s", o->permitted_opens[i]);
+ }
+ printf("\n");
+ printf("permitlisten");
+ if (o->num_permitted_listens == 0)
+ printf(" any");
+ else {
+ for (i = 0; i < o->num_permitted_listens; i++)
+ printf(" %s", o->permitted_listens[i]);
+ }
+ printf("\n");
+
+ if (o->permit_user_env_whitelist == NULL) {
+ dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
+ } else {
+ printf("permituserenvironment %s\n",
+ o->permit_user_env_whitelist);
+ }
+
+ printf("pubkeyauthoptions");
+ if (o->pubkey_auth_options == 0)
+ printf(" none");
+ if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED)
+ printf(" touch-required");
+ printf("\n");
}
diff --git a/servconf.h b/servconf.h
index 9922f0c8..a420f398 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.116 2015/01/13 07:39:19 djm Exp $ */
+/* $OpenBSD: servconf.h,v 1.144 2020/04/17 03:30:05 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -16,19 +16,11 @@
#ifndef SERVCONF_H
#define SERVCONF_H
+#include <openbsd-compat/sys-queue.h>
+
#define MAX_PORTS 256 /* Max # ports. */
-#define MAX_ALLOW_USERS 256 /* Max # users on allow list. */
-#define MAX_DENY_USERS 256 /* Max # users on deny list. */
-#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
-#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
-#define MAX_HOSTKEYS 256 /* Max # hostkeys. */
-#define MAX_HOSTCERTS 256 /* Max # host certificates. */
-#define MAX_ACCEPT_ENV 256 /* Max # of env vars. */
-#define MAX_MATCH_GROUPS 256 /* Max # of groups for Match. */
-#define MAX_AUTHKEYS_FILES 256 /* Max # of authorized_keys files. */
-#define MAX_AUTH_METHODS 256 /* Max # of AuthenticationMethods. */
/* permit_root_login */
#define PERMIT_NOT_SET -1
@@ -42,11 +34,14 @@
#define PRIVSEP_ON 1
#define PRIVSEP_NOSANDBOX 2
-/* AllowTCPForwarding */
-#define FORWARD_DENY 0
-#define FORWARD_REMOTE (1)
-#define FORWARD_LOCAL (1<<1)
-#define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL)
+/* PermitOpen */
+#define PERMITOPEN_ANY 0
+#define PERMITOPEN_NONE -2
+
+/* IgnoreRhosts */
+#define IGNORE_RHOSTS_NO 0
+#define IGNORE_RHOSTS_YES 1
+#define IGNORE_RHOSTS_SHOSTS 2
#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */
#define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */
@@ -54,23 +49,51 @@
/* Magic name for internal sftp-server */
#define INTERNAL_SFTP_NAME "internal-sftp"
+/* PubkeyAuthOptions flags */
+#define PUBKEYAUTH_TOUCH_REQUIRED 1
+
+struct ssh;
+struct fwd_perm_list;
+
+/*
+ * Used to store addresses from ListenAddr directives. These may be
+ * incomplete, as they may specify addresses that need to be merged
+ * with any ports requested by ListenPort.
+ */
+struct queued_listenaddr {
+ char *addr;
+ int port; /* <=0 if unspecified */
+ char *rdomain;
+};
+
+/* Resolved listen addresses, grouped by optional routing domain */
+struct listenaddr {
+ char *rdomain;
+ struct addrinfo *addrs;
+};
+
typedef struct {
u_int num_ports;
u_int ports_from_cmdline;
int ports[MAX_PORTS]; /* Port number to listen on. */
- char *listen_addr; /* Address on which the server listens. */
- struct addrinfo *listen_addrs; /* Addresses on which the server listens. */
- int address_family; /* Address family used by the server. */
- char *host_key_files[MAX_HOSTKEYS]; /* Files containing host keys. */
- int num_host_key_files; /* Number of files for host keys. */
- char *host_cert_files[MAX_HOSTCERTS]; /* Files containing host certs. */
- int num_host_cert_files; /* Number of files for host certs. */
- char *host_key_agent; /* ssh-agent socket for host keys. */
- char *pid_file; /* Where to put our pid */
- int server_key_bits;/* Size of the server key. */
+ struct queued_listenaddr *queued_listen_addrs;
+ u_int num_queued_listens;
+ struct listenaddr *listen_addrs;
+ u_int num_listen_addrs;
+ int address_family; /* Address family used by the server. */
+
+ char *routing_domain; /* Bind session to routing domain */
+
+ char **host_key_files; /* Files containing host keys. */
+ int *host_key_file_userprovided; /* Key was specified by user. */
+ u_int num_host_key_files; /* Number of files for host keys. */
+ char **host_cert_files; /* Files containing host certs. */
+ u_int num_host_cert_files; /* Number of files for host certs. */
+
+ char *host_key_agent; /* ssh-agent socket for host keys. */
+ char *pid_file; /* Where to put our pid */
int login_grace_time; /* Disconnect if no auth in this time
* (sec). */
- int key_regeneration_time; /* Server key lifetime (seconds). */
int permit_root_login; /* PERMIT_*, see above */
int ignore_rhosts; /* Ignore .rhosts and .shosts. */
int ignore_user_known_hosts; /* Ignore ~/.ssh/known_hosts
@@ -91,18 +114,17 @@ typedef struct {
char *ciphers; /* Supported SSH2 ciphers. */
char *macs; /* Supported SSH2 macs. */
char *kex_algorithms; /* SSH2 kex methods in order of preference. */
- int protocol; /* Supported protocol versions. */
struct ForwardOptions fwd_opts; /* forwarding options */
SyslogFacility log_facility; /* Facility for system logging. */
LogLevel log_level; /* Level for system logging. */
- int rhosts_rsa_authentication; /* If true, permit rhosts RSA
- * authentication. */
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 */
- int rsa_authentication; /* If true, permit RSA authentication. */
+ char *hostkeyalgorithms; /* SSH2 server key types */
+ char *ca_sign_algorithms; /* Allowed CA signature algorithms */
int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */
char *pubkey_key_types; /* Key types allowed for public key */
+ int pubkey_auth_options; /* -1 or mask of PUBKEYAUTH_* flags */
int kerberos_authentication; /* If true, permit Kerberos
* authentication. */
int kerberos_or_local_passwd; /* If true, permit kerberos
@@ -116,6 +138,7 @@ typedef struct {
* authenticated with Kerberos. */
int gss_authentication; /* If true, permit GSSAPI authentication */
int gss_cleanup_creds; /* If true, destroy cred cache on logout */
+ int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */
int password_authentication; /* If true, permit password
* authentication. */
int kbd_interactive_authentication; /* If true, permit */
@@ -123,19 +146,20 @@ typedef struct {
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
int permit_user_env; /* If true, read ~/.ssh/environment */
- int use_login; /* If true, login(1) is used */
+ char *permit_user_env_whitelist; /* pattern-list whitelist */
int compression; /* If true, compression is allowed */
int allow_tcp_forwarding; /* One of FORWARD_* */
int allow_streamlocal_forwarding; /* One of FORWARD_* */
int allow_agent_forwarding;
+ int disable_forwarding;
u_int num_allow_users;
- char *allow_users[MAX_ALLOW_USERS];
+ char **allow_users;
u_int num_deny_users;
- char *deny_users[MAX_DENY_USERS];
+ char **deny_users;
u_int num_allow_groups;
- char *allow_groups[MAX_ALLOW_GROUPS];
+ char **allow_groups;
u_int num_deny_groups;
- char *deny_groups[MAX_DENY_GROUPS];
+ char **deny_groups;
u_int num_subsystems;
char *subsystem_name[MAX_SUBSYSTEMS];
@@ -143,7 +167,9 @@ typedef struct {
char *subsystem_args[MAX_SUBSYSTEMS];
u_int num_accept_env;
- char *accept_env[MAX_ACCEPT_ENV];
+ char **accept_env;
+ u_int num_setenv;
+ char **setenv;
int max_startups_begin;
int max_startups_rate;
@@ -162,8 +188,8 @@ typedef struct {
* disconnect the session
*/
- u_int num_authkeys_files; /* Files containing public keys */
- char *authorized_keys_files[MAX_AUTHKEYS_FILES];
+ u_int num_authkeys_files; /* Files containing public keys */
+ char **authorized_keys_files;
char *adm_forced_command;
@@ -171,14 +197,19 @@ typedef struct {
int permit_tun;
- int num_permitted_opens;
+ char **permitted_opens; /* May also be one of PERMITOPEN_* */
+ u_int num_permitted_opens;
+ char **permitted_listens; /* May also be one of PERMITOPEN_* */
+ u_int num_permitted_listens;
char *chroot_directory;
char *revoked_keys_file;
char *trusted_user_ca_keys;
- char *authorized_principals_file;
char *authorized_keys_command;
char *authorized_keys_command_user;
+ char *authorized_principals_file;
+ char *authorized_principals_command;
+ char *authorized_principals_command_user;
int64_t rekey_limit;
int rekey_interval;
@@ -186,9 +217,12 @@ typedef struct {
char *version_addendum; /* Appended to SSH banner */
u_int num_auth_methods;
- char *auth_methods[MAX_AUTH_METHODS];
+ char **auth_methods;
int fingerprint_hash;
+ int expose_userauth_info;
+ u_int64_t timing_secret;
+ char *sk_provider;
} ServerOptions;
/* Information about the incoming connection as used by Match */
@@ -198,7 +232,19 @@ struct connection_info {
const char *address; /* remote address */
const char *laddress; /* local address */
int lport; /* local port */
+ const char *rdomain; /* routing domain if available */
+ int test; /* test mode, allow some attributes to be
+ * unspecified */
+};
+
+/* List of included files for re-exec from the parsed configuration */
+struct include_item {
+ char *selector;
+ char *filename;
+ struct sshbuf *contents;
+ TAILQ_ENTRY(include_item) entry;
};
+TAILQ_HEAD(include_list, include_item);
/*
@@ -214,11 +260,16 @@ struct connection_info {
M_CP_STROPT(banner); \
M_CP_STROPT(trusted_user_ca_keys); \
M_CP_STROPT(revoked_keys_file); \
- M_CP_STROPT(authorized_principals_file); \
M_CP_STROPT(authorized_keys_command); \
M_CP_STROPT(authorized_keys_command_user); \
+ M_CP_STROPT(authorized_principals_file); \
+ M_CP_STROPT(authorized_principals_command); \
+ M_CP_STROPT(authorized_principals_command_user); \
M_CP_STROPT(hostbased_key_types); \
M_CP_STROPT(pubkey_key_types); \
+ M_CP_STROPT(ca_sign_algorithms); \
+ M_CP_STROPT(routing_domain); \
+ M_CP_STROPT(permit_user_env_whitelist); \
M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
M_CP_STRARRAYOPT(allow_users, num_allow_users); \
M_CP_STRARRAYOPT(deny_users, num_deny_users); \
@@ -226,21 +277,29 @@ struct connection_info {
M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \
M_CP_STRARRAYOPT(accept_env, num_accept_env); \
M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \
+ M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens); \
+ M_CP_STRARRAYOPT(permitted_listens, num_permitted_listens); \
} while (0)
-struct connection_info *get_connection_info(int, int);
+struct connection_info *get_connection_info(struct ssh *, int, int);
void initialize_server_options(ServerOptions *);
void fill_default_server_options(ServerOptions *);
int process_server_config_line(ServerOptions *, char *, const char *, int,
- int *, struct connection_info *);
-void load_server_config(const char *, Buffer *);
-void parse_server_config(ServerOptions *, const char *, Buffer *,
- struct connection_info *);
-void parse_server_match_config(ServerOptions *, struct connection_info *);
+ int *, struct connection_info *, struct include_list *includes);
+void process_permitopen(struct ssh *ssh, ServerOptions *options);
+void load_server_config(const char *, struct sshbuf *);
+void parse_server_config(ServerOptions *, const char *, struct sshbuf *,
+ struct include_list *includes, struct connection_info *);
+void parse_server_match_config(ServerOptions *,
+ struct include_list *includes, struct connection_info *);
int parse_server_match_testspec(struct connection_info *, char *);
int server_match_spec_complete(struct connection_info *);
void copy_set_server_options(ServerOptions *, ServerOptions *, int);
void dump_config(ServerOptions *);
char *derelativise_path(const char *);
+void servconf_add_hostkey(const char *, const int,
+ ServerOptions *, const char *path, int);
+void servconf_add_hostcert(const char *, const int,
+ ServerOptions *, const char *path);
#endif /* SERVCONF_H */
diff --git a/serverloop.c b/serverloop.c
index 306ac36b..340b19a5 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.178 2015/02/20 22:17:21 djm Exp $ */
+/* $OpenBSD: serverloop.c,v 1.222 2020/01/30 07:21:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -37,7 +37,6 @@
#include "includes.h"
-#include <sys/param.h> /* MIN MAX */
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
@@ -50,6 +49,7 @@
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
+#include <limits.h>
#include <signal.h>
#include <string.h>
#include <termios.h>
@@ -59,7 +59,7 @@
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "packet.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
@@ -67,9 +67,8 @@
#include "sshpty.h"
#include "channels.h"
#include "compat.h"
-#include "ssh1.h"
#include "ssh2.h"
-#include "key.h"
+#include "sshkey.h"
#include "cipher.h"
#include "kex.h"
#include "hostfile.h"
@@ -78,34 +77,15 @@
#include "dispatch.h"
#include "auth-options.h"
#include "serverloop.h"
-#include "roaming.h"
#include "ssherr.h"
extern ServerOptions options;
/* XXX */
extern Authctxt *the_authctxt;
+extern struct sshauthopt *auth_opts;
extern int use_privsep;
-static Buffer stdin_buffer; /* Buffer for stdin data. */
-static Buffer stdout_buffer; /* Buffer for stdout data. */
-static Buffer stderr_buffer; /* Buffer for stderr data. */
-static int fdin; /* Descriptor for stdin (for writing) */
-static int fdout; /* Descriptor for stdout (for reading);
- May be same number as fdin. */
-static int fderr; /* Descriptor for stderr. May be -1. */
-static long stdin_bytes = 0; /* Number of bytes written to stdin. */
-static long stdout_bytes = 0; /* Number of stdout bytes sent to client. */
-static long stderr_bytes = 0; /* Number of stderr bytes sent to client. */
-static long fdout_bytes = 0; /* Number of stdout bytes read from program. */
-static int stdin_eof = 0; /* EOF message received from client. */
-static int fdout_eof = 0; /* EOF encountered reading from fdout. */
-static int fderr_eof = 0; /* EOF encountered readung from fderr. */
-static int fdin_is_tty = 0; /* fdin points to a tty. */
-static int connection_in; /* Connection to client (input). */
-static int connection_out; /* Connection to client (output). */
-static int connection_closed = 0; /* Connection to client closed. */
-static u_int buffer_high; /* "Soft" max buffer size. */
static int no_more_sessions = 0; /* Disallow further sessions. */
/*
@@ -119,7 +99,21 @@ static volatile sig_atomic_t child_terminated = 0; /* The child has terminated.
static volatile sig_atomic_t received_sigterm = 0;
/* prototypes */
-static void server_init_dispatch(void);
+static void server_init_dispatch(struct ssh *);
+
+/* requested tunnel forwarding interface(s), shared with session.c */
+char *tun_fwd_ifnames = NULL;
+
+/* returns 1 if bind to specified port by specified user is permitted */
+static int
+bind_permitted(int port, uid_t uid)
+{
+ if (use_privsep)
+ return 1; /* allow system to decide */
+ if (port < IPPORT_RESERVED && uid != 0)
+ return 0;
+ return 1;
+}
/*
* we write to this pipe if a SIGCHLD is caught in order to avoid
@@ -129,7 +123,7 @@ static int notify_pipe[2];
static void
notify_setup(void)
{
- if (pipe(notify_pipe) < 0) {
+ 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)) {
@@ -163,7 +157,7 @@ notify_done(fd_set *readset)
if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset))
while (read(notify_pipe[0], &c, 1) != -1)
- debug2("notify_done: reading");
+ debug2("%s: reading", __func__);
}
/*ARGSUSED*/
@@ -172,9 +166,6 @@ sigchld_handler(int sig)
{
int save_errno = errno;
child_terminated = 1;
-#ifndef _UNICOS
- mysignal(SIGCHLD, sigchld_handler);
-#endif
notify_parent();
errno = save_errno;
}
@@ -186,72 +177,18 @@ sigterm_handler(int sig)
received_sigterm = sig;
}
-/*
- * Make packets from buffered stderr data, and buffer it for sending
- * to the client.
- */
-static void
-make_packets_from_stderr_data(void)
-{
- u_int len;
-
- /* Send buffered stderr data to the client. */
- while (buffer_len(&stderr_buffer) > 0 &&
- packet_not_very_much_data_to_write()) {
- len = buffer_len(&stderr_buffer);
- if (packet_is_interactive()) {
- if (len > 512)
- len = 512;
- } else {
- /* Keep the packets at reasonable size. */
- if (len > packet_get_maxsize())
- len = packet_get_maxsize();
- }
- packet_start(SSH_SMSG_STDERR_DATA);
- packet_put_string(buffer_ptr(&stderr_buffer), len);
- packet_send();
- buffer_consume(&stderr_buffer, len);
- stderr_bytes += len;
- }
-}
-
-/*
- * Make packets from buffered stdout data, and buffer it for sending to the
- * client.
- */
static void
-make_packets_from_stdout_data(void)
+client_alive_check(struct ssh *ssh)
{
- u_int len;
-
- /* Send buffered stdout data to the client. */
- while (buffer_len(&stdout_buffer) > 0 &&
- packet_not_very_much_data_to_write()) {
- len = buffer_len(&stdout_buffer);
- if (packet_is_interactive()) {
- if (len > 512)
- len = 512;
- } else {
- /* Keep the packets at reasonable size. */
- if (len > packet_get_maxsize())
- len = packet_get_maxsize();
- }
- packet_start(SSH_SMSG_STDOUT_DATA);
- packet_put_string(buffer_ptr(&stdout_buffer), len);
- packet_send();
- buffer_consume(&stdout_buffer, len);
- stdout_bytes += len;
- }
-}
-
-static void
-client_alive_check(void)
-{
- int channel_id;
+ char remote_id[512];
+ int r, channel_id;
/* timeout, check to see how many we have had */
- if (packet_inc_alive_timeouts() > options.client_alive_count_max) {
- logit("Timeout, client not responding.");
+ if (options.client_alive_count_max > 0 &&
+ ssh_packet_inc_alive_timeouts(ssh) >
+ options.client_alive_count_max) {
+ sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
+ logit("Timeout, client not responding from %s", remote_id);
cleanup_exit(255);
}
@@ -259,14 +196,18 @@ client_alive_check(void)
* send a bogus global/channel request with "wantreply",
* we should get back a failure
*/
- if ((channel_id = channel_find_open()) == -1) {
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring("keepalive@openssh.com");
- packet_put_char(1); /* boolean: want reply */
+ if ((channel_id = channel_find_open(ssh)) == -1) {
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "keepalive@openssh.com"))
+ != 0 ||
+ (r = sshpkt_put_u8(ssh, 1)) != 0) /* boolean: want reply */
+ fatal("%s: %s", __func__, ssh_err(r));
} else {
- channel_request_start(channel_id, "keepalive@openssh.com", 1);
+ channel_request_start(ssh, channel_id,
+ "keepalive@openssh.com", 1);
}
- packet_send();
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
}
/*
@@ -276,22 +217,25 @@ client_alive_check(void)
* for the duration of the wait (0 = infinite).
*/
static void
-wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
- u_int *nallocp, u_int64_t max_time_milliseconds)
+wait_until_can_do_something(struct ssh *ssh,
+ int connection_in, int connection_out,
+ fd_set **readsetp, fd_set **writesetp, int *maxfdp,
+ u_int *nallocp, u_int64_t max_time_ms)
{
struct timeval tv, *tvp;
int ret;
time_t minwait_secs = 0;
int client_alive_scheduled = 0;
- int program_alive_scheduled = 0;
+ /* time we last heard from the client OR sent a keepalive */
+ static time_t last_client_time;
/* Allocate and update select() masks for channel descriptors. */
- channel_prepare_select(readsetp, writesetp, maxfdp, nallocp,
- &minwait_secs, 0);
+ channel_prepare_select(ssh, readsetp, writesetp, maxfdp,
+ nallocp, &minwait_secs);
+ /* XXX need proper deadline system for rekey/client alive */
if (minwait_secs != 0)
- max_time_milliseconds = MIN(max_time_milliseconds,
- (u_int)minwait_secs * 1000);
+ max_time_ms = MINIMUM(max_time_ms, (u_int)minwait_secs * 1000);
/*
* if using client_alive, set the max timeout accordingly,
@@ -301,67 +245,43 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
* this could be randomized somewhat to make traffic
* analysis more difficult, but we're not doing it yet.
*/
- if (compat20 &&
- max_time_milliseconds == 0 && options.client_alive_interval) {
- client_alive_scheduled = 1;
- max_time_milliseconds =
- (u_int64_t)options.client_alive_interval * 1000;
+ if (options.client_alive_interval) {
+ uint64_t keepalive_ms =
+ (uint64_t)options.client_alive_interval * 1000;
+
+ if (max_time_ms == 0 || max_time_ms > keepalive_ms) {
+ max_time_ms = keepalive_ms;
+ client_alive_scheduled = 1;
+ }
}
- if (compat20) {
#if 0
- /* wrong: bad condition XXX */
- if (channel_not_very_much_buffered_data())
+ /* wrong: bad condition XXX */
+ if (channel_not_very_much_buffered_data())
#endif
- FD_SET(connection_in, *readsetp);
- } else {
- /*
- * Read packets from the client unless we have too much
- * buffered stdin or channel data.
- */
- if (buffer_len(&stdin_buffer) < buffer_high &&
- channel_not_very_much_buffered_data())
- FD_SET(connection_in, *readsetp);
- /*
- * If there is not too much data already buffered going to
- * the client, try to get some more data from the program.
- */
- if (packet_not_very_much_data_to_write()) {
- program_alive_scheduled = child_terminated;
- if (!fdout_eof)
- FD_SET(fdout, *readsetp);
- if (!fderr_eof)
- FD_SET(fderr, *readsetp);
- }
- /*
- * If we have buffered data, try to write some of that data
- * to the program.
- */
- if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
- FD_SET(fdin, *writesetp);
- }
+ FD_SET(connection_in, *readsetp);
notify_prepare(*readsetp);
/*
* If we have buffered packet data going to the client, mark that
* descriptor.
*/
- if (packet_have_data_to_write())
+ if (ssh_packet_have_data_to_write(ssh))
FD_SET(connection_out, *writesetp);
/*
* If child has terminated and there is enough buffer space to read
* from it, then read as much as is available and exit.
*/
- if (child_terminated && packet_not_very_much_data_to_write())
- if (max_time_milliseconds == 0 || client_alive_scheduled)
- max_time_milliseconds = 100;
+ if (child_terminated && ssh_packet_not_very_much_data_to_write(ssh))
+ if (max_time_ms == 0 || client_alive_scheduled)
+ max_time_ms = 100;
- if (max_time_milliseconds == 0)
+ if (max_time_ms == 0)
tvp = NULL;
else {
- tv.tv_sec = max_time_milliseconds / 1000;
- tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
+ tv.tv_sec = max_time_ms / 1000;
+ tv.tv_usec = 1000 * (max_time_ms % 1000);
tvp = &tv;
}
@@ -373,14 +293,19 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
memset(*writesetp, 0, *nallocp);
if (errno != EINTR)
error("select: %.100s", strerror(errno));
- } else {
- if (ret == 0 && client_alive_scheduled)
- client_alive_check();
- if (!compat20 && program_alive_scheduled && fdin_is_tty) {
- if (!fdout_eof)
- FD_SET(fdout, *readsetp);
- if (!fderr_eof)
- FD_SET(fderr, *readsetp);
+ } else if (client_alive_scheduled) {
+ time_t now = monotime();
+
+ /*
+ * If the select timed out, or returned for some other reason
+ * but we haven't heard from the client in time, send keepalive.
+ */
+ if (ret == 0 || (last_client_time != 0 && last_client_time +
+ options.client_alive_interval <= now)) {
+ client_alive_check(ssh);
+ last_client_time = now;
+ } else if (FD_ISSET(connection_in, *readsetp)) {
+ last_client_time = now;
}
}
@@ -391,415 +316,64 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
* Processes input from the client and the program. Input data is stored
* in buffers and processed later.
*/
-static void
-process_input(fd_set *readset)
+static int
+process_input(struct ssh *ssh, fd_set *readset, int connection_in)
{
- int len;
+ int r, len;
char buf[16384];
/* Read and buffer any input data from the client. */
if (FD_ISSET(connection_in, readset)) {
- int cont = 0;
- len = roaming_read(connection_in, buf, sizeof(buf), &cont);
+ len = read(connection_in, buf, sizeof(buf));
if (len == 0) {
- if (cont)
- return;
- verbose("Connection closed by %.100s",
- get_remote_ipaddr());
- connection_closed = 1;
- if (compat20)
- return;
- cleanup_exit(255);
- } else if (len < 0) {
+ verbose("Connection closed by %.100s port %d",
+ 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: %.100s",
- get_remote_ipaddr(), strerror(errno));
+ "%.100s port %d: %.100s",
+ ssh_remote_ipaddr(ssh),
+ ssh_remote_port(ssh), strerror(errno));
cleanup_exit(255);
}
} else {
/* Buffer any received data. */
- packet_process_incoming(buf, len);
- }
- }
- if (compat20)
- return;
-
- /* Read and buffer any available stdout data from the program. */
- if (!fdout_eof && FD_ISSET(fdout, readset)) {
- errno = 0;
- len = read(fdout, buf, sizeof(buf));
- if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
- errno == EWOULDBLOCK) && !child_terminated))) {
- /* do nothing */
-#ifndef PTY_ZEROREAD
- } else if (len <= 0) {
-#else
- } else if ((!isatty(fdout) && len <= 0) ||
- (isatty(fdout) && (len < 0 || (len == 0 && errno != 0)))) {
-#endif
- fdout_eof = 1;
- } else {
- buffer_append(&stdout_buffer, buf, len);
- fdout_bytes += len;
- }
- }
- /* Read and buffer any available stderr data from the program. */
- if (!fderr_eof && FD_ISSET(fderr, readset)) {
- errno = 0;
- len = read(fderr, buf, sizeof(buf));
- if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
- errno == EWOULDBLOCK) && !child_terminated))) {
- /* do nothing */
-#ifndef PTY_ZEROREAD
- } else if (len <= 0) {
-#else
- } else if ((!isatty(fderr) && len <= 0) ||
- (isatty(fderr) && (len < 0 || (len == 0 && errno != 0)))) {
-#endif
- fderr_eof = 1;
- } else {
- buffer_append(&stderr_buffer, buf, len);
+ if ((r = ssh_packet_process_incoming(ssh, buf, len))
+ != 0)
+ fatal("%s: ssh_packet_process_incoming: %s",
+ __func__, ssh_err(r));
}
}
+ return 0;
}
/*
* Sends data from internal buffers to client program stdin.
*/
static void
-process_output(fd_set *writeset)
+process_output(struct ssh *ssh, fd_set *writeset, int connection_out)
{
- struct termios tio;
- u_char *data;
- u_int dlen;
- int len;
-
- /* Write buffered data to program stdin. */
- if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) {
- data = buffer_ptr(&stdin_buffer);
- dlen = buffer_len(&stdin_buffer);
- len = write(fdin, data, dlen);
- if (len < 0 &&
- (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) {
- /* do nothing */
- } else if (len <= 0) {
- if (fdin != fdout)
- close(fdin);
- else
- shutdown(fdin, SHUT_WR); /* We will no longer send. */
- fdin = -1;
- } else {
- /* Successful write. */
- if (fdin_is_tty && dlen >= 1 && data[0] != '\r' &&
- tcgetattr(fdin, &tio) == 0 &&
- !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
- /*
- * Simulate echo to reduce the impact of
- * traffic analysis
- */
- packet_send_ignore(len);
- packet_send();
- }
- /* Consume the data from the buffer. */
- buffer_consume(&stdin_buffer, len);
- /* Update the count of bytes written to the program. */
- stdin_bytes += len;
+ int r;
+
+ /* Send any buffered packet data to the client. */
+ if (FD_ISSET(connection_out, writeset)) {
+ if ((r = ssh_packet_write_poll(ssh)) != 0) {
+ sshpkt_fatal(ssh, r, "%s: ssh_packet_write_poll",
+ __func__);
}
}
- /* Send any buffered packet data to the client. */
- if (FD_ISSET(connection_out, writeset))
- packet_write_poll();
}
-/*
- * Wait until all buffered output has been sent to the client.
- * This is used when the program terminates.
- */
static void
-drain_output(void)
+process_buffered_input_packets(struct ssh *ssh)
{
- /* Send any buffered stdout data to the client. */
- if (buffer_len(&stdout_buffer) > 0) {
- packet_start(SSH_SMSG_STDOUT_DATA);
- packet_put_string(buffer_ptr(&stdout_buffer),
- buffer_len(&stdout_buffer));
- packet_send();
- /* Update the count of sent bytes. */
- stdout_bytes += buffer_len(&stdout_buffer);
- }
- /* Send any buffered stderr data to the client. */
- if (buffer_len(&stderr_buffer) > 0) {
- packet_start(SSH_SMSG_STDERR_DATA);
- packet_put_string(buffer_ptr(&stderr_buffer),
- buffer_len(&stderr_buffer));
- packet_send();
- /* Update the count of sent bytes. */
- stderr_bytes += buffer_len(&stderr_buffer);
- }
- /* Wait until all buffered data has been written to the client. */
- packet_write_wait();
+ ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, NULL);
}
static void
-process_buffered_input_packets(void)
-{
- dispatch_run(DISPATCH_NONBLOCK, NULL, active_state);
-}
-
-/*
- * Performs the interactive session. This handles data transmission between
- * the client and the program. Note that the notion of stdin, stdout, and
- * stderr in this function is sort of reversed: this function writes to
- * stdin (of the child program), and reads from stdout and stderr (of the
- * child program).
- */
-void
-server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
-{
- fd_set *readset = NULL, *writeset = NULL;
- int max_fd = 0;
- u_int nalloc = 0;
- int wait_status; /* Status returned by wait(). */
- pid_t wait_pid; /* pid returned by wait(). */
- int waiting_termination = 0; /* Have displayed waiting close message. */
- u_int64_t max_time_milliseconds;
- u_int previous_stdout_buffer_bytes;
- u_int stdout_buffer_bytes;
- int type;
-
- debug("Entering interactive session.");
-
- /* Initialize the SIGCHLD kludge. */
- child_terminated = 0;
- mysignal(SIGCHLD, sigchld_handler);
-
- if (!use_privsep) {
- signal(SIGTERM, sigterm_handler);
- signal(SIGINT, sigterm_handler);
- signal(SIGQUIT, sigterm_handler);
- }
-
- /* Initialize our global variables. */
- fdin = fdin_arg;
- fdout = fdout_arg;
- fderr = fderr_arg;
-
- /* nonblocking IO */
- set_nonblock(fdin);
- set_nonblock(fdout);
- /* we don't have stderr for interactive terminal sessions, see below */
- if (fderr != -1)
- set_nonblock(fderr);
-
- if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin))
- fdin_is_tty = 1;
-
- connection_in = packet_get_connection_in();
- connection_out = packet_get_connection_out();
-
- notify_setup();
-
- previous_stdout_buffer_bytes = 0;
-
- /* Set approximate I/O buffer size. */
- if (packet_is_interactive())
- buffer_high = 4096;
- else
- buffer_high = 64 * 1024;
-
-#if 0
- /* Initialize max_fd to the maximum of the known file descriptors. */
- max_fd = MAX(connection_in, connection_out);
- max_fd = MAX(max_fd, fdin);
- max_fd = MAX(max_fd, fdout);
- if (fderr != -1)
- max_fd = MAX(max_fd, fderr);
-#endif
-
- /* Initialize Initialize buffers. */
- buffer_init(&stdin_buffer);
- buffer_init(&stdout_buffer);
- buffer_init(&stderr_buffer);
-
- /*
- * If we have no separate fderr (which is the case when we have a pty
- * - there we cannot make difference between data sent to stdout and
- * stderr), indicate that we have seen an EOF from stderr. This way
- * we don't need to check the descriptor everywhere.
- */
- if (fderr == -1)
- fderr_eof = 1;
-
- server_init_dispatch();
-
- /* Main loop of the server for the interactive session mode. */
- for (;;) {
-
- /* Process buffered packets from the client. */
- process_buffered_input_packets();
-
- /*
- * If we have received eof, and there is no more pending
- * input data, cause a real eof by closing fdin.
- */
- if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) {
- if (fdin != fdout)
- close(fdin);
- else
- shutdown(fdin, SHUT_WR); /* We will no longer send. */
- fdin = -1;
- }
- /* Make packets from buffered stderr data to send to the client. */
- make_packets_from_stderr_data();
-
- /*
- * Make packets from buffered stdout data to send to the
- * client. If there is very little to send, this arranges to
- * not send them now, but to wait a short while to see if we
- * are getting more data. This is necessary, as some systems
- * wake up readers from a pty after each separate character.
- */
- max_time_milliseconds = 0;
- stdout_buffer_bytes = buffer_len(&stdout_buffer);
- if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
- stdout_buffer_bytes != previous_stdout_buffer_bytes) {
- /* try again after a while */
- max_time_milliseconds = 10;
- } else {
- /* Send it now. */
- make_packets_from_stdout_data();
- }
- previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
-
- /* Send channel data to the client. */
- if (packet_not_very_much_data_to_write())
- channel_output_poll();
-
- /*
- * Bail out of the loop if the program has closed its output
- * descriptors, and we have no more data to send to the
- * client, and there is no pending buffered data.
- */
- if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
- buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) {
- if (!channel_still_open())
- break;
- if (!waiting_termination) {
- const char *s = "Waiting for forwarded connections to terminate...\r\n";
- char *cp;
- waiting_termination = 1;
- buffer_append(&stderr_buffer, s, strlen(s));
-
- /* Display list of open channels. */
- cp = channel_open_message();
- buffer_append(&stderr_buffer, cp, strlen(cp));
- free(cp);
- }
- }
- max_fd = MAX(connection_in, connection_out);
- max_fd = MAX(max_fd, fdin);
- max_fd = MAX(max_fd, fdout);
- max_fd = MAX(max_fd, fderr);
- max_fd = MAX(max_fd, notify_pipe[0]);
-
- /* Sleep in select() until we can do something. */
- wait_until_can_do_something(&readset, &writeset, &max_fd,
- &nalloc, max_time_milliseconds);
-
- if (received_sigterm) {
- logit("Exiting on signal %d", (int)received_sigterm);
- /* Clean up sessions, utmp, etc. */
- cleanup_exit(255);
- }
-
- /* Process any channel events. */
- channel_after_select(readset, writeset);
-
- /* Process input from the client and from program stdout/stderr. */
- process_input(readset);
-
- /* Process output to the client and to program stdin. */
- process_output(writeset);
- }
- free(readset);
- free(writeset);
-
- /* Cleanup and termination code. */
-
- /* Wait until all output has been sent to the client. */
- drain_output();
-
- debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
- stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
-
- /* Free and clear the buffers. */
- buffer_free(&stdin_buffer);
- buffer_free(&stdout_buffer);
- buffer_free(&stderr_buffer);
-
- /* Close the file descriptors. */
- if (fdout != -1)
- close(fdout);
- fdout = -1;
- fdout_eof = 1;
- if (fderr != -1)
- close(fderr);
- fderr = -1;
- fderr_eof = 1;
- if (fdin != -1)
- close(fdin);
- fdin = -1;
-
- channel_free_all();
-
- /* We no longer want our SIGCHLD handler to be called. */
- mysignal(SIGCHLD, SIG_DFL);
-
- while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0)
- if (errno != EINTR)
- packet_disconnect("wait: %.100s", strerror(errno));
- if (wait_pid != pid)
- error("Strange, wait returned pid %ld, expected %ld",
- (long)wait_pid, (long)pid);
-
- /* Check if it exited normally. */
- if (WIFEXITED(wait_status)) {
- /* Yes, normal exit. Get exit status and send it to the client. */
- debug("Command exited with status %d.", WEXITSTATUS(wait_status));
- packet_start(SSH_SMSG_EXITSTATUS);
- packet_put_int(WEXITSTATUS(wait_status));
- packet_send();
- packet_write_wait();
-
- /*
- * Wait for exit confirmation. Note that there might be
- * other packets coming before it; however, the program has
- * already died so we just ignore them. The client is
- * supposed to respond with the confirmation when it receives
- * the exit status.
- */
- do {
- type = packet_read();
- }
- while (type != SSH_CMSG_EXIT_CONFIRMATION);
-
- debug("Received exit confirmation.");
- return;
- }
- /* Check if the program terminated due to a signal. */
- if (WIFSIGNALED(wait_status))
- packet_disconnect("Command terminated on signal %d.",
- WTERMSIG(wait_status));
-
- /* Some weird exit cause. Just exit. */
- packet_disconnect("wait returned status %04x.", wait_status);
- /* NOTREACHED */
-}
-
-static void
-collect_children(void)
+collect_children(struct ssh *ssh)
{
pid_t pid;
sigset_t oset, nset;
@@ -812,56 +386,58 @@ collect_children(void)
if (child_terminated) {
debug("Received SIGCHLD.");
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
- (pid < 0 && errno == EINTR))
+ (pid == -1 && errno == EINTR))
if (pid > 0)
- session_close_by_pid(pid, status);
+ session_close_by_pid(ssh, pid, status);
child_terminated = 0;
}
sigprocmask(SIG_SETMASK, &oset, NULL);
}
void
-server_loop2(Authctxt *authctxt)
+server_loop2(struct ssh *ssh, Authctxt *authctxt)
{
fd_set *readset = NULL, *writeset = NULL;
- int rekeying = 0, max_fd;
- u_int nalloc = 0;
+ int max_fd;
+ u_int nalloc = 0, connection_in, connection_out;
u_int64_t rekey_timeout_ms = 0;
debug("Entering interactive session for SSH2.");
- mysignal(SIGCHLD, sigchld_handler);
+ ssh_signal(SIGCHLD, sigchld_handler);
child_terminated = 0;
- connection_in = packet_get_connection_in();
- connection_out = packet_get_connection_out();
+ connection_in = ssh_packet_get_connection_in(ssh);
+ connection_out = ssh_packet_get_connection_out(ssh);
if (!use_privsep) {
- signal(SIGTERM, sigterm_handler);
- signal(SIGINT, sigterm_handler);
- signal(SIGQUIT, sigterm_handler);
+ ssh_signal(SIGTERM, sigterm_handler);
+ ssh_signal(SIGINT, sigterm_handler);
+ ssh_signal(SIGQUIT, sigterm_handler);
}
notify_setup();
- max_fd = MAX(connection_in, connection_out);
- max_fd = MAX(max_fd, notify_pipe[0]);
+ max_fd = MAXIMUM(connection_in, connection_out);
+ max_fd = MAXIMUM(max_fd, notify_pipe[0]);
- server_init_dispatch();
+ server_init_dispatch(ssh);
for (;;) {
- process_buffered_input_packets();
-
- rekeying = (active_state->kex != NULL && !active_state->kex->done);
-
- if (!rekeying && packet_not_very_much_data_to_write())
- channel_output_poll();
- if (options.rekey_interval > 0 && compat20 && !rekeying)
- rekey_timeout_ms = packet_get_rekey_timeout() * 1000;
- else
+ process_buffered_input_packets(ssh);
+
+ if (!ssh_packet_is_rekeying(ssh) &&
+ ssh_packet_not_very_much_data_to_write(ssh))
+ channel_output_poll(ssh);
+ if (options.rekey_interval > 0 &&
+ !ssh_packet_is_rekeying(ssh)) {
+ rekey_timeout_ms = ssh_packet_get_rekey_timeout(ssh) *
+ 1000;
+ } else {
rekey_timeout_ms = 0;
+ }
- wait_until_can_do_something(&readset, &writeset, &max_fd,
- &nalloc, rekey_timeout_ms);
+ wait_until_can_do_something(ssh, connection_in, connection_out,
+ &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms);
if (received_sigterm) {
logit("Exiting on signal %d", (int)received_sigterm);
@@ -869,34 +445,27 @@ server_loop2(Authctxt *authctxt)
cleanup_exit(255);
}
- collect_children();
- if (!rekeying) {
- channel_after_select(readset, writeset);
- if (packet_need_rekeying()) {
- debug("need rekeying");
- active_state->kex->done = 0;
- kex_send_kexinit(active_state);
- }
- }
- process_input(readset);
- if (connection_closed)
+ collect_children(ssh);
+ if (!ssh_packet_is_rekeying(ssh))
+ channel_after_select(ssh, readset, writeset);
+ if (process_input(ssh, readset, connection_in) < 0)
break;
- process_output(writeset);
+ process_output(ssh, writeset, connection_out);
}
- collect_children();
+ collect_children(ssh);
free(readset);
free(writeset);
/* free all channels, no more reads and writes */
- channel_free_all();
+ channel_free_all(ssh);
/* free remaining sessions, e.g. remove wtmp entries */
- session_destroy_all(NULL);
+ session_destroy_all(ssh, NULL);
}
static int
-server_input_keep_alive(int type, u_int32_t seq, void *ctxt)
+server_input_keep_alive(int type, u_int32_t seq, struct ssh *ssh)
{
debug("Got %d/%u for keepalive", type, seq);
/*
@@ -904,109 +473,88 @@ server_input_keep_alive(int type, u_int32_t seq, void *ctxt)
* even if this was generated by something other than
* the bogus CHANNEL_REQUEST we send for keepalives.
*/
- packet_set_alive_timeouts(0);
- return 0;
-}
-
-static int
-server_input_stdin_data(int type, u_int32_t seq, void *ctxt)
-{
- char *data;
- u_int data_len;
-
- /* Stdin data from the client. Append it to the buffer. */
- /* Ignore any data if the client has closed stdin. */
- if (fdin == -1)
- return 0;
- data = packet_get_string(&data_len);
- packet_check_eom();
- buffer_append(&stdin_buffer, data, data_len);
- explicit_bzero(data, data_len);
- free(data);
- return 0;
-}
-
-static int
-server_input_eof(int type, u_int32_t seq, void *ctxt)
-{
- /*
- * Eof from the client. The stdin descriptor to the
- * program will be closed when all buffered data has
- * drained.
- */
- debug("EOF received for stdin.");
- packet_check_eom();
- stdin_eof = 1;
- return 0;
-}
-
-static int
-server_input_window_size(int type, u_int32_t seq, void *ctxt)
-{
- u_int row = packet_get_int();
- u_int col = packet_get_int();
- u_int xpixel = packet_get_int();
- u_int ypixel = packet_get_int();
-
- debug("Window change received.");
- packet_check_eom();
- if (fdin != -1)
- pty_change_window_size(fdin, row, col, xpixel, ypixel);
+ ssh_packet_set_alive_timeouts(ssh, 0);
return 0;
}
static Channel *
-server_request_direct_tcpip(void)
+server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg)
{
Channel *c = NULL;
- char *target, *originator;
- u_short target_port, originator_port;
-
- target = packet_get_string(NULL);
- target_port = packet_get_int();
- originator = packet_get_string(NULL);
- originator_port = packet_get_int();
- packet_check_eom();
-
- debug("server_request_direct_tcpip: originator %s port %d, target %s "
- "port %d", originator, originator_port, target, target_port);
+ char *target = NULL, *originator = NULL;
+ u_int target_port = 0, originator_port = 0;
+ int r;
+
+ if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &target_port)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+ if (target_port > 0xFFFF) {
+ error("%s: invalid target port", __func__);
+ *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
+ goto out;
+ }
+ if (originator_port > 0xFFFF) {
+ error("%s: invalid originator port", __func__);
+ *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
+ goto out;
+ }
+
+ debug("%s: originator %s port %u, target %s port %u", __func__,
+ originator, originator_port, target, target_port);
/* XXX fine grained permissions */
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
- !no_port_forwarding_flag) {
- c = channel_connect_to_port(target, target_port,
- "direct-tcpip", "direct-tcpip");
+ auth_opts->permit_port_forwarding_flag &&
+ !options.disable_forwarding) {
+ c = channel_connect_to_port(ssh, target, target_port,
+ "direct-tcpip", "direct-tcpip", reason, errmsg);
} else {
logit("refused local port forward: "
"originator %s port %d, target %s port %d",
originator, originator_port, target, target_port);
+ if (reason != NULL)
+ *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
}
+ out:
free(originator);
free(target);
-
return c;
}
static Channel *
-server_request_direct_streamlocal(void)
+server_request_direct_streamlocal(struct ssh *ssh)
{
Channel *c = NULL;
- char *target, *originator;
- u_short originator_port;
+ char *target = NULL, *originator = NULL;
+ u_int originator_port = 0;
+ struct passwd *pw = the_authctxt->pw;
+ int r;
+
+ if (pw == NULL || !the_authctxt->valid)
+ fatal("%s: no/invalid user", __func__);
- target = packet_get_string(NULL);
- originator = packet_get_string(NULL);
- originator_port = packet_get_int();
- packet_check_eom();
+ if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+ if (originator_port > 0xFFFF) {
+ error("%s: invalid originator port", __func__);
+ goto out;
+ }
- debug("server_request_direct_streamlocal: originator %s port %d, target %s",
+ debug("%s: originator %s port %d, target %s", __func__,
originator, originator_port, target);
/* XXX fine grained permissions */
if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
- !no_port_forwarding_flag) {
- c = channel_connect_to_path(target,
+ auth_opts->permit_port_forwarding_flag &&
+ !options.disable_forwarding && (pw->pw_uid == 0 || use_privsep)) {
+ c = channel_connect_to_path(ssh, target,
"direct-streamlocal@openssh.com", "direct-streamlocal");
} else {
logit("refused streamlocal port forward: "
@@ -1014,69 +562,94 @@ server_request_direct_streamlocal(void)
originator, originator_port, target);
}
+out:
free(originator);
free(target);
-
return c;
}
static Channel *
-server_request_tun(void)
+server_request_tun(struct ssh *ssh)
{
Channel *c = NULL;
- int mode, tun;
- int sock;
+ u_int mode, tun;
+ int r, sock;
+ char *tmp, *ifname = NULL;
- mode = packet_get_int();
+ if ((r = sshpkt_get_u32(ssh, &mode)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse mode", __func__);
switch (mode) {
case SSH_TUNMODE_POINTOPOINT:
case SSH_TUNMODE_ETHERNET:
break;
default:
- packet_send_debug("Unsupported tunnel device mode.");
+ ssh_packet_send_debug(ssh, "Unsupported tunnel device mode.");
return NULL;
}
if ((options.permit_tun & mode) == 0) {
- packet_send_debug("Server has rejected tunnel device "
+ ssh_packet_send_debug(ssh, "Server has rejected tunnel device "
"forwarding");
return NULL;
}
- tun = packet_get_int();
- if (forced_tun_device != -1) {
- if (tun != SSH_TUNID_ANY && forced_tun_device != tun)
+ if ((r = sshpkt_get_u32(ssh, &tun)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse device", __func__);
+ if (tun > INT_MAX) {
+ debug("%s: invalid tun", __func__);
+ goto done;
+ }
+ if (auth_opts->force_tun_device != -1) {
+ if (tun != SSH_TUNID_ANY &&
+ auth_opts->force_tun_device != (int)tun)
goto done;
- tun = forced_tun_device;
+ tun = auth_opts->force_tun_device;
}
- sock = tun_open(tun, mode);
+ sock = tun_open(tun, mode, &ifname);
if (sock < 0)
goto done;
- c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
+ debug("Tunnel forwarding using interface %s", ifname);
+
+ c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
c->datagram = 1;
#if defined(SSH_TUN_FILTER)
if (mode == SSH_TUNMODE_POINTOPOINT)
- channel_register_filter(c->self, sys_tun_infilter,
+ channel_register_filter(ssh, c->self, sys_tun_infilter,
sys_tun_outfilter, NULL, NULL);
#endif
+ /*
+ * Update the list of names exposed to the session
+ * XXX remove these if the tunnels are closed (won't matter
+ * much if they are already in the environment though)
+ */
+ tmp = tun_fwd_ifnames;
+ xasprintf(&tun_fwd_ifnames, "%s%s%s",
+ tun_fwd_ifnames == NULL ? "" : tun_fwd_ifnames,
+ tun_fwd_ifnames == NULL ? "" : ",",
+ ifname);
+ free(tmp);
+ free(ifname);
+
done:
if (c == NULL)
- packet_send_debug("Failed to open the tunnel device.");
+ ssh_packet_send_debug(ssh, "Failed to open the tunnel device.");
return c;
}
static Channel *
-server_request_session(void)
+server_request_session(struct ssh *ssh)
{
Channel *c;
+ int r;
debug("input_session_request");
- packet_check_eom();
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
if (no_more_sessions) {
- packet_disconnect("Possible attack: attempt to open a session "
- "after additional sessions disabled");
+ ssh_packet_disconnect(ssh, "Possible attack: attempt to open a "
+ "session after additional sessions disabled");
}
/*
@@ -1085,79 +658,84 @@ server_request_session(void)
* SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
* CHANNEL_REQUEST messages is registered.
*/
- c = channel_new("session", SSH_CHANNEL_LARVAL,
+ c = channel_new(ssh, "session", SSH_CHANNEL_LARVAL,
-1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
0, "server-session", 1);
if (session_open(the_authctxt, c->self) != 1) {
debug("session open failed, free channel %d", c->self);
- channel_free(c);
+ channel_free(ssh, c);
return NULL;
}
- channel_register_cleanup(c->self, session_close_by_channel, 0);
+ channel_register_cleanup(ssh, c->self, session_close_by_channel, 0);
return c;
}
static int
-server_input_channel_open(int type, u_int32_t seq, void *ctxt)
+server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c = NULL;
- char *ctype;
- int rchan;
- u_int rmaxpack, rwindow, len;
-
- ctype = packet_get_string(&len);
- rchan = packet_get_int();
- rwindow = packet_get_int();
- rmaxpack = packet_get_int();
-
- debug("server_input_channel_open: ctype %s rchan %d win %d max %d",
+ char *ctype = NULL;
+ const char *errmsg = NULL;
+ int r, reason = SSH2_OPEN_CONNECT_FAILED;
+ u_int rchan = 0, rmaxpack = 0, rwindow = 0;
+
+ if ((r = sshpkt_get_cstring(ssh, &ctype, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &rchan)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &rwindow)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+ debug("%s: ctype %s rchan %u win %u max %u", __func__,
ctype, rchan, rwindow, rmaxpack);
if (strcmp(ctype, "session") == 0) {
- c = server_request_session();
+ c = server_request_session(ssh);
} else if (strcmp(ctype, "direct-tcpip") == 0) {
- c = server_request_direct_tcpip();
+ c = server_request_direct_tcpip(ssh, &reason, &errmsg);
} else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) {
- c = server_request_direct_streamlocal();
+ c = server_request_direct_streamlocal(ssh);
} else if (strcmp(ctype, "tun@openssh.com") == 0) {
- c = server_request_tun();
+ c = server_request_tun(ssh);
}
if (c != NULL) {
- debug("server_input_channel_open: confirm %s", ctype);
+ debug("%s: confirm %s", __func__, ctype);
c->remote_id = rchan;
+ c->have_remote_id = 1;
c->remote_window = rwindow;
c->remote_maxpacket = rmaxpack;
if (c->type != SSH_CHANNEL_CONNECTING) {
- packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(c->remote_id);
- packet_put_int(c->self);
- packet_put_int(c->local_window);
- packet_put_int(c->local_maxpacket);
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ sshpkt_fatal(ssh, r,
+ "%s: send open confirm", __func__);
+ }
}
} else {
- debug("server_input_channel_open: failure %s", ctype);
- packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(rchan);
- packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
- if (!(datafellows & SSH_BUG_OPENFAILURE)) {
- packet_put_cstring("open failed");
- packet_put_cstring("");
+ debug("%s: failure %s", __func__, 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 ||
+ (r = sshpkt_put_cstring(ssh, errmsg ? errmsg : "open failed")) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ sshpkt_fatal(ssh, r,
+ "%s: send open failure", __func__);
}
- packet_send();
}
free(ctype);
return 0;
}
static int
-server_input_hostkeys_prove(struct sshbuf **respp)
+server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
{
- struct ssh *ssh = active_state; /* XXX */
struct sshbuf *resp = NULL;
struct sshbuf *sigbuf = NULL;
struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL;
- int r, ndx, success = 0;
+ int r, ndx, kexsigtype, use_kexsigtype, success = 0;
const u_char *blob;
u_char *sig = 0;
size_t blen, slen;
@@ -1165,6 +743,8 @@ server_input_hostkeys_prove(struct sshbuf **respp)
if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
+ kexsigtype = sshkey_type_plain(
+ sshkey_type_from_name(ssh->kex->hostkey_alg));
while (ssh_packet_remaining(ssh) > 0) {
sshkey_free(key);
key = NULL;
@@ -1195,13 +775,20 @@ server_input_hostkeys_prove(struct sshbuf **respp)
sshbuf_reset(sigbuf);
free(sig);
sig = NULL;
+ /*
+ * For RSA keys, prefer to use the signature type negotiated
+ * during KEX to the default (SHA1).
+ */
+ use_kexsigtype = kexsigtype == KEY_RSA &&
+ sshkey_type_plain(key->type) == KEY_RSA;
if ((r = sshbuf_put_cstring(sigbuf,
"hostkeys-prove-00@openssh.com")) != 0 ||
(r = sshbuf_put_string(sigbuf,
ssh->kex->session_id, ssh->kex->session_id_len)) != 0 ||
(r = sshkey_puts(key, sigbuf)) != 0 ||
- (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen,
- sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), 0)) != 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));
@@ -1221,198 +808,175 @@ server_input_hostkeys_prove(struct sshbuf **respp)
}
static int
-server_input_global_request(int type, u_int32_t seq, void *ctxt)
+server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
{
- char *rtype;
- int want_reply;
+ char *rtype = NULL;
+ u_char want_reply = 0;
int r, success = 0, allocated_listen_port = 0;
+ u_int port = 0;
struct sshbuf *resp = NULL;
+ struct passwd *pw = the_authctxt->pw;
+ struct Forward fwd;
+
+ memset(&fwd, 0, sizeof(fwd));
+ if (pw == NULL || !the_authctxt->valid)
+ fatal("%s: no/invalid user", __func__);
- rtype = packet_get_string(NULL);
- want_reply = packet_get_char();
- debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply);
+ if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
+ (r = sshpkt_get_u8(ssh, &want_reply)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+ debug("%s: rtype %s want_reply %d", __func__, rtype, want_reply);
/* -R style forwarding */
if (strcmp(rtype, "tcpip-forward") == 0) {
- struct passwd *pw;
- struct Forward fwd;
-
- pw = the_authctxt->pw;
- if (pw == NULL || !the_authctxt->valid)
- fatal("server_input_global_request: no/invalid user");
- memset(&fwd, 0, sizeof(fwd));
- fwd.listen_host = packet_get_string(NULL);
- fwd.listen_port = (u_short)packet_get_int();
- debug("server_input_global_request: tcpip-forward listen %s port %d",
- fwd.listen_host, fwd.listen_port);
-
+ if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &port)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse tcpip-forward", __func__);
+ debug("%s: tcpip-forward listen %s port %u", __func__,
+ fwd.listen_host, port);
+ if (port <= INT_MAX)
+ fwd.listen_port = (int)port;
/* check permissions */
- if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
- no_port_forwarding_flag ||
- (!want_reply && fwd.listen_port == 0)
-#ifndef NO_IPPORT_RESERVED_CONCEPT
- || (fwd.listen_port != 0 && fwd.listen_port < IPPORT_RESERVED &&
- pw->pw_uid != 0)
-#endif
- ) {
+ if (port > INT_MAX ||
+ (options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
+ !auth_opts->permit_port_forwarding_flag ||
+ options.disable_forwarding ||
+ (!want_reply && fwd.listen_port == 0) ||
+ (fwd.listen_port != 0 &&
+ !bind_permitted(fwd.listen_port, pw->pw_uid))) {
success = 0;
- packet_send_debug("Server has disabled port forwarding.");
+ ssh_packet_send_debug(ssh, "Server has disabled port forwarding.");
} else {
/* Start listening on the port */
- success = channel_setup_remote_fwd_listener(&fwd,
+ success = channel_setup_remote_fwd_listener(ssh, &fwd,
&allocated_listen_port, &options.fwd_opts);
}
- free(fwd.listen_host);
if ((resp = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
- if ((r = sshbuf_put_u32(resp, allocated_listen_port)) != 0)
+ if (allocated_listen_port != 0 &&
+ (r = sshbuf_put_u32(resp, allocated_listen_port)) != 0)
fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r));
} else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
- struct Forward fwd;
+ if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &port)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse cancel-tcpip-forward", __func__);
- memset(&fwd, 0, sizeof(fwd));
- fwd.listen_host = packet_get_string(NULL);
- fwd.listen_port = (u_short)packet_get_int();
debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
- fwd.listen_host, fwd.listen_port);
-
- success = channel_cancel_rport_listener(&fwd);
- free(fwd.listen_host);
+ fwd.listen_host, port);
+ if (port <= INT_MAX) {
+ fwd.listen_port = (int)port;
+ success = channel_cancel_rport_listener(ssh, &fwd);
+ }
} else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) {
- struct Forward fwd;
-
- memset(&fwd, 0, sizeof(fwd));
- fwd.listen_path = packet_get_string(NULL);
- debug("server_input_global_request: streamlocal-forward listen path %s",
+ if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse streamlocal-forward@openssh.com", __func__);
+ debug("%s: streamlocal-forward listen path %s", __func__,
fwd.listen_path);
/* check permissions */
if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0
- || no_port_forwarding_flag) {
+ || !auth_opts->permit_port_forwarding_flag ||
+ options.disable_forwarding ||
+ (pw->pw_uid != 0 && !use_privsep)) {
success = 0;
- packet_send_debug("Server has disabled port forwarding.");
+ ssh_packet_send_debug(ssh, "Server has disabled "
+ "streamlocal forwarding.");
} else {
/* Start listening on the socket */
- success = channel_setup_remote_fwd_listener(
+ success = channel_setup_remote_fwd_listener(ssh,
&fwd, NULL, &options.fwd_opts);
}
- free(fwd.listen_path);
} else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) {
- struct Forward fwd;
-
- memset(&fwd, 0, sizeof(fwd));
- fwd.listen_path = packet_get_string(NULL);
+ if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse cancel-streamlocal-forward@openssh.com", __func__);
debug("%s: cancel-streamlocal-forward path %s", __func__,
fwd.listen_path);
- success = channel_cancel_rport_listener(&fwd);
- free(fwd.listen_path);
+ success = channel_cancel_rport_listener(ssh, &fwd);
} else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
no_more_sessions = 1;
success = 1;
} else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) {
- success = server_input_hostkeys_prove(&resp);
+ success = server_input_hostkeys_prove(ssh, &resp);
}
+ /* XXX sshpkt_get_end() */
if (want_reply) {
- packet_start(success ?
- SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
- if (success && resp != NULL)
- ssh_packet_put_raw(active_state, sshbuf_ptr(resp),
- sshbuf_len(resp));
- packet_send();
- packet_write_wait();
- }
+ if ((r = sshpkt_start(ssh, success ?
+ SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE)) != 0 ||
+ (success && resp != NULL && (r = sshpkt_putb(ssh, resp)) != 0) ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send reply", __func__);
+ }
+ free(fwd.listen_host);
+ free(fwd.listen_path);
free(rtype);
sshbuf_free(resp);
return 0;
}
static int
-server_input_channel_req(int type, u_int32_t seq, void *ctxt)
+server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c;
- int id, reply, success = 0;
- char *rtype;
+ int r, success = 0;
+ char *rtype = NULL;
+ u_char want_reply = 0;
+ u_int id = 0;
- id = packet_get_int();
- rtype = packet_get_string(NULL);
- reply = packet_get_char();
+ if ((r = sshpkt_get_u32(ssh, &id)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
+ (r = sshpkt_get_u8(ssh, &want_reply)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
- debug("server_input_channel_req: channel %d request %s reply %d",
- id, rtype, reply);
+ debug("server_input_channel_req: channel %u request %s reply %d",
+ id, rtype, want_reply);
- if ((c = channel_lookup(id)) == NULL)
- packet_disconnect("server_input_channel_req: "
- "unknown channel %d", id);
+ if (id >= INT_MAX || (c = channel_lookup(ssh, (int)id)) == NULL) {
+ ssh_packet_disconnect(ssh, "%s: unknown channel %d",
+ __func__, id);
+ }
if (!strcmp(rtype, "eow@openssh.com")) {
- packet_check_eom();
- chan_rcvd_eow(c);
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+ chan_rcvd_eow(ssh, c);
} else if ((c->type == SSH_CHANNEL_LARVAL ||
c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
- success = session_input_channel_req(c, rtype);
- if (reply && !(c->flags & CHAN_CLOSE_SENT)) {
- packet_start(success ?
- SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
- packet_put_int(c->remote_id);
- packet_send();
+ 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);
+ if ((r = sshpkt_start(ssh, success ?
+ SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send reply", __func__);
}
free(rtype);
return 0;
}
static void
-server_init_dispatch_20(void)
-{
- debug("server_init_dispatch_20");
- dispatch_init(&dispatch_protocol_error);
- dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
- dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
- dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
- dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
- dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
- dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
- dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
- dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
- dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
- dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
+server_init_dispatch(struct ssh *ssh)
+{
+ debug("server_init_dispatch");
+ ssh_dispatch_init(ssh, &dispatch_protocol_error);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_DATA, &channel_input_data);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
+ ssh_dispatch_set(ssh, SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
/* client_alive */
- dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive);
- dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);
- dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);
- dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);
+ ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);
+ ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
/* rekeying */
- dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
-}
-static void
-server_init_dispatch_13(void)
-{
- debug("server_init_dispatch_13");
- dispatch_init(NULL);
- dispatch_set(SSH_CMSG_EOF, &server_input_eof);
- dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data);
- dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size);
- dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
- dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
- dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
- dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
- dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
- dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
-}
-static void
-server_init_dispatch_15(void)
-{
- server_init_dispatch_13();
- debug("server_init_dispatch_15");
- dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
- dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
-}
-static void
-server_init_dispatch(void)
-{
- if (compat20)
- server_init_dispatch_20();
- else if (compat13)
- server_init_dispatch_13();
- else
- server_init_dispatch_15();
+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
}
diff --git a/serverloop.h b/serverloop.h
index 7311558f..fd2cf63f 100644
--- a/serverloop.h
+++ b/serverloop.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.h,v 1.6 2006/03/25 22:22:43 djm Exp $ */
+/* $OpenBSD: serverloop.h,v 1.8 2017/09/12 06:32:07 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -21,7 +21,8 @@
#ifndef SERVERLOOP_H
#define SERVERLOOP_H
-void server_loop(pid_t, int, int, int);
-void server_loop2(Authctxt *);
+struct ssh;
+
+void server_loop2(struct ssh *, Authctxt *);
#endif
diff --git a/session.c b/session.c
index 9a153846..449b84c5 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.277 2015/01/16 06:40:12 deraadt Exp $ */
+/* $OpenBSD: session.c,v 1.319 2020/03/13 03:17:07 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -46,6 +46,7 @@
#include <arpa/inet.h>
+#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
@@ -55,26 +56,26 @@
#endif
#include <pwd.h>
#include <signal.h>
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
#include <unistd.h>
#include <limits.h>
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
-#include "ssh1.h"
#include "ssh2.h"
#include "sshpty.h"
#include "packet.h"
-#include "buffer.h"
+#include "sshbuf.h"
+#include "ssherr.h"
#include "match.h"
#include "uidswap.h"
#include "compat.h"
#include "channels.h"
-#include "key.h"
+#include "sshkey.h"
#include "cipher.h"
#ifdef GSSAPI
#include "ssh-gss.h"
@@ -94,6 +95,7 @@
#include "kex.h"
#include "monitor_wrap.h"
#include "sftp.h"
+#include "atomicio.h"
#if defined(KRB5) && defined(USE_AFS)
#include <kafs.h>
@@ -112,35 +114,32 @@
/* func */
Session *session_new(void);
-void session_set_fds(Session *, int, int, int, int, int);
+void session_set_fds(struct ssh *, Session *, int, int, int, int, int);
void session_pty_cleanup(Session *);
void session_proctitle(Session *);
-int session_setup_x11fwd(Session *);
-int do_exec_pty(Session *, const char *);
-int do_exec_no_pty(Session *, const char *);
-int do_exec(Session *, const char *);
-void do_login(Session *, const char *);
-#ifdef LOGIN_NEEDS_UTMPX
-static void do_pre_login(Session *s);
-#endif
-void do_child(Session *, const char *);
+int session_setup_x11fwd(struct ssh *, Session *);
+int do_exec_pty(struct ssh *, Session *, const char *);
+int do_exec_no_pty(struct ssh *, Session *, const char *);
+int do_exec(struct ssh *, Session *, const char *);
+void do_login(struct ssh *, Session *, const char *);
+void do_child(struct ssh *, Session *, const char *);
void do_motd(void);
int check_quietlogin(Session *, const char *);
-static void do_authenticated1(Authctxt *);
-static void do_authenticated2(Authctxt *);
+static void do_authenticated2(struct ssh *, Authctxt *);
-static int session_pty_req(Session *);
+static int session_pty_req(struct ssh *, Session *);
/* import */
extern ServerOptions options;
extern char *__progname;
-extern int log_stderr;
extern int debug_flag;
extern u_int utmp_len;
extern int startup_pipe;
extern void destroy_sensitive_data(void);
-extern Buffer loginmsg;
+extern struct sshbuf *loginmsg;
+extern struct sshauthopt *auth_opts;
+extern char *tun_fwd_ifnames; /* serverloop.c */
/* original command from peer. */
const char *original_command = NULL;
@@ -160,6 +159,10 @@ login_cap_t *lc;
#endif
static int is_child = 0;
+static int in_chroot = 0;
+
+/* File containing userauth info, if ExposeAuthInfo set */
+static char *auth_info_file = NULL;
/* Name and directory of socket for authentication agent forwarding. */
static char *auth_sock_name = NULL;
@@ -180,7 +183,7 @@ auth_sock_cleanup_proc(struct passwd *pw)
}
static int
-auth_input_request_forwarding(struct passwd * pw)
+auth_input_request_forwarding(struct ssh *ssh, struct passwd * pw)
{
Channel *nc;
int sock = -1;
@@ -198,7 +201,7 @@ auth_input_request_forwarding(struct passwd * pw)
/* Create private directory for socket */
if (mkdtemp(auth_sock_dir) == NULL) {
- packet_send_debug("Agent forwarding disabled: "
+ ssh_packet_send_debug(ssh, "Agent forwarding disabled: "
"mkdtemp() failed: %.100s", strerror(errno));
restore_uid();
free(auth_sock_dir);
@@ -220,7 +223,7 @@ auth_input_request_forwarding(struct passwd * pw)
goto authsock_err;
/* Allocate a channel for the authentication agent socket. */
- nc = channel_new("auth socket",
+ nc = channel_new(ssh, "auth socket",
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
0, "auth socket", 1);
@@ -230,7 +233,9 @@ auth_input_request_forwarding(struct passwd * pw)
authsock_err:
free(auth_sock_name);
if (auth_sock_dir != NULL) {
+ temporarily_use_uid(pw);
rmdir(auth_sock_dir);
+ restore_uid();
free(auth_sock_dir);
}
if (sock != -1)
@@ -243,186 +248,138 @@ auth_input_request_forwarding(struct passwd * pw)
static void
display_loginmsg(void)
{
- if (buffer_len(&loginmsg) > 0) {
- buffer_append(&loginmsg, "\0", 1);
- printf("%s", (char *)buffer_ptr(&loginmsg));
- buffer_clear(&loginmsg);
- }
+ int r;
+
+ if (sshbuf_len(loginmsg) == 0)
+ return;
+ if ((r = sshbuf_put_u8(loginmsg, 0)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ printf("%s", (char *)sshbuf_ptr(loginmsg));
+ sshbuf_reset(loginmsg);
}
-void
-do_authenticated(Authctxt *authctxt)
+static void
+prepare_auth_info_file(struct passwd *pw, struct sshbuf *info)
{
- setproctitle("%s", authctxt->pw->pw_name);
+ int fd = -1, success = 0;
- /* setup the channel layer */
- /* XXX - streamlocal? */
- if (no_port_forwarding_flag ||
- (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
- channel_disable_adm_local_opens();
- else
- channel_permit_all_opens();
-
- auth_debug_send();
-
- if (compat20)
- do_authenticated2(authctxt);
- else
- do_authenticated1(authctxt);
+ if (!options.expose_userauth_info || info == NULL)
+ return;
- do_cleanup(authctxt);
+ temporarily_use_uid(pw);
+ auth_info_file = xstrdup("/tmp/sshauth.XXXXXXXXXXXXXXX");
+ if ((fd = mkstemp(auth_info_file)) == -1) {
+ error("%s: mkstemp: %s", __func__, strerror(errno));
+ goto out;
+ }
+ if (atomicio(vwrite, fd, sshbuf_mutable_ptr(info),
+ sshbuf_len(info)) != sshbuf_len(info)) {
+ error("%s: write: %s", __func__, strerror(errno));
+ goto out;
+ }
+ if (close(fd) != 0) {
+ error("%s: close: %s", __func__, strerror(errno));
+ goto out;
+ }
+ success = 1;
+ out:
+ if (!success) {
+ if (fd != -1)
+ close(fd);
+ free(auth_info_file);
+ auth_info_file = NULL;
+ }
+ restore_uid();
}
-/*
- * Prepares for an interactive session. This is called after the user has
- * been successfully authenticated. During this message exchange, pseudo
- * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
- * are requested, etc.
- */
static void
-do_authenticated1(Authctxt *authctxt)
+set_fwdpermit_from_authopts(struct ssh *ssh, const struct sshauthopt *opts)
{
- Session *s;
- char *command;
- int success, type, screen_flag;
- int enable_compression_after_reply = 0;
- u_int proto_len, data_len, dlen, compression_level = 0;
-
- s = session_new();
- if (s == NULL) {
- error("no more sessions");
- return;
+ char *tmp, *cp, *host;
+ int port;
+ size_t i;
+
+ if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) {
+ channel_clear_permission(ssh, FORWARD_USER, FORWARD_LOCAL);
+ for (i = 0; i < auth_opts->npermitopen; i++) {
+ tmp = cp = xstrdup(auth_opts->permitopen[i]);
+ /* This shouldn't fail as it has already been checked */
+ if ((host = hpdelim(&cp)) == NULL)
+ fatal("%s: internal error: hpdelim", __func__);
+ host = cleanhostname(host);
+ if (cp == NULL || (port = permitopen_port(cp)) < 0)
+ fatal("%s: internal error: permitopen port",
+ __func__);
+ channel_add_permission(ssh,
+ FORWARD_USER, FORWARD_LOCAL, host, port);
+ free(tmp);
+ }
}
- s->authctxt = authctxt;
- s->pw = authctxt->pw;
-
- /*
- * We stay in this loop until the client requests to execute a shell
- * or a command.
- */
- for (;;) {
- success = 0;
+ if ((options.allow_tcp_forwarding & FORWARD_REMOTE) != 0) {
+ channel_clear_permission(ssh, FORWARD_USER, FORWARD_REMOTE);
+ for (i = 0; i < auth_opts->npermitlisten; i++) {
+ tmp = cp = xstrdup(auth_opts->permitlisten[i]);
+ /* This shouldn't fail as it has already been checked */
+ if ((host = hpdelim(&cp)) == NULL)
+ fatal("%s: internal error: hpdelim", __func__);
+ host = cleanhostname(host);
+ if (cp == NULL || (port = permitopen_port(cp)) < 0)
+ fatal("%s: internal error: permitlisten port",
+ __func__);
+ channel_add_permission(ssh,
+ FORWARD_USER, FORWARD_REMOTE, host, port);
+ free(tmp);
+ }
+ }
+}
- /* Get a packet from the client. */
- type = packet_read();
-
- /* Process the packet. */
- switch (type) {
- case SSH_CMSG_REQUEST_COMPRESSION:
- compression_level = packet_get_int();
- packet_check_eom();
- if (compression_level < 1 || compression_level > 9) {
- packet_send_debug("Received invalid compression level %d.",
- compression_level);
- break;
- }
- if (options.compression == COMP_NONE) {
- debug2("compression disabled");
- break;
- }
- /* Enable compression after we have responded with SUCCESS. */
- enable_compression_after_reply = 1;
- success = 1;
- break;
+void
+do_authenticated(struct ssh *ssh, Authctxt *authctxt)
+{
+ setproctitle("%s", authctxt->pw->pw_name);
- case SSH_CMSG_REQUEST_PTY:
- success = session_pty_req(s);
- break;
+ auth_log_authopts("active", auth_opts, 0);
- case SSH_CMSG_X11_REQUEST_FORWARDING:
- s->auth_proto = packet_get_string(&proto_len);
- s->auth_data = packet_get_string(&data_len);
+ /* setup the channel layer */
+ /* XXX - streamlocal? */
+ set_fwdpermit_from_authopts(ssh, auth_opts);
- screen_flag = packet_get_protocol_flags() &
- SSH_PROTOFLAG_SCREEN_NUMBER;
- debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag);
+ if (!auth_opts->permit_port_forwarding_flag ||
+ options.disable_forwarding) {
+ channel_disable_admin(ssh, FORWARD_LOCAL);
+ channel_disable_admin(ssh, FORWARD_REMOTE);
+ } else {
+ if ((options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
+ channel_disable_admin(ssh, FORWARD_LOCAL);
+ else
+ channel_permit_all(ssh, FORWARD_LOCAL);
+ if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0)
+ channel_disable_admin(ssh, FORWARD_REMOTE);
+ else
+ channel_permit_all(ssh, FORWARD_REMOTE);
+ }
+ auth_debug_send(ssh);
- if (packet_remaining() == 4) {
- if (!screen_flag)
- debug2("Buggy client: "
- "X11 screen flag missing");
- s->screen = packet_get_int();
- } else {
- s->screen = 0;
- }
- packet_check_eom();
- success = session_setup_x11fwd(s);
- if (!success) {
- free(s->auth_proto);
- free(s->auth_data);
- s->auth_proto = NULL;
- s->auth_data = NULL;
- }
- break;
+ prepare_auth_info_file(authctxt->pw, authctxt->session_info);
- case SSH_CMSG_AGENT_REQUEST_FORWARDING:
- if (!options.allow_agent_forwarding ||
- no_agent_forwarding_flag || compat13) {
- debug("Authentication agent forwarding not permitted for this authentication.");
- break;
- }
- debug("Received authentication agent forwarding request.");
- success = auth_input_request_forwarding(s->pw);
- break;
+ do_authenticated2(ssh, authctxt);
- case SSH_CMSG_PORT_FORWARD_REQUEST:
- if (no_port_forwarding_flag) {
- debug("Port forwarding not permitted for this authentication.");
- break;
- }
- if (!(options.allow_tcp_forwarding & FORWARD_REMOTE)) {
- debug("Port forwarding not permitted.");
- break;
- }
- debug("Received TCP/IP port forwarding request.");
- if (channel_input_port_forward_request(s->pw->pw_uid == 0,
- &options.fwd_opts) < 0) {
- debug("Port forwarding failed.");
- break;
- }
- success = 1;
- break;
+ do_cleanup(ssh, authctxt);
+}
- case SSH_CMSG_MAX_PACKET_SIZE:
- if (packet_set_maxsize(packet_get_int()) > 0)
- success = 1;
- break;
+/* Check untrusted xauth strings for metacharacters */
+static int
+xauth_valid_string(const char *s)
+{
+ size_t i;
- case SSH_CMSG_EXEC_SHELL:
- case SSH_CMSG_EXEC_CMD:
- if (type == SSH_CMSG_EXEC_CMD) {
- command = packet_get_string(&dlen);
- debug("Exec command '%.500s'", command);
- if (do_exec(s, command) != 0)
- packet_disconnect(
- "command execution failed");
- free(command);
- } else {
- if (do_exec(s, NULL) != 0)
- packet_disconnect(
- "shell execution failed");
- }
- packet_check_eom();
- session_close(s);
- return;
-
- default:
- /*
- * Any unknown messages in this phase are ignored,
- * and a failure message is returned.
- */
- logit("Unknown packet type received after authentication: %d", type);
- }
- packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
-
- /* Enable compression now that we have replied if appropriate. */
- if (enable_compression_after_reply) {
- enable_compression_after_reply = 0;
- packet_start_compression(compression_level);
- }
+ for (i = 0; s[i] != '\0'; i++) {
+ if (!isalnum((u_char)s[i]) &&
+ s[i] != '.' && s[i] != ':' && s[i] != '/' &&
+ s[i] != '-' && s[i] != '_')
+ return 0;
}
+ return 1;
}
#define USE_PIPES 1
@@ -432,10 +389,9 @@ do_authenticated1(Authctxt *authctxt)
* setting up file descriptors and such.
*/
int
-do_exec_no_pty(Session *s, const char *command)
+do_exec_no_pty(struct ssh *ssh, Session *s, const char *command)
{
pid_t pid;
-
#ifdef USE_PIPES
int pin[2], pout[2], perr[2];
@@ -443,17 +399,17 @@ do_exec_no_pty(Session *s, const char *command)
fatal("do_exec_no_pty: no session");
/* Allocate pipes for communicating with the program. */
- if (pipe(pin) < 0) {
+ if (pipe(pin) == -1) {
error("%s: pipe in: %.100s", __func__, strerror(errno));
return -1;
}
- if (pipe(pout) < 0) {
+ if (pipe(pout) == -1) {
error("%s: pipe out: %.100s", __func__, strerror(errno));
close(pin[0]);
close(pin[1]);
return -1;
}
- if (pipe(perr) < 0) {
+ if (pipe(perr) == -1) {
error("%s: pipe err: %.100s", __func__,
strerror(errno));
close(pin[0]);
@@ -469,11 +425,11 @@ do_exec_no_pty(Session *s, const char *command)
fatal("do_exec_no_pty: no session");
/* Uses socket pairs to communicate with the program. */
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) {
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1) {
error("%s: socketpair #1: %.100s", __func__, strerror(errno));
return -1;
}
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) {
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) == -1) {
error("%s: socketpair #2: %.100s", __func__,
strerror(errno));
close(inout[0]);
@@ -505,15 +461,11 @@ do_exec_no_pty(Session *s, const char *command)
case 0:
is_child = 1;
- /* Child. Reinitialize the log since the pid has changed. */
- log_init(__progname, options.log_level,
- options.log_facility, log_stderr);
-
/*
* Create a new session and process group since the 4.4BSD
* setlogin() affects the entire process group.
*/
- if (setsid() < 0)
+ if (setsid() == -1)
error("setsid failed: %.100s", strerror(errno));
#ifdef USE_PIPES
@@ -522,19 +474,19 @@ do_exec_no_pty(Session *s, const char *command)
* pair, and make the child side the standard input.
*/
close(pin[1]);
- if (dup2(pin[0], 0) < 0)
+ if (dup2(pin[0], 0) == -1)
perror("dup2 stdin");
close(pin[0]);
/* Redirect stdout. */
close(pout[0]);
- if (dup2(pout[1], 1) < 0)
+ if (dup2(pout[1], 1) == -1)
perror("dup2 stdout");
close(pout[1]);
/* Redirect stderr. */
close(perr[0]);
- if (dup2(perr[1], 2) < 0)
+ if (dup2(perr[1], 2) == -1)
perror("dup2 stderr");
close(perr[1]);
#else
@@ -545,38 +497,30 @@ do_exec_no_pty(Session *s, const char *command)
*/
close(inout[1]);
close(err[1]);
- if (dup2(inout[0], 0) < 0) /* stdin */
+ if (dup2(inout[0], 0) == -1) /* stdin */
perror("dup2 stdin");
- if (dup2(inout[0], 1) < 0) /* stdout (same as stdin) */
+ if (dup2(inout[0], 1) == -1) /* stdout (same as stdin) */
perror("dup2 stdout");
close(inout[0]);
- if (dup2(err[0], 2) < 0) /* stderr */
+ if (dup2(err[0], 2) == -1) /* stderr */
perror("dup2 stderr");
close(err[0]);
#endif
-
-#ifdef _UNICOS
- cray_init_job(s->pw); /* set up cray jid and tmpdir */
-#endif
-
/* Do processing for the child (exec command etc). */
- do_child(s, command);
+ do_child(ssh, s, command);
/* NOTREACHED */
default:
break;
}
-#ifdef _UNICOS
- signal(WJSIGNAL, cray_job_termination_handler);
-#endif /* _UNICOS */
#ifdef HAVE_CYGWIN
cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
#endif
s->pid = pid;
/* Set interactive/non-interactive mode. */
- packet_set_interactive(s->display != NULL,
+ ssh_packet_set_interactive(ssh, s->display != NULL,
options.ip_qos_interactive, options.ip_qos_bulk);
/*
@@ -584,7 +528,7 @@ do_exec_no_pty(Session *s, const char *command)
* it to the user, otherwise multiple sessions may accumulate
* multiple copies of the login messages.
*/
- buffer_clear(&loginmsg);
+ sshbuf_reset(loginmsg);
#ifdef USE_PIPES
/* We are the parent. Close the child sides of the pipes. */
@@ -592,14 +536,8 @@ do_exec_no_pty(Session *s, const char *command)
close(pout[1]);
close(perr[1]);
- if (compat20) {
- session_set_fds(s, pin[1], pout[0], perr[0],
- s->is_subsystem, 0);
- } else {
- /* Enter the interactive session. */
- server_loop(pid, pin[1], pout[0], perr[0]);
- /* server_loop has closed pin[1], pout[0], and perr[0]. */
- }
+ session_set_fds(ssh, s, pin[1], pout[0], perr[0],
+ s->is_subsystem, 0);
#else
/* We are the parent. Close the child sides of the socket pairs. */
close(inout[0]);
@@ -609,13 +547,8 @@ do_exec_no_pty(Session *s, const char *command)
* Enter the interactive session. Note: server_loop must be able to
* handle the case that fdin and fdout are the same.
*/
- if (compat20) {
- session_set_fds(s, inout[1], inout[1], err[1],
- s->is_subsystem, 0);
- } else {
- server_loop(pid, inout[1], inout[1], err[1]);
- /* server_loop has closed inout[1] and err[1]. */
- }
+ session_set_fds(ssh, s, inout[1], inout[1], err[1],
+ s->is_subsystem, 0);
#endif
return 0;
}
@@ -627,7 +560,7 @@ do_exec_no_pty(Session *s, const char *command)
* lastlog, and other such operations.
*/
int
-do_exec_pty(Session *s, const char *command)
+do_exec_pty(struct ssh *ssh, Session *s, const char *command)
{
int fdout, ptyfd, ttyfd, ptymaster;
pid_t pid;
@@ -644,14 +577,14 @@ do_exec_pty(Session *s, const char *command)
* Do this before forking (and cleanup in the child) so as to
* detect and gracefully fail out-of-fd conditions.
*/
- if ((fdout = dup(ptyfd)) < 0) {
+ if ((fdout = dup(ptyfd)) == -1) {
error("%s: dup #1: %s", __func__, strerror(errno));
close(ttyfd);
close(ptyfd);
return -1;
}
/* we keep a reference to the pty master */
- if ((ptymaster = dup(ptyfd)) < 0) {
+ if ((ptymaster = dup(ptyfd)) == -1) {
error("%s: dup #2: %s", __func__, strerror(errno));
close(ttyfd);
close(ptyfd);
@@ -674,9 +607,6 @@ do_exec_pty(Session *s, const char *command)
close(fdout);
close(ptymaster);
- /* Child. Reinitialize the log because the pid has changed. */
- log_init(__progname, options.log_level,
- options.log_facility, log_stderr);
/* Close the master side of the pseudo tty. */
close(ptyfd);
@@ -684,11 +614,11 @@ do_exec_pty(Session *s, const char *command)
pty_make_controlling_tty(&ttyfd, s->tty);
/* Redirect stdin/stdout/stderr from the pseudo tty. */
- if (dup2(ttyfd, 0) < 0)
+ if (dup2(ttyfd, 0) == -1)
error("dup2 stdin: %s", strerror(errno));
- if (dup2(ttyfd, 1) < 0)
+ if (dup2(ttyfd, 1) == -1)
error("dup2 stdout: %s", strerror(errno));
- if (dup2(ttyfd, 2) < 0)
+ if (dup2(ttyfd, 2) == -1)
error("dup2 stderr: %s", strerror(errno));
/* Close the extra descriptor for the pseudo tty. */
@@ -696,30 +626,18 @@ do_exec_pty(Session *s, const char *command)
/* record login, etc. similar to login(1) */
#ifndef HAVE_OSF_SIA
- if (!(options.use_login && command == NULL)) {
-#ifdef _UNICOS
- cray_init_job(s->pw); /* set up cray jid and tmpdir */
-#endif /* _UNICOS */
- do_login(s, command);
- }
-# ifdef LOGIN_NEEDS_UTMPX
- else
- do_pre_login(s);
-# endif
+ do_login(ssh, s, command);
#endif
/*
* Do common processing for the child, such as execing
* the command.
*/
- do_child(s, command);
+ do_child(ssh, s, command);
/* NOTREACHED */
default:
break;
}
-#ifdef _UNICOS
- signal(WJSIGNAL, cray_job_termination_handler);
-#endif /* _UNICOS */
#ifdef HAVE_CYGWIN
cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
#endif
@@ -731,66 +649,35 @@ do_exec_pty(Session *s, const char *command)
/* Enter interactive session. */
s->ptymaster = ptymaster;
- packet_set_interactive(1,
+ ssh_packet_set_interactive(ssh, 1,
options.ip_qos_interactive, options.ip_qos_bulk);
- if (compat20) {
- session_set_fds(s, ptyfd, fdout, -1, 1, 1);
- } else {
- server_loop(pid, ptyfd, fdout, -1);
- /* server_loop _has_ closed ptyfd and fdout. */
- }
+ session_set_fds(ssh, s, ptyfd, fdout, -1, 1, 1);
return 0;
}
-#ifdef LOGIN_NEEDS_UTMPX
-static void
-do_pre_login(Session *s)
-{
- socklen_t fromlen;
- struct sockaddr_storage from;
- pid_t pid = getpid();
-
- /*
- * Get IP address of client. If the connection is not a socket, let
- * the address be 0.0.0.0.
- */
- memset(&from, 0, sizeof(from));
- fromlen = sizeof(from);
- if (packet_connection_is_on_socket()) {
- if (getpeername(packet_get_connection_in(),
- (struct sockaddr *)&from, &fromlen) < 0) {
- debug("getpeername: %.100s", strerror(errno));
- cleanup_exit(255);
- }
- }
-
- record_utmp_only(pid, s->tty, s->pw->pw_name,
- get_remote_name_or_ip(utmp_len, options.use_dns),
- (struct sockaddr *)&from, fromlen);
-}
-#endif
-
/*
* This is called to fork and execute a command. If another command is
* to be forced, execute that instead.
*/
int
-do_exec(Session *s, const char *command)
+do_exec(struct ssh *ssh, Session *s, const char *command)
{
int ret;
- const char *forced = NULL;
- char session_type[1024], *tty = NULL;
+ const char *forced = NULL, *tty = NULL;
+ char session_type[1024];
if (options.adm_forced_command) {
original_command = command;
command = options.adm_forced_command;
forced = "(config)";
- } else if (forced_command) {
+ } else if (auth_opts->force_command != NULL) {
original_command = command;
- command = forced_command;
+ command = auth_opts->force_command;
forced = "(key-option)";
}
+ s->forced = 0;
if (forced != NULL) {
+ s->forced = 1;
if (IS_INTERNAL_SFTP(command)) {
s->is_subsystem = s->is_subsystem ?
SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
@@ -814,13 +701,14 @@ do_exec(Session *s, const char *command)
tty += 5;
}
- verbose("Starting session: %s%s%s for %s from %.200s port %d",
+ verbose("Starting session: %s%s%s for %s from %.200s port %d id %d",
session_type,
tty == NULL ? "" : " on ",
tty == NULL ? "" : tty,
s->pw->pw_name,
- get_remote_ipaddr(),
- get_remote_port());
+ ssh_remote_ipaddr(ssh),
+ ssh_remote_port(ssh),
+ s->self);
#ifdef SSH_AUDIT_EVENTS
if (command != NULL)
@@ -834,9 +722,9 @@ do_exec(Session *s, const char *command)
}
#endif
if (s->ttyfd != -1)
- ret = do_exec_pty(s, command);
+ ret = do_exec_pty(ssh, s, command);
else
- ret = do_exec_no_pty(s, command);
+ ret = do_exec_no_pty(ssh, s, command);
original_command = NULL;
@@ -845,14 +733,14 @@ do_exec(Session *s, const char *command)
* it to the user, otherwise multiple sessions may accumulate
* multiple copies of the login messages.
*/
- buffer_clear(&loginmsg);
+ sshbuf_reset(loginmsg);
return ret;
}
/* administrative, login(1)-like work */
void
-do_login(Session *s, const char *command)
+do_login(struct ssh *ssh, Session *s, const char *command)
{
socklen_t fromlen;
struct sockaddr_storage from;
@@ -865,9 +753,9 @@ do_login(Session *s, const char *command)
*/
memset(&from, 0, sizeof(from));
fromlen = sizeof(from);
- if (packet_connection_is_on_socket()) {
- if (getpeername(packet_get_connection_in(),
- (struct sockaddr *)&from, &fromlen) < 0) {
+ if (ssh_packet_connection_is_on_socket(ssh)) {
+ if (getpeername(ssh_packet_get_connection_in(ssh),
+ (struct sockaddr *)&from, &fromlen) == -1) {
debug("getpeername: %.100s", strerror(errno));
cleanup_exit(255);
}
@@ -876,7 +764,7 @@ do_login(Session *s, const char *command)
/* Record that there was a login on that tty from the remote host. */
if (!use_privsep)
record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
- get_remote_name_or_ip(utmp_len,
+ session_get_remote_name_or_ip(ssh, utmp_len,
options.use_dns),
(struct sockaddr *)&from, fromlen);
@@ -951,87 +839,30 @@ check_quietlogin(Session *s, const char *command)
}
/*
- * Sets the value of the given variable in the environment. If the variable
- * already exists, its value is overridden.
- */
-void
-child_set_env(char ***envp, u_int *envsizep, const char *name,
- const char *value)
-{
- char **env;
- u_int envsize;
- u_int i, namelen;
-
- if (strchr(name, '=') != NULL) {
- error("Invalid environment variable \"%.100s\"", name);
- return;
- }
-
- /*
- * If we're passed an uninitialized list, allocate a single null
- * entry before continuing.
- */
- if (*envp == NULL && *envsizep == 0) {
- *envp = xmalloc(sizeof(char *));
- *envp[0] = NULL;
- *envsizep = 1;
- }
-
- /*
- * Find the slot where the value should be stored. If the variable
- * already exists, we reuse the slot; otherwise we append a new slot
- * at the end of the array, expanding if necessary.
- */
- env = *envp;
- namelen = strlen(name);
- for (i = 0; env[i]; i++)
- if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
- break;
- if (env[i]) {
- /* Reuse the slot. */
- free(env[i]);
- } else {
- /* New variable. Expand if necessary. */
- envsize = *envsizep;
- if (i >= envsize - 1) {
- if (envsize >= 1000)
- fatal("child_set_env: too many env vars");
- envsize += 50;
- env = (*envp) = xrealloc(env, envsize, sizeof(char *));
- *envsizep = envsize;
- }
- /* Need to set the NULL pointer at end of array beyond the new slot. */
- env[i + 1] = NULL;
- }
-
- /* Allocate space and format the variable in the appropriate slot. */
- env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
- snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
-}
-
-/*
* Reads environment variables from the given file and adds/overrides them
* into the environment. If the file does not exist, this does nothing.
* Otherwise, it must consist of empty lines, comments (line starts with '#')
* and assignments of the form name=value. No other forms are allowed.
+ * If whitelist is not NULL, then it is interpreted as a pattern list and
+ * only variable names that match it will be accepted.
*/
static void
read_environment_file(char ***env, u_int *envsize,
- const char *filename)
+ const char *filename, const char *whitelist)
{
FILE *f;
- char buf[4096];
- char *cp, *value;
+ char *line = NULL, *cp, *value;
+ size_t linesize = 0;
u_int lineno = 0;
f = fopen(filename, "r");
if (!f)
return;
- while (fgets(buf, sizeof(buf), f)) {
+ while (getline(&line, &linesize, f) != -1) {
if (++lineno > 1000)
fatal("Too many lines in environment file %s", filename);
- for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
+ for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '#' || *cp == '\n')
continue;
@@ -1050,8 +881,12 @@ read_environment_file(char ***env, u_int *envsize,
*/
*value = '\0';
value++;
+ if (whitelist != NULL &&
+ match_pattern_list(cp, whitelist, 0) != 1)
+ continue;
child_set_env(env, envsize, cp, value);
}
+ free(line);
fclose(f);
}
@@ -1088,7 +923,8 @@ read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
* so we use a temporary environment and copy the variables we're
* interested in.
*/
- read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login");
+ read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login",
+ options.permit_user_env_whitelist);
if (tmpenv == NULL)
return;
@@ -1110,8 +946,10 @@ read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
}
#endif /* HAVE_ETC_DEFAULT_LOGIN */
-void
-copy_environment(char **source, char ***env, u_int *envsize)
+#if defined(USE_PAM) || defined(HAVE_CYGWIN)
+static void
+copy_environment_blacklist(char **source, char ***env, u_int *envsize,
+ const char *blacklist)
{
char *var_name, *var_val;
int i;
@@ -1127,19 +965,32 @@ copy_environment(char **source, char ***env, u_int *envsize)
}
*var_val++ = '\0';
- debug3("Copy environment: %s=%s", var_name, var_val);
- child_set_env(env, envsize, var_name, var_val);
+ if (blacklist == NULL ||
+ match_pattern_list(var_name, blacklist, 0) != 1) {
+ debug3("Copy environment: %s=%s", var_name, var_val);
+ child_set_env(env, envsize, var_name, var_val);
+ }
free(var_name);
}
}
+#endif /* defined(USE_PAM) || defined(HAVE_CYGWIN) */
+
+#ifdef HAVE_CYGWIN
+static void
+copy_environment(char **source, char ***env, u_int *envsize)
+{
+ copy_environment_blacklist(source, env, envsize, NULL);
+}
+#endif
static char **
-do_setup_env(Session *s, const char *shell)
+do_setup_env(struct ssh *ssh, Session *s, const char *shell)
{
char buf[256];
+ size_t n;
u_int i, envsize;
- char **env, *laddr;
+ char *ocp, *cp, *value, **env, *laddr;
struct passwd *pw = s->pw;
#if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN)
char *path = NULL;
@@ -1166,103 +1017,62 @@ do_setup_env(Session *s, const char *shell)
#ifdef GSSAPI
/* Allow any GSSAPI methods that we've used to alter
- * the childs environment as they see fit
+ * the child's environment as they see fit
*/
ssh_gssapi_do_child(&env, &envsize);
#endif
- if (!options.use_login) {
- /* Set basic environment. */
- for (i = 0; i < s->num_env; i++)
- child_set_env(&env, &envsize, s->env[i].name,
- s->env[i].val);
+ /* Set basic environment. */
+ for (i = 0; i < s->num_env; i++)
+ child_set_env(&env, &envsize, s->env[i].name, s->env[i].val);
- child_set_env(&env, &envsize, "USER", pw->pw_name);
- child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
+ child_set_env(&env, &envsize, "USER", pw->pw_name);
+ child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
#ifdef _AIX
- child_set_env(&env, &envsize, "LOGIN", pw->pw_name);
+ child_set_env(&env, &envsize, "LOGIN", pw->pw_name);
#endif
- child_set_env(&env, &envsize, "HOME", pw->pw_dir);
+ child_set_env(&env, &envsize, "HOME", pw->pw_dir);
#ifdef HAVE_LOGIN_CAP
- if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0)
- child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
- else
- child_set_env(&env, &envsize, "PATH", getenv("PATH"));
+ if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0)
+ child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
+ else
+ child_set_env(&env, &envsize, "PATH", getenv("PATH"));
#else /* HAVE_LOGIN_CAP */
# ifndef HAVE_CYGWIN
- /*
- * There's no standard path on Windows. The path contains
- * important components pointing to the system directories,
- * needed for loading shared libraries. So the path better
- * remains intact here.
- */
+ /*
+ * There's no standard path on Windows. The path contains
+ * important components pointing to the system directories,
+ * needed for loading shared libraries. So the path better
+ * remains intact here.
+ */
# ifdef HAVE_ETC_DEFAULT_LOGIN
- read_etc_default_login(&env, &envsize, pw->pw_uid);
- path = child_get_env(env, "PATH");
+ read_etc_default_login(&env, &envsize, pw->pw_uid);
+ path = child_get_env(env, "PATH");
# endif /* HAVE_ETC_DEFAULT_LOGIN */
- if (path == NULL || *path == '\0') {
- child_set_env(&env, &envsize, "PATH",
- s->pw->pw_uid == 0 ?
- SUPERUSER_PATH : _PATH_STDPATH);
- }
+ if (path == NULL || *path == '\0') {
+ child_set_env(&env, &envsize, "PATH",
+ s->pw->pw_uid == 0 ? SUPERUSER_PATH : _PATH_STDPATH);
+ }
# endif /* HAVE_CYGWIN */
#endif /* HAVE_LOGIN_CAP */
-#ifndef ANDROID
+#if !defined(ANDROID)
+ if (!options.use_pam) {
snprintf(buf, sizeof buf, "%.200s/%.50s",
- _PATH_MAILDIR, pw->pw_name);
+ _PATH_MAILDIR, pw->pw_name);
child_set_env(&env, &envsize, "MAIL", buf);
+ }
#endif
- /* Normal systems set SHELL by default. */
- child_set_env(&env, &envsize, "SHELL", shell);
- }
+ /* Normal systems set SHELL by default. */
+ child_set_env(&env, &envsize, "SHELL", shell);
+
if (getenv("TZ"))
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
-
- /* Set custom environment options from RSA authentication. */
- if (!options.use_login) {
- while (custom_environment) {
- struct envstring *ce = custom_environment;
- char *str = ce->s;
-
- for (i = 0; str[i] != '=' && str[i]; i++)
- ;
- if (str[i] == '=') {
- str[i] = 0;
- child_set_env(&env, &envsize, str, str + i + 1);
- }
- custom_environment = ce->next;
- free(ce->s);
- free(ce);
- }
- }
-
- /* SSH_CLIENT deprecated */
- snprintf(buf, sizeof buf, "%.50s %d %d",
- get_remote_ipaddr(), get_remote_port(), get_local_port());
- child_set_env(&env, &envsize, "SSH_CLIENT", buf);
-
- laddr = get_local_ipaddr(packet_get_connection_in());
- snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
- get_remote_ipaddr(), get_remote_port(), laddr, get_local_port());
- free(laddr);
- child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
-
- if (s->ttyfd != -1)
- child_set_env(&env, &envsize, "SSH_TTY", s->tty);
if (s->term)
child_set_env(&env, &envsize, "TERM", s->term);
if (s->display)
child_set_env(&env, &envsize, "DISPLAY", s->display);
- if (original_command)
- child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
- original_command);
-
-#ifdef _UNICOS
- if (cray_tmpdir[0] != '\0')
- child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir);
-#endif /* _UNICOS */
/*
* Since we clear KRB5CCNAME at startup, if it's set now then it
@@ -1282,7 +1092,8 @@ do_setup_env(Session *s, const char *shell)
if ((cp = getenv("AUTHSTATE")) != NULL)
child_set_env(&env, &envsize, "AUTHSTATE", cp);
- read_environment_file(&env, &envsize, "/etc/environment");
+ read_environment_file(&env, &envsize, "/etc/environment",
+ options.permit_user_env_whitelist);
}
#endif
#ifdef KRB5
@@ -1290,6 +1101,37 @@ do_setup_env(Session *s, const char *shell)
child_set_env(&env, &envsize, "KRB5CCNAME",
s->authctxt->krb5_ccname);
#endif
+ if (auth_sock_name != NULL)
+ child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
+ auth_sock_name);
+
+
+ /* Set custom environment options from pubkey authentication. */
+ if (options.permit_user_env) {
+ for (n = 0 ; n < auth_opts->nenv; n++) {
+ ocp = xstrdup(auth_opts->env[n]);
+ cp = strchr(ocp, '=');
+ if (*cp == '=') {
+ *cp = '\0';
+ /* Apply PermitUserEnvironment whitelist */
+ if (options.permit_user_env_whitelist == NULL ||
+ match_pattern_list(ocp,
+ options.permit_user_env_whitelist, 0) == 1)
+ child_set_env(&env, &envsize,
+ ocp, cp + 1);
+ }
+ free(ocp);
+ }
+ }
+
+ /* read $HOME/.ssh/environment. */
+ if (options.permit_user_env) {
+ snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
+ pw->pw_dir);
+ read_environment_file(&env, &envsize, buf,
+ options.permit_user_env_whitelist);
+ }
+
#ifdef USE_PAM
/*
* Pull in any environment variables that may have
@@ -1298,26 +1140,57 @@ do_setup_env(Session *s, const char *shell)
if (options.use_pam) {
char **p;
+ /*
+ * Don't allow PAM-internal env vars to leak
+ * back into the session environment.
+ */
+#define PAM_ENV_BLACKLIST "SSH_AUTH_INFO*,SSH_CONNECTION*"
p = fetch_pam_child_environment();
- copy_environment(p, &env, &envsize);
+ copy_environment_blacklist(p, &env, &envsize,
+ PAM_ENV_BLACKLIST);
free_pam_environment(p);
p = fetch_pam_environment();
- copy_environment(p, &env, &envsize);
+ copy_environment_blacklist(p, &env, &envsize,
+ PAM_ENV_BLACKLIST);
free_pam_environment(p);
}
#endif /* USE_PAM */
- if (auth_sock_name != NULL)
- child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
- auth_sock_name);
-
- /* read $HOME/.ssh/environment. */
- if (options.permit_user_env && !options.use_login) {
- snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
- strcmp(pw->pw_dir, "/") ? pw->pw_dir : "");
- read_environment_file(&env, &envsize, buf);
+ /* Environment specified by admin */
+ for (i = 0; i < options.num_setenv; i++) {
+ cp = xstrdup(options.setenv[i]);
+ if ((value = strchr(cp, '=')) == NULL) {
+ /* shouldn't happen; vars are checked in servconf.c */
+ fatal("Invalid config SetEnv: %s", options.setenv[i]);
+ }
+ *value++ = '\0';
+ child_set_env(&env, &envsize, cp, value);
}
+
+ /* SSH_CLIENT deprecated */
+ snprintf(buf, sizeof buf, "%.50s %d %d",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+ ssh_local_port(ssh));
+ child_set_env(&env, &envsize, "SSH_CLIENT", buf);
+
+ laddr = get_local_ipaddr(ssh_packet_get_connection_in(ssh));
+ snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+ laddr, ssh_local_port(ssh));
+ free(laddr);
+ child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
+
+ if (tun_fwd_ifnames != NULL)
+ child_set_env(&env, &envsize, "SSH_TUNNEL", tun_fwd_ifnames);
+ if (auth_info_file != NULL)
+ child_set_env(&env, &envsize, "SSH_USER_AUTH", auth_info_file);
+ if (s->ttyfd != -1)
+ child_set_env(&env, &envsize, "SSH_TTY", s->tty);
+ if (original_command)
+ child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
+ original_command);
+
if (debug_flag) {
/* dump the environment */
fprintf(stderr, "Environment:\n");
@@ -1332,7 +1205,7 @@ do_setup_env(Session *s, const char *shell)
* first in this order).
*/
static void
-do_rc_files(Session *s, const char *shell)
+do_rc_files(struct ssh *ssh, Session *s, const char *shell)
{
FILE *f = NULL;
char cmd[1024];
@@ -1344,7 +1217,7 @@ do_rc_files(Session *s, const char *shell)
/* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */
if (!s->is_subsystem && options.adm_forced_command == NULL &&
- !no_user_rc && options.permit_user_rc &&
+ 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);
@@ -1425,10 +1298,10 @@ do_nologin(struct passwd *pw)
/* /etc/nologin exists. Print its contents if we can and exit. */
logit("User %.100s not allowed because %s exists", pw->pw_name, nl);
if ((f = fopen(nl, "r")) != NULL) {
- while (fgets(buf, sizeof(buf), f))
- fputs(buf, stderr);
- fclose(f);
- }
+ while (fgets(buf, sizeof(buf), f))
+ fputs(buf, stderr);
+ fclose(f);
+ }
exit(254);
}
@@ -1443,7 +1316,7 @@ safely_chroot(const char *path, uid_t uid)
char component[PATH_MAX];
struct stat st;
- if (*path != '/')
+ if (!path_absolute(path))
fatal("chroot path does not begin at root");
if (strlen(path) >= sizeof(component))
fatal("chroot path too long");
@@ -1468,7 +1341,7 @@ safely_chroot(const char *path, uid_t uid)
component, strerror(errno));
if (st.st_uid != 0 || (st.st_mode & 022) != 0)
fatal("bad ownership or modes for chroot "
- "directory %s\"%s\"",
+ "directory %s\"%s\"",
cp == NULL ? "" : "component ", component);
if (!S_ISDIR(st.st_mode))
fatal("chroot path %s\"%s\" is not a directory",
@@ -1491,10 +1364,7 @@ safely_chroot(const char *path, uid_t uid)
void
do_setusercontext(struct passwd *pw)
{
- char *chroot_path, *tmp;
-#ifdef USE_LIBIAF
- int doing_chroot = 0;
-#endif
+ char uidstr[32], *chroot_path, *tmp;
platform_setusercontext(pw);
@@ -1517,28 +1387,26 @@ do_setusercontext(struct passwd *pw)
perror("initgroups");
exit(1);
}
-#if !defined(ANDROID)
endgrent();
#endif
-#endif
platform_setusercontext_post_groups(pw);
- if (options.chroot_directory != NULL &&
+ if (!in_chroot && options.chroot_directory != NULL &&
strcasecmp(options.chroot_directory, "none") != 0) {
tmp = tilde_expand_filename(options.chroot_directory,
pw->pw_uid);
+ snprintf(uidstr, sizeof(uidstr), "%llu",
+ (unsigned long long)pw->pw_uid);
chroot_path = percent_expand(tmp, "h", pw->pw_dir,
- "u", pw->pw_name, (char *)NULL);
+ "u", pw->pw_name, "U", uidstr, (char *)NULL);
safely_chroot(chroot_path, pw->pw_uid);
free(tmp);
free(chroot_path);
/* Make sure we don't attempt to chroot again */
free(options.chroot_directory);
options.chroot_directory = NULL;
-#ifdef USE_LIBIAF
- doing_chroot = 1;
-#endif
+ in_chroot = 1;
}
#ifdef HAVE_LOGIN_CAP
@@ -1553,16 +1421,16 @@ do_setusercontext(struct passwd *pw)
(void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUMASK);
#else
# ifdef USE_LIBIAF
-/* In a chroot environment, the set_id() will always fail; typically
- * because of the lack of necessary authentication services and runtime
- * such as ./usr/lib/libiaf.so, ./usr/lib/libpam.so.1, and ./etc/passwd
- * We skip it in the internal sftp chroot case.
- * We'll lose auditing and ACLs but permanently_set_uid will
- * take care of the rest.
- */
- if ((doing_chroot == 0) && set_id(pw->pw_name) != 0) {
- fatal("set_id(%s) Failed", pw->pw_name);
- }
+ /*
+ * In a chroot environment, the set_id() will always fail;
+ * typically because of the lack of necessary authentication
+ * services and runtime such as ./usr/lib/libiaf.so,
+ * ./usr/lib/libpam.so.1, and ./etc/passwd We skip it in the
+ * internal sftp chroot case. We'll lose auditing and ACLs but
+ * permanently_set_uid will take care of the rest.
+ */
+ if (!in_chroot && set_id(pw->pw_name) != 0)
+ fatal("set_id(%s) Failed", pw->pw_name);
# endif /* USE_LIBIAF */
/* Permanently switch to the desired uid. */
permanently_set_uid(pw);
@@ -1602,28 +1470,7 @@ do_pwchange(Session *s)
}
static void
-launch_login(struct passwd *pw, const char *hostname)
-{
- /* Launch login(1). */
-
- execl(LOGIN_PROGRAM, "login", "-h", hostname,
-#ifdef xxxLOGIN_NEEDS_TERM
- (s->term ? s->term : "unknown"),
-#endif /* LOGIN_NEEDS_TERM */
-#ifdef LOGIN_NO_ENDOPT
- "-p", "-f", pw->pw_name, (char *)NULL);
-#else
- "-p", "-f", "--", pw->pw_name, (char *)NULL);
-#endif
-
- /* Login couldn't be executed, die. */
-
- perror("login");
- exit(1);
-}
-
-static void
-child_close_fds(void)
+child_close_fds(struct ssh *ssh)
{
extern int auth_sock;
@@ -1632,26 +1479,25 @@ child_close_fds(void)
auth_sock = -1;
}
- if (packet_get_connection_in() == packet_get_connection_out())
- close(packet_get_connection_in());
+ if (ssh_packet_get_connection_in(ssh) ==
+ ssh_packet_get_connection_out(ssh))
+ close(ssh_packet_get_connection_in(ssh));
else {
- close(packet_get_connection_in());
- close(packet_get_connection_out());
+ close(ssh_packet_get_connection_in(ssh));
+ close(ssh_packet_get_connection_out(ssh));
}
/*
* Close all descriptors related to channels. They will still remain
* open in the parent.
*/
/* XXX better use close-on-exec? -markus */
- channel_close_all();
+ channel_close_all(ssh);
-#if !defined(ANDROID)
/*
* Close any extra file descriptors. Note that there may still be
* descriptors left by system functions. They will be closed later.
*/
endpwent();
-#endif
/*
* Close any extra open file descriptors so that we don't have them
@@ -1669,60 +1515,52 @@ child_close_fds(void)
*/
#define ARGV_MAX 10
void
-do_child(Session *s, const char *command)
+do_child(struct ssh *ssh, Session *s, const char *command)
{
extern char **environ;
- char **env;
- char *argv[ARGV_MAX];
- const char *shell, *shell0, *hostname = NULL;
+ char **env, *argv[ARGV_MAX], remote_id[512];
+ const char *shell, *shell0;
struct passwd *pw = s->pw;
int r = 0;
+ sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
+
/* remove hostkey from the child's memory */
destroy_sensitive_data();
+ ssh_packet_clear_keys(ssh);
/* Force a password change */
if (s->authctxt->force_pwchange) {
do_setusercontext(pw);
- child_close_fds();
+ child_close_fds(ssh);
do_pwchange(s);
exit(1);
}
- /* login(1) is only called if we execute the login shell */
- if (options.use_login && command != NULL)
- options.use_login = 0;
-
-#ifdef _UNICOS
- cray_setup(pw->pw_uid, pw->pw_name, command);
-#endif /* _UNICOS */
-
/*
* Login(1) does this as well, and it needs uid 0 for the "-h"
* switch, so we let login(1) to this for us.
*/
- if (!options.use_login) {
#ifdef HAVE_OSF_SIA
- session_setup_sia(pw, s->ttyfd == -1 ? NULL : s->tty);
- if (!check_quietlogin(s, command))
- do_motd();
+ session_setup_sia(pw, s->ttyfd == -1 ? NULL : s->tty);
+ if (!check_quietlogin(s, command))
+ do_motd();
#else /* HAVE_OSF_SIA */
- /* When PAM is enabled we rely on it to do the nologin check */
- if (!options.use_pam)
- do_nologin(pw);
- do_setusercontext(pw);
- /*
- * PAM session modules in do_setusercontext may have
- * generated messages, so if this in an interactive
- * login then display them too.
- */
- if (!check_quietlogin(s, command))
- display_loginmsg();
+ /* When PAM is enabled we rely on it to do the nologin check */
+ if (!options.use_pam)
+ do_nologin(pw);
+ do_setusercontext(pw);
+ /*
+ * PAM session modules in do_setusercontext may have
+ * generated messages, so if this in an interactive
+ * login then display them too.
+ */
+ if (!check_quietlogin(s, command))
+ display_loginmsg();
#endif /* HAVE_OSF_SIA */
- }
#ifdef USE_PAM
- if (options.use_pam && !options.use_login && !is_pam_session_open()) {
+ if (options.use_pam && !is_pam_session_open()) {
debug3("PAM session not opened, exiting");
display_loginmsg();
exit(254);
@@ -1739,24 +1577,20 @@ do_child(Session *s, const char *command)
* Make sure $SHELL points to the shell from the password file,
* even if shell is overridden from login.conf
*/
- env = do_setup_env(s, shell);
+ env = do_setup_env(ssh, s, shell);
#ifdef HAVE_LOGIN_CAP
shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
#endif
- /* we have to stash the hostname before we close our socket. */
- if (options.use_login)
- hostname = get_remote_name_or_ip(utmp_len,
- options.use_dns);
/*
* Close the connection descriptors; note that this is the child, and
* the server will still have the socket open, and it is important
* that we do not shutdown it. Note that the descriptors cannot be
* closed before building the environment, as we call
- * get_remote_ipaddr there.
+ * ssh_remote_ipaddr there.
*/
- child_close_fds();
+ child_close_fds(ssh);
/*
* Must take new environment into use so that .ssh/rc,
@@ -1791,29 +1625,30 @@ do_child(Session *s, const char *command)
#endif
/* Change current directory to the user's home directory. */
- if (chdir(pw->pw_dir) < 0) {
+ if (chdir(pw->pw_dir) == -1) {
/* Suppress missing homedir warning for chroot case */
#ifdef HAVE_LOGIN_CAP
r = login_getcapbool(lc, "requirehome", 0);
#endif
- if (r || options.chroot_directory == NULL ||
- strcasecmp(options.chroot_directory, "none") == 0)
+ if (r || !in_chroot) {
fprintf(stderr, "Could not chdir to home "
"directory %s: %s\n", pw->pw_dir,
strerror(errno));
+ }
if (r)
exit(1);
}
closefrom(STDERR_FILENO + 1);
- if (!options.use_login)
- do_rc_files(s, shell);
+ do_rc_files(ssh, s, shell);
/* restore SIGPIPE for child */
- signal(SIGPIPE, SIG_DFL);
+ ssh_signal(SIGPIPE, SIG_DFL);
if (s->is_subsystem == SUBSYSTEM_INT_SFTP_ERROR) {
+ error("Connection from %s: refusing non-sftp session",
+ remote_id);
printf("This service allows sftp connections only.\n");
fflush(NULL);
exit(1);
@@ -1838,11 +1673,6 @@ do_child(Session *s, const char *command)
fflush(NULL);
- if (options.use_login) {
- launch_login(pw, hostname);
- /* NEVERREACHED */
- }
-
/* Get the last component of the shell name. */
if ((shell0 = strrchr(shell, '/')) != NULL)
shell0++;
@@ -1920,8 +1750,8 @@ session_new(void)
return NULL;
debug2("%s: allocate (allocated %d max %d)",
__func__, sessions_nalloc, options.max_sessions);
- tmp = xrealloc(sessions, sessions_nalloc + 1,
- sizeof(*sessions));
+ tmp = xrecallocarray(sessions, sessions_nalloc,
+ sessions_nalloc + 1, sizeof(*sessions));
if (tmp == NULL) {
error("%s: cannot allocate %d sessions",
__func__, sessions_nalloc + 1);
@@ -2059,43 +1889,40 @@ session_by_pid(pid_t pid)
}
static int
-session_window_change_req(Session *s)
+session_window_change_req(struct ssh *ssh, Session *s)
{
- s->col = packet_get_int();
- s->row = packet_get_int();
- s->xpixel = packet_get_int();
- s->ypixel = packet_get_int();
- packet_check_eom();
+ int r;
+
+ if ((r = sshpkt_get_u32(ssh, &s->col)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->row)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->xpixel)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->ypixel)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
return 1;
}
static int
-session_pty_req(Session *s)
+session_pty_req(struct ssh *ssh, Session *s)
{
- u_int len;
- int n_bytes;
+ int r;
- if (no_pty_flag || !options.permit_tty) {
- debug("Allocating a pty not permitted for this authentication.");
+ if (!auth_opts->permit_pty_flag || !options.permit_tty) {
+ debug("Allocating a pty not permitted for this connection.");
return 0;
}
if (s->ttyfd != -1) {
- packet_disconnect("Protocol error: you already have a pty.");
+ ssh_packet_disconnect(ssh, "Protocol error: you already have a pty.");
return 0;
}
- s->term = packet_get_string(&len);
-
- if (compat20) {
- s->col = packet_get_int();
- s->row = packet_get_int();
- } else {
- s->row = packet_get_int();
- s->col = packet_get_int();
- }
- s->xpixel = packet_get_int();
- s->ypixel = packet_get_int();
+ if ((r = sshpkt_get_cstring(ssh, &s->term, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->col)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->row)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->xpixel)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->ypixel)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
if (strcmp(s->term, "") == 0) {
free(s->term);
@@ -2115,10 +1942,10 @@ session_pty_req(Session *s)
}
debug("session_pty_req: session %d alloc %s", s->self, s->tty);
- /* for SSH1 the tty modes length is not given */
- if (!compat20)
- n_bytes = packet_remaining();
- tty_parse_modes(s->ttyfd, &n_bytes);
+ ssh_tty_parse_modes(ssh, s->ttyfd);
+
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
if (!use_privsep)
pty_setowner(s->pw, s->tty);
@@ -2126,22 +1953,21 @@ session_pty_req(Session *s)
/* Set window size from the packet. */
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
- packet_check_eom();
session_proctitle(s);
return 1;
}
static int
-session_subsystem_req(Session *s)
+session_subsystem_req(struct ssh *ssh, Session *s)
{
struct stat st;
- u_int len;
- int success = 0;
+ int r, success = 0;
char *prog, *cmd;
u_int i;
- s->subsys = packet_get_string(&len);
- packet_check_eom();
+ if ((r = sshpkt_get_cstring(ssh, &s->subsys, NULL)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
debug2("subsystem request for %.100s by user %s", s->subsys,
s->pw->pw_name);
@@ -2153,13 +1979,13 @@ session_subsystem_req(Session *s)
s->is_subsystem = SUBSYSTEM_INT_SFTP;
debug("subsystem: %s", prog);
} else {
- if (stat(prog, &st) < 0)
+ if (stat(prog, &st) == -1)
debug("subsystem: cannot stat %s: %s",
prog, strerror(errno));
s->is_subsystem = SUBSYSTEM_EXT;
debug("subsystem: exec() %s", cmd);
}
- success = do_exec(s, cmd) == 0;
+ success = do_exec(ssh, s, cmd) == 0;
break;
}
}
@@ -2172,22 +1998,32 @@ session_subsystem_req(Session *s)
}
static int
-session_x11_req(Session *s)
+session_x11_req(struct ssh *ssh, Session *s)
{
- int success;
+ int r, success;
+ u_char single_connection = 0;
if (s->auth_proto != NULL || s->auth_data != NULL) {
error("session_x11_req: session %d: "
"x11 forwarding already active", s->self);
return 0;
}
- s->single_connection = packet_get_char();
- s->auth_proto = packet_get_string(NULL);
- s->auth_data = packet_get_string(NULL);
- s->screen = packet_get_int();
- packet_check_eom();
+ if ((r = sshpkt_get_u8(ssh, &single_connection)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &s->auth_proto, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &s->auth_data, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->screen)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+
+ s->single_connection = single_connection;
- success = session_setup_x11fwd(s);
+ if (xauth_valid_string(s->auth_proto) &&
+ xauth_valid_string(s->auth_data))
+ success = session_setup_x11fwd(ssh, s);
+ else {
+ success = 0;
+ error("Invalid X11 forwarding data");
+ }
if (!success) {
free(s->auth_proto);
free(s->auth_data);
@@ -2198,45 +2034,56 @@ session_x11_req(Session *s)
}
static int
-session_shell_req(Session *s)
+session_shell_req(struct ssh *ssh, Session *s)
{
- packet_check_eom();
- return do_exec(s, NULL) == 0;
+ int r;
+
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+ return do_exec(ssh, s, NULL) == 0;
}
static int
-session_exec_req(Session *s)
+session_exec_req(struct ssh *ssh, Session *s)
{
- u_int len, success;
+ u_int success;
+ int r;
+ char *command = NULL;
+
+ if ((r = sshpkt_get_cstring(ssh, &command, NULL)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
- char *command = packet_get_string(&len);
- packet_check_eom();
- success = do_exec(s, command) == 0;
+ success = do_exec(ssh, s, command) == 0;
free(command);
return success;
}
static int
-session_break_req(Session *s)
+session_break_req(struct ssh *ssh, Session *s)
{
+ int r;
- packet_get_int(); /* ignored */
- packet_check_eom();
+ if ((r = sshpkt_get_u32(ssh, NULL)) != 0 || /* ignore */
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
- if (s->ptymaster == -1 || tcsendbreak(s->ptymaster, 0) < 0)
+ if (s->ptymaster == -1 || tcsendbreak(s->ptymaster, 0) == -1)
return 0;
return 1;
}
static int
-session_env_req(Session *s)
+session_env_req(struct ssh *ssh, Session *s)
{
char *name, *val;
- u_int name_len, val_len, i;
+ u_int i;
+ int r;
- name = packet_get_cstring(&name_len);
- val = packet_get_cstring(&val_len);
- packet_check_eom();
+ if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &val, NULL)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
/* Don't set too many environment variables */
if (s->num_env > 128) {
@@ -2247,8 +2094,8 @@ session_env_req(Session *s)
for (i = 0; i < options.num_accept_env; i++) {
if (match_pattern(name, options.accept_env[i])) {
debug2("Setting env %d: %s=%s", s->num_env, name, val);
- s->env = xrealloc(s->env, s->num_env + 1,
- sizeof(*s->env));
+ s->env = xrecallocarray(s->env, s->num_env,
+ s->num_env + 1, sizeof(*s->env));
s->env[s->num_env].name = name;
s->env[s->num_env].val = val;
s->num_env++;
@@ -2263,35 +2110,110 @@ session_env_req(Session *s)
return (0);
}
+/*
+ * Conversion of signals from ssh channel request names.
+ * Subset of signals from RFC 4254 section 6.10C, with SIGINFO as
+ * local extension.
+ */
static int
-session_auth_agent_req(Session *s)
+name2sig(char *name)
+{
+#define SSH_SIG(x) if (strcmp(name, #x) == 0) return SIG ## x
+ SSH_SIG(HUP);
+ SSH_SIG(INT);
+ SSH_SIG(KILL);
+ SSH_SIG(QUIT);
+ SSH_SIG(TERM);
+ SSH_SIG(USR1);
+ SSH_SIG(USR2);
+#undef SSH_SIG
+#ifdef SIGINFO
+ if (strcmp(name, "INFO@openssh.com") == 0)
+ return SIGINFO;
+#endif
+ return -1;
+}
+
+static int
+session_signal_req(struct ssh *ssh, Session *s)
+{
+ char *signame = NULL;
+ int r, sig, success = 0;
+
+ if ((r = sshpkt_get_cstring(ssh, &signame, NULL)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0) {
+ error("%s: parse packet: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if ((sig = name2sig(signame)) == -1) {
+ error("%s: unsupported signal \"%s\"", __func__, signame);
+ goto out;
+ }
+ if (s->pid <= 0) {
+ error("%s: no pid for session %d", __func__, s->self);
+ goto out;
+ }
+ if (s->forced || s->is_subsystem) {
+ error("%s: refusing to send signal %s to %s session", __func__,
+ signame, s->forced ? "forced-command" : "subsystem");
+ goto out;
+ }
+ if (!use_privsep || mm_is_monitor()) {
+ error("%s: session signalling requires privilege separation",
+ __func__);
+ goto out;
+ }
+
+ debug("%s: signal %s, killpg(%ld, %d)", __func__, signame,
+ (long)s->pid, sig);
+ temporarily_use_uid(s->pw);
+ r = killpg(s->pid, sig);
+ restore_uid();
+ if (r != 0) {
+ error("%s: killpg(%ld, %d): %s", __func__, (long)s->pid,
+ sig, strerror(errno));
+ goto out;
+ }
+
+ /* success */
+ success = 1;
+ out:
+ free(signame);
+ return success;
+}
+
+static int
+session_auth_agent_req(struct ssh *ssh, Session *s)
{
static int called = 0;
- packet_check_eom();
- if (no_agent_forwarding_flag || !options.allow_agent_forwarding) {
- debug("session_auth_agent_req: no_agent_forwarding_flag");
+ int r;
+
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+ if (!auth_opts->permit_agent_forwarding_flag ||
+ !options.allow_agent_forwarding) {
+ debug("%s: agent forwarding disabled", __func__);
return 0;
}
if (called) {
return 0;
} else {
called = 1;
- return auth_input_request_forwarding(s->pw);
+ return auth_input_request_forwarding(ssh, s->pw);
}
}
int
-session_input_channel_req(Channel *c, const char *rtype)
+session_input_channel_req(struct ssh *ssh, Channel *c, const char *rtype)
{
int success = 0;
Session *s;
if ((s = session_by_channel(c->self)) == NULL) {
- logit("session_input_channel_req: no session %d req %.100s",
- c->self, rtype);
+ logit("%s: no session %d req %.100s", __func__, c->self, rtype);
return 0;
}
- debug("session_input_channel_req: session %d req %s", s->self, rtype);
+ debug("%s: session %d req %s", __func__, s->self, rtype);
/*
* a session is in LARVAL state until a shell, a command
@@ -2299,43 +2221,43 @@ session_input_channel_req(Channel *c, const char *rtype)
*/
if (c->type == SSH_CHANNEL_LARVAL) {
if (strcmp(rtype, "shell") == 0) {
- success = session_shell_req(s);
+ success = session_shell_req(ssh, s);
} else if (strcmp(rtype, "exec") == 0) {
- success = session_exec_req(s);
+ success = session_exec_req(ssh, s);
} else if (strcmp(rtype, "pty-req") == 0) {
- success = session_pty_req(s);
+ success = session_pty_req(ssh, s);
} else if (strcmp(rtype, "x11-req") == 0) {
- success = session_x11_req(s);
+ success = session_x11_req(ssh, s);
} else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {
- success = session_auth_agent_req(s);
+ success = session_auth_agent_req(ssh, s);
} else if (strcmp(rtype, "subsystem") == 0) {
- success = session_subsystem_req(s);
+ success = session_subsystem_req(ssh, s);
} else if (strcmp(rtype, "env") == 0) {
- success = session_env_req(s);
+ success = session_env_req(ssh, s);
}
}
if (strcmp(rtype, "window-change") == 0) {
- success = session_window_change_req(s);
+ success = session_window_change_req(ssh, s);
} else if (strcmp(rtype, "break") == 0) {
- success = session_break_req(s);
+ success = session_break_req(ssh, s);
+ } else if (strcmp(rtype, "signal") == 0) {
+ success = session_signal_req(ssh, s);
}
return success;
}
void
-session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr,
- int is_tty)
+session_set_fds(struct ssh *ssh, Session *s,
+ int fdin, int fdout, int fderr, int ignore_fderr, int is_tty)
{
- if (!compat20)
- fatal("session_set_fds: called for proto != 2.0");
/*
* now that have a child and a pipe to the child,
* we can activate our channel and register the fd's
*/
if (s->chanid == -1)
fatal("no channel for session %d", s->self);
- channel_set_fds(s->chanid,
+ channel_set_fds(ssh, s->chanid,
fdout, fdin, fderr,
ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
1, is_tty, CHAN_SES_WINDOW_DEFAULT);
@@ -2349,13 +2271,13 @@ void
session_pty_cleanup2(Session *s)
{
if (s == NULL) {
- error("session_pty_cleanup: no session");
+ error("%s: no session", __func__);
return;
}
if (s->ttyfd == -1)
return;
- debug("session_pty_cleanup: session %d release %s", s->self, s->tty);
+ debug("%s: session %d release %s", __func__, s->self, s->tty);
/* Record that the user has logged out. */
if (s->pid != 0)
@@ -2370,7 +2292,7 @@ session_pty_cleanup2(Session *s)
* the pty cleanup, so that another process doesn't get this pty
* while we're still cleaning up.
*/
- if (s->ptymaster != -1 && close(s->ptymaster) < 0)
+ if (s->ptymaster != -1 && close(s->ptymaster) == -1)
error("close(s->ptymaster/%d): %s",
s->ptymaster, strerror(errno));
@@ -2406,40 +2328,40 @@ sig2name(int sig)
}
static void
-session_close_x11(int id)
+session_close_x11(struct ssh *ssh, int id)
{
Channel *c;
- if ((c = channel_by_id(id)) == NULL) {
- debug("session_close_x11: x11 channel %d missing", id);
+ if ((c = channel_by_id(ssh, id)) == NULL) {
+ debug("%s: x11 channel %d missing", __func__, id);
} else {
/* Detach X11 listener */
- debug("session_close_x11: detach x11 channel %d", id);
- channel_cancel_cleanup(id);
+ debug("%s: detach x11 channel %d", __func__, id);
+ channel_cancel_cleanup(ssh, id);
if (c->ostate != CHAN_OUTPUT_CLOSED)
- chan_mark_dead(c);
+ chan_mark_dead(ssh, c);
}
}
static void
-session_close_single_x11(int id, void *arg)
+session_close_single_x11(struct ssh *ssh, int id, void *arg)
{
Session *s;
u_int i;
- debug3("session_close_single_x11: channel %d", id);
- channel_cancel_cleanup(id);
+ debug3("%s: channel %d", __func__, id);
+ channel_cancel_cleanup(ssh, id);
if ((s = session_by_x11_channel(id)) == NULL)
- fatal("session_close_single_x11: no x11 channel %d", id);
+ fatal("%s: no x11 channel %d", __func__, id);
for (i = 0; s->x11_chanids[i] != -1; i++) {
- debug("session_close_single_x11: session %d: "
- "closing channel %d", s->self, s->x11_chanids[i]);
+ debug("%s: session %d: closing channel %d",
+ __func__, s->self, s->x11_chanids[i]);
/*
* The channel "id" is already closing, but make sure we
* close all of its siblings.
*/
if (s->x11_chanids[i] != id)
- session_close_x11(s->x11_chanids[i]);
+ session_close_x11(ssh, s->x11_chanids[i]);
}
free(s->x11_chanids);
s->x11_chanids = NULL;
@@ -2454,45 +2376,47 @@ session_close_single_x11(int id, void *arg)
}
static void
-session_exit_message(Session *s, int status)
+session_exit_message(struct ssh *ssh, Session *s, int status)
{
Channel *c;
+ int r;
- if ((c = channel_lookup(s->chanid)) == NULL)
- fatal("session_exit_message: session %d: no channel %d",
- s->self, s->chanid);
- debug("session_exit_message: session %d channel %d pid %ld",
- s->self, s->chanid, (long)s->pid);
+ if ((c = channel_lookup(ssh, s->chanid)) == NULL)
+ fatal("%s: session %d: no channel %d",
+ __func__, s->self, s->chanid);
+ debug("%s: session %d channel %d pid %ld",
+ __func__, s->self, s->chanid, (long)s->pid);
if (WIFEXITED(status)) {
- channel_request_start(s->chanid, "exit-status", 0);
- packet_put_int(WEXITSTATUS(status));
- packet_send();
+ channel_request_start(ssh, s->chanid, "exit-status", 0);
+ if ((r = sshpkt_put_u32(ssh, WEXITSTATUS(status))) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: exit reply", __func__);
} else if (WIFSIGNALED(status)) {
- channel_request_start(s->chanid, "exit-signal", 0);
- packet_put_cstring(sig2name(WTERMSIG(status)));
-#ifdef WCOREDUMP
- packet_put_char(WCOREDUMP(status)? 1 : 0);
-#else /* WCOREDUMP */
- packet_put_char(0);
-#endif /* WCOREDUMP */
- packet_put_cstring("");
- packet_put_cstring("");
- packet_send();
+ channel_request_start(ssh, s->chanid, "exit-signal", 0);
+#ifndef WCOREDUMP
+# define WCOREDUMP(x) (0)
+#endif
+ if ((r = sshpkt_put_cstring(ssh, sig2name(WTERMSIG(status)))) != 0 ||
+ (r = sshpkt_put_u8(ssh, WCOREDUMP(status)? 1 : 0)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: exit reply", __func__);
} else {
/* Some weird exit cause. Just exit. */
- packet_disconnect("wait returned status %04x.", status);
+ ssh_packet_disconnect(ssh, "wait returned status %04x.", status);
}
/* disconnect channel */
- debug("session_exit_message: release channel %d", s->chanid);
+ debug("%s: release channel %d", __func__, s->chanid);
/*
* Adjust cleanup callback attachment to send close messages when
* the channel gets EOF. The session will be then be closed
- * by session_close_by_channel when the childs close their fds.
+ * by session_close_by_channel when the child sessions close their fds.
*/
- channel_register_cleanup(c->self, session_close_by_channel, 1);
+ channel_register_cleanup(ssh, c->self, session_close_by_channel, 1);
/*
* emulate a write failure with 'chan_write_failed', nobody will be
@@ -2501,15 +2425,20 @@ session_exit_message(Session *s, int status)
* be some more data waiting in the pipe.
*/
if (c->ostate != CHAN_OUTPUT_CLOSED)
- chan_write_failed(c);
+ chan_write_failed(ssh, c);
}
void
-session_close(Session *s)
+session_close(struct ssh *ssh, Session *s)
{
u_int i;
- debug("session_close: session %d pid %ld", s->self, (long)s->pid);
+ verbose("Close session: user %s from %.200s port %d id %d",
+ s->pw->pw_name,
+ ssh_remote_ipaddr(ssh),
+ ssh_remote_port(ssh),
+ s->self);
+
if (s->ttyfd != -1)
session_pty_cleanup(s);
free(s->term);
@@ -2531,16 +2460,15 @@ session_close(Session *s)
}
void
-session_close_by_pid(pid_t pid, int status)
+session_close_by_pid(struct ssh *ssh, pid_t pid, int status)
{
Session *s = session_by_pid(pid);
if (s == NULL) {
- debug("session_close_by_pid: no session for pid %ld",
- (long)pid);
+ debug("%s: no session for pid %ld", __func__, (long)pid);
return;
}
if (s->chanid != -1)
- session_exit_message(s, status);
+ session_exit_message(ssh, s, status);
if (s->ttyfd != -1)
session_pty_cleanup(s);
s->pid = 0;
@@ -2551,19 +2479,19 @@ session_close_by_pid(pid_t pid, int status)
* the session 'child' itself dies
*/
void
-session_close_by_channel(int id, void *arg)
+session_close_by_channel(struct ssh *ssh, int id, void *arg)
{
Session *s = session_by_channel(id);
u_int i;
if (s == NULL) {
- debug("session_close_by_channel: no session for id %d", id);
+ debug("%s: no session for id %d", __func__, id);
return;
}
- debug("session_close_by_channel: channel %d child %ld",
- id, (long)s->pid);
+ debug("%s: channel %d child %ld", __func__, id, (long)s->pid);
if (s->pid != 0) {
- debug("session_close_by_channel: channel %d: has child", id);
+ debug("%s: channel %d: has child, ttyfd %d",
+ __func__, id, s->ttyfd);
/*
* delay detach of session, but release pty, since
* the fd's to the child are already closed
@@ -2573,22 +2501,22 @@ session_close_by_channel(int id, void *arg)
return;
}
/* detach by removing callback */
- channel_cancel_cleanup(s->chanid);
+ channel_cancel_cleanup(ssh, s->chanid);
/* Close any X11 listeners associated with this session */
if (s->x11_chanids != NULL) {
for (i = 0; s->x11_chanids[i] != -1; i++) {
- session_close_x11(s->x11_chanids[i]);
+ session_close_x11(ssh, s->x11_chanids[i]);
s->x11_chanids[i] = -1;
}
}
s->chanid = -1;
- session_close(s);
+ session_close(ssh, s);
}
void
-session_destroy_all(void (*closefunc)(Session *))
+session_destroy_all(struct ssh *ssh, void (*closefunc)(Session *))
{
int i;
for (i = 0; i < sessions_nalloc; i++) {
@@ -2597,7 +2525,7 @@ session_destroy_all(void (*closefunc)(Session *))
if (closefunc != NULL)
closefunc(s);
else
- session_close(s);
+ session_close(ssh, s);
}
}
}
@@ -2640,15 +2568,15 @@ session_proctitle(Session *s)
}
int
-session_setup_x11fwd(Session *s)
+session_setup_x11fwd(struct ssh *ssh, Session *s)
{
struct stat st;
char display[512], auth_display[512];
char hostname[NI_MAXHOST];
u_int i;
- if (no_x11_forwarding_flag) {
- packet_send_debug("X11 forwarding disabled in user configuration file.");
+ if (!auth_opts->permit_x11_forwarding_flag) {
+ ssh_packet_send_debug(ssh, "X11 forwarding disabled by key options.");
return 0;
}
if (!options.x11_forwarding) {
@@ -2657,31 +2585,26 @@ session_setup_x11fwd(Session *s)
}
if (options.xauth_location == NULL ||
(stat(options.xauth_location, &st) == -1)) {
- packet_send_debug("No xauth program; cannot forward with spoofing.");
- return 0;
- }
- if (options.use_login) {
- packet_send_debug("X11 forwarding disabled; "
- "not compatible with UseLogin=yes.");
+ ssh_packet_send_debug(ssh, "No xauth program; cannot forward X11.");
return 0;
}
if (s->display != NULL) {
debug("X11 display already set.");
return 0;
}
- if (x11_create_display_inet(options.x11_display_offset,
+ if (x11_create_display_inet(ssh, options.x11_display_offset,
options.x11_use_localhost, s->single_connection,
&s->display_number, &s->x11_chanids) == -1) {
debug("x11_create_display_inet failed.");
return 0;
}
for (i = 0; s->x11_chanids[i] != -1; i++) {
- channel_register_cleanup(s->x11_chanids[i],
+ channel_register_cleanup(ssh, s->x11_chanids[i],
session_close_single_x11, 0);
}
/* Set up a suitable value for the DISPLAY variable. */
- if (gethostname(hostname, sizeof(hostname)) < 0)
+ if (gethostname(hostname, sizeof(hostname)) == -1)
fatal("gethostname: %.100s", strerror(errno));
/*
* auth_display must be used as the displayname when the
@@ -2703,7 +2626,7 @@ session_setup_x11fwd(Session *s)
he = gethostbyname(hostname);
if (he == NULL) {
error("Can't get IP address for X11 DISPLAY.");
- packet_send_debug("Can't get IP address for X11 DISPLAY.");
+ ssh_packet_send_debug(ssh, "Can't get IP address for X11 DISPLAY.");
return 0;
}
memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));
@@ -2721,13 +2644,13 @@ session_setup_x11fwd(Session *s)
}
static void
-do_authenticated2(Authctxt *authctxt)
+do_authenticated2(struct ssh *ssh, Authctxt *authctxt)
{
- server_loop2(authctxt);
+ server_loop2(ssh, authctxt);
}
void
-do_cleanup(Authctxt *authctxt)
+do_cleanup(struct ssh *ssh, Authctxt *authctxt)
{
static int called = 0;
@@ -2762,17 +2685,41 @@ do_cleanup(Authctxt *authctxt)
#endif
#ifdef GSSAPI
- if (compat20 && options.gss_cleanup_creds)
+ if (options.gss_cleanup_creds)
ssh_gssapi_cleanup_creds();
#endif
/* remove agent socket */
auth_sock_cleanup_proc(authctxt->pw);
+ /* remove userauth info */
+ if (auth_info_file != NULL) {
+ temporarily_use_uid(authctxt->pw);
+ unlink(auth_info_file);
+ restore_uid();
+ free(auth_info_file);
+ auth_info_file = NULL;
+ }
+
/*
* Cleanup ptys/utmp only if privsep is disabled,
* or if running in monitor.
*/
if (!use_privsep || mm_is_monitor())
- session_destroy_all(session_pty_cleanup2);
+ session_destroy_all(ssh, session_pty_cleanup2);
}
+
+/* Return a name for the remote host that fits inside utmp_size */
+
+const char *
+session_get_remote_name_or_ip(struct ssh *ssh, u_int utmp_size, int use_dns)
+{
+ const char *remote = "";
+
+ if (utmp_size > 0)
+ remote = auth_get_canonical_hostname(ssh, use_dns);
+ if (utmp_size == 0 || strlen(remote) > utmp_size)
+ remote = ssh_remote_ipaddr(ssh);
+ return remote;
+}
+
diff --git a/session.h b/session.h
index 6a2f35e4..ce59dabd 100644
--- a/session.h
+++ b/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.31 2013/10/14 21:20:52 djm Exp $ */
+/* $OpenBSD: session.h,v 1.36 2018/10/02 12:40:07 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -35,6 +35,7 @@ struct Session {
struct passwd *pw;
Authctxt *authctxt;
pid_t pid;
+ int forced;
/* tty */
char *term;
@@ -51,7 +52,6 @@ struct Session {
char *auth_data;
int single_connection;
- /* proto 2 */
int chanid;
int *x11_chanids;
int is_subsystem;
@@ -63,22 +63,22 @@ struct Session {
} *env;
};
-void do_authenticated(Authctxt *);
-void do_cleanup(Authctxt *);
+void do_authenticated(struct ssh *, Authctxt *);
+void do_cleanup(struct ssh *, Authctxt *);
int session_open(Authctxt *, int);
void session_unused(int);
-int session_input_channel_req(Channel *, const char *);
-void session_close_by_pid(pid_t, int);
-void session_close_by_channel(int, void *);
-void session_destroy_all(void (*)(Session *));
+int session_input_channel_req(struct ssh *, Channel *, const char *);
+void session_close_by_pid(struct ssh *ssh, pid_t, int);
+void session_close_by_channel(struct ssh *, int, void *);
+void session_destroy_all(struct ssh *, void (*)(Session *));
void session_pty_cleanup2(Session *);
Session *session_new(void);
Session *session_by_tty(char *);
-void session_close(Session *);
+void session_close(struct ssh *, Session *);
void do_setusercontext(struct passwd *);
-void child_set_env(char ***envp, u_int *envsizep, const char *name,
- const char *value);
+
+const char *session_get_remote_name_or_ip(struct ssh *, u_int, int);
#endif
diff --git a/sftp-client.c b/sftp-client.c
index 80f4805c..72f7fff7 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-client.c,v 1.117 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: sftp-client.c,v 1.135 2019/10/04 04:31:59 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@@ -22,7 +22,6 @@
#include "includes.h"
-#include <sys/param.h> /* MIN MAX */
#include <sys/types.h>
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
@@ -53,6 +52,7 @@
#include "atomicio.h"
#include "progressmeter.h"
#include "misc.h"
+#include "utf8.h"
#include "sftp.h"
#include "sftp-common.h"
@@ -67,6 +67,13 @@ extern int showprogress;
/* Maximum depth to descend in directory trees */
#define MAX_DIR_DEPTH 64
+/* Directory separator characters */
+#ifdef HAVE_CYGWIN
+# define SFTP_DIRECTORY_CHARS "/\\"
+#else /* HAVE_CYGWIN */
+# define SFTP_DIRECTORY_CHARS "/"
+#endif /* HAVE_CYGWIN */
+
struct sftp_conn {
int fd_in;
int fd_out;
@@ -79,6 +86,7 @@ struct sftp_conn {
#define SFTP_EXT_FSTATVFS 0x00000004
#define SFTP_EXT_HARDLINK 0x00000008
#define SFTP_EXT_FSYNC 0x00000010
+#define SFTP_EXT_LSETSTAT 0x00000020
u_int exts;
u_int64_t limit_kbps;
struct bwlimit bwlimit_in, bwlimit_out;
@@ -94,7 +102,9 @@ sftpio(void *_bwlimit, size_t amount)
{
struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
- bandwidth_limit(bwlimit, amount);
+ refresh_progress_meter(0);
+ if (bwlimit != NULL)
+ bandwidth_limit(bwlimit, amount);
return 0;
}
@@ -114,8 +124,8 @@ send_msg(struct sftp_conn *conn, struct sshbuf *m)
iov[1].iov_base = (u_char *)sshbuf_ptr(m);
iov[1].iov_len = sshbuf_len(m);
- if (atomiciov6(writev, conn->fd_out, iov, 2,
- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) !=
+ if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio,
+ conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) !=
sshbuf_len(m) + sizeof(mlen))
fatal("Couldn't send packet: %s", strerror(errno));
@@ -123,7 +133,7 @@ send_msg(struct sftp_conn *conn, struct sshbuf *m)
}
static void
-get_msg(struct sftp_conn *conn, struct sshbuf *m)
+get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
{
u_int msg_len;
u_char *p;
@@ -131,9 +141,9 @@ get_msg(struct sftp_conn *conn, struct sshbuf *m)
if ((r = sshbuf_reserve(m, 4, &p)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (atomicio6(read, conn->fd_in, p, 4,
- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) {
- if (errno == EPIPE)
+ if (atomicio6(read, conn->fd_in, p, 4, sftpio,
+ conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
+ if (errno == EPIPE || errno == ECONNRESET)
fatal("Connection closed");
else
fatal("Couldn't read packet: %s", strerror(errno));
@@ -141,13 +151,17 @@ get_msg(struct sftp_conn *conn, struct sshbuf *m)
if ((r = sshbuf_get_u32(m, &msg_len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (msg_len > SFTP_MAX_MSG_LENGTH)
- fatal("Received message too long %u", msg_len);
+ if (msg_len > SFTP_MAX_MSG_LENGTH) {
+ do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL,
+ "Received message too long %u", msg_len);
+ fatal("Ensure the remote shell produces no output "
+ "for non-interactive sessions.");
+ }
if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (atomicio6(read, conn->fd_in, p, msg_len,
- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in)
+ if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
+ conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
!= msg_len) {
if (errno == EPIPE)
fatal("Connection closed");
@@ -157,6 +171,12 @@ get_msg(struct sftp_conn *conn, struct sshbuf *m)
}
static void
+get_msg(struct sftp_conn *conn, struct sshbuf *m)
+{
+ get_msg_extended(conn, m, 0);
+}
+
+static void
send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s,
u_int len)
{
@@ -399,7 +419,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
sshbuf_reset(msg);
- get_msg(ret, msg);
+ get_msg_extended(ret, msg, 1);
/* Expecting a VERSION reply */
if ((r = sshbuf_get_u8(msg, &type)) != 0)
@@ -408,6 +428,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
error("Invalid packet back from SSH2_FXP_INIT (type %u)",
type);
sshbuf_free(msg);
+ free(ret);
return(NULL);
}
if ((r = sshbuf_get_u32(msg, &ret->version)) != 0)
@@ -445,6 +466,10 @@ 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_FSYNC;
known = 1;
+ } else if (strcmp(name, "lsetstat@openssh.com") == 0 &&
+ strcmp((char *)value, "1") == 0) {
+ ret->exts |= SFTP_EXT_LSETSTAT;
+ known = 1;
}
if (known) {
debug2("Server supports extension \"%s\" revision %s",
@@ -460,7 +485,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
/* Some filexfer v.0 servers don't support large packets */
if (ret->version == 0)
- ret->transfer_buflen = MIN(ret->transfer_buflen, 20480);
+ ret->transfer_buflen = MINIMUM(ret->transfer_buflen, 20480);
ret->limit_kbps = limit_kbps;
if (ret->limit_kbps > 0) {
@@ -514,8 +539,7 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
struct sshbuf *msg;
u_int count, id, i, expected_id, ents = 0;
size_t handle_len;
- u_char type;
- char *handle;
+ u_char type, *handle;
int status = SSH2_FX_FAILURE;
int r;
@@ -587,6 +611,8 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
if ((r = sshbuf_get_u32(msg, &count)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (count > SSHBUF_SIZE_MAX)
+ fatal("%s: nonsensical number of entries", __func__);
if (count == 0)
break;
debug3("Received %d SSH2_FXP_NAME responses", count);
@@ -605,23 +631,22 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
__func__, ssh_err(r));
free(filename);
free(longname);
- sshbuf_free(msg);
- return -1;
+ goto out;
}
if (print_flag)
- printf("%s\n", longname);
+ mprintf("%s\n", longname);
/*
* Directory entries should never contain '/'
* These can be used to attack recursive ops
* (e.g. send '../../../../etc/passwd')
*/
- if (strchr(filename, '/') != NULL) {
+ if (strpbrk(filename, SFTP_DIRECTORY_CHARS) != NULL) {
error("Server sent suspect path \"%s\" "
"during readdir of \"%s\"", filename, path);
} else if (dir) {
- *dir = xrealloc(*dir, ents + 2, sizeof(**dir));
+ *dir = xreallocarray(*dir, ents + 2, sizeof(**dir));
(*dir)[ents] = xcalloc(1, sizeof(***dir));
(*dir)[ents]->filename = xstrdup(filename);
(*dir)[ents]->longname = xstrdup(longname);
@@ -650,7 +675,7 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
**dir = NULL;
}
- return status;
+ return status == SSH2_FX_OK ? 0 : -1;
}
int
@@ -1000,7 +1025,7 @@ do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
if (status != SSH2_FX_OK)
error("Couldn't sync file: %s", fx2txt(status));
- return status;
+ return status == SSH2_FX_OK ? 0 : -1;
}
#ifdef notyet
@@ -1077,7 +1102,6 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- sshbuf_reset(msg);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
@@ -1106,7 +1130,6 @@ do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- sshbuf_reset(msg);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
@@ -1119,6 +1142,38 @@ do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
}
#endif
+int
+do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a)
+{
+ struct sshbuf *msg;
+ u_int status, id;
+ int r;
+
+ if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) {
+ error("Server does not support lsetstat@openssh.com extension");
+ return -1;
+ }
+
+ id = conn->msg_id++;
+ if ((msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
+ (r = sshbuf_put_u32(msg, id)) != 0 ||
+ (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
+ (r = sshbuf_put_cstring(msg, path)) != 0 ||
+ (r = encode_attrib(msg, a)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ send_msg(conn, msg);
+ sshbuf_free(msg);
+
+ status = get_status(conn, id);
+ if (status != SSH2_FX_OK)
+ error("Couldn't setstat on \"%s\": %s", path,
+ fx2txt(status));
+
+ return status == SSH2_FX_OK ? 0 : -1;
+}
+
static void
send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
u_int len, const u_char *handle, u_int handle_len)
@@ -1128,7 +1183,6 @@ send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- sshbuf_reset(msg);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
@@ -1148,7 +1202,7 @@ do_download(struct sftp_conn *conn, const char *remote_path,
struct sshbuf *msg;
u_char *handle;
int local_fd = -1, write_error;
- int read_error, write_errno, reordered = 0, r;
+ int read_error, write_errno, lmodified = 0, reordered = 0, r;
u_int64_t offset = 0, size, highwater;
u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK;
off_t progress_counter;
@@ -1318,6 +1372,7 @@ do_download(struct sftp_conn *conn, const char *remote_path,
if (len > req->len)
fatal("Received more data than asked for "
"%zu > %zu", len, req->len);
+ lmodified = 1;
if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||
atomicio(vwrite, local_fd, data, len) != len) &&
!write_error) {
@@ -1350,7 +1405,7 @@ do_download(struct sftp_conn *conn, const char *remote_path,
req->offset, req->len, handle, handle_len);
/* Reduce the request size */
if (len < buflen)
- buflen = MAX(MIN_READ_SIZE, len);
+ buflen = MAXIMUM(MIN_READ_SIZE, len);
}
if (max_req > 0) { /* max_req = 0 iff EOF received */
if (size > 0 && offset > size) {
@@ -1384,7 +1439,9 @@ do_download(struct sftp_conn *conn, const char *remote_path,
"server reordered requests", local_path);
}
debug("truncating at %llu", (unsigned long long)highwater);
- ftruncate(local_fd, highwater);
+ if (ftruncate(local_fd, highwater) == -1)
+ error("ftruncate \"%s\": %s", local_path,
+ strerror(errno));
}
if (read_error) {
error("Couldn't read from remote file \"%s\" : %s",
@@ -1419,7 +1476,9 @@ do_download(struct sftp_conn *conn, const char *remote_path,
error("Can't set times on \"%s\": %s",
local_path, strerror(errno));
}
- if (fsync_flag) {
+ if (resume_flag && !lmodified)
+ logit("File \"%s\" was not modified", local_path);
+ else if (fsync_flag) {
debug("syncing \"%s\"", local_path);
if (fsync(local_fd) == -1)
error("Couldn't sync file \"%s\": %s",
@@ -1430,7 +1489,7 @@ do_download(struct sftp_conn *conn, const char *remote_path,
sshbuf_free(msg);
free(handle);
- return(status);
+ return status == SSH2_FX_OK ? 0 : -1;
}
static int
@@ -1440,7 +1499,7 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
{
int i, ret = 0;
SFTP_DIRENT **dir_entries;
- char *filename, *new_src, *new_dst;
+ char *filename, *new_src = NULL, *new_dst = NULL;
mode_t mode = 0777;
if (depth >= MAX_DIR_DEPTH) {
@@ -1458,7 +1517,7 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
return -1;
}
if (print_flag)
- printf("Retrieving %s\n", src);
+ mprintf("Retrieving %s\n", src);
if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
mode = dirattrib->perm & 01777;
@@ -1478,8 +1537,10 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
}
for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
- filename = dir_entries[i]->filename;
+ free(new_dst);
+ free(new_src);
+ filename = dir_entries[i]->filename;
new_dst = path_append(dst, filename);
new_src = path_append(src, filename);
@@ -1502,9 +1563,9 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
} else
logit("%s: not a regular file\n", new_src);
- free(new_dst);
- free(new_src);
}
+ free(new_dst);
+ free(new_src);
if (preserve_flag) {
if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
@@ -1598,7 +1659,7 @@ do_upload(struct sftp_conn *conn, const char *local_path,
if (resume) {
/* Get remote file size if it exists */
if ((c = do_stat(conn, remote_path, 0)) == NULL) {
- close(local_fd);
+ close(local_fd);
return -1;
}
@@ -1757,7 +1818,7 @@ do_upload(struct sftp_conn *conn, const char *local_path,
if (fsync_flag)
(void)do_fsync(conn, handle, handle_len);
- if (do_close(conn, handle, handle_len) != SSH2_FX_OK)
+ if (do_close(conn, handle, handle_len) != 0)
status = SSH2_FX_FAILURE;
free(handle);
@@ -1770,12 +1831,11 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
int depth, int preserve_flag, int print_flag, int resume, int fsync_flag)
{
int ret = 0;
- u_int status;
DIR *dirp;
struct dirent *dp;
- char *filename, *new_src, *new_dst;
+ char *filename, *new_src = NULL, *new_dst = NULL;
struct stat sb;
- Attrib a;
+ Attrib a, *dirattrib;
if (depth >= MAX_DIR_DEPTH) {
error("Maximum directory depth exceeded: %d levels", depth);
@@ -1792,7 +1852,7 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
return -1;
}
if (print_flag)
- printf("Entering %s\n", src);
+ mprintf("Entering %s\n", src);
attrib_clear(&a);
stat_to_attrib(&sb, &a);
@@ -1802,17 +1862,18 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
if (!preserve_flag)
a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
- status = do_mkdir(conn, dst, &a, 0);
/*
- * we lack a portable status for errno EEXIST,
- * so if we get a SSH2_FX_FAILURE back we must check
- * if it was created successfully.
+ * sftp lacks a portable status value to match errno EEXIST,
+ * so if we get a failure back then we must check whether
+ * the path already existed and is a directory.
*/
- if (status != SSH2_FX_OK) {
- if (status != SSH2_FX_FAILURE)
+ if (do_mkdir(conn, dst, &a, 0) != 0) {
+ if ((dirattrib = do_stat(conn, dst, 0)) == NULL)
return -1;
- if (do_stat(conn, dst, 0) == NULL)
+ if (!S_ISDIR(dirattrib->perm)) {
+ error("\"%s\" exists but is not a directory", dst);
return -1;
+ }
}
if ((dirp = opendir(src)) == NULL) {
@@ -1823,6 +1884,8 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
while (((dp = readdir(dirp)) != NULL) && !interrupted) {
if (dp->d_ino == 0)
continue;
+ free(new_dst);
+ free(new_src);
filename = dp->d_name;
new_dst = path_append(dst, filename);
new_src = path_append(src, filename);
@@ -1849,9 +1912,9 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
}
} else
logit("%s: not a regular file\n", filename);
- free(new_dst);
- free(new_src);
}
+ free(new_dst);
+ free(new_src);
do_setstat(conn, dst, &a);
diff --git a/sftp-client.h b/sftp-client.h
index 507d763e..63a9b8b1 100644
--- a/sftp-client.h
+++ b/sftp-client.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-client.h,v 1.26 2015/01/14 13:54:13 djm Exp $ */
+/* $OpenBSD: sftp-client.h,v 1.28 2019/01/16 23:23:45 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
@@ -21,6 +21,12 @@
#ifndef _SFTP_CLIENT_H
#define _SFTP_CLIENT_H
+#ifdef USE_SYSTEM_GLOB
+# include <glob.h>
+#else
+# include "openbsd-compat/glob.h"
+#endif
+
typedef struct SFTP_DIRENT SFTP_DIRENT;
struct SFTP_DIRENT {
@@ -85,6 +91,9 @@ int do_setstat(struct sftp_conn *, const char *, Attrib *);
/* Set file attributes of open file 'handle' */
int do_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *);
+/* Set file attributes of 'path', not following symlinks */
+int do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a);
+
/* Canonicalise 'path' - caller must free result */
char *do_realpath(struct sftp_conn *, const char *);
@@ -111,7 +120,7 @@ int do_download(struct sftp_conn *, const char *, const char *,
Attrib *, int, int, int);
/*
- * Recursively download 'remote_directory' to 'local_directory'. Preserve
+ * Recursively download 'remote_directory' to 'local_directory'. Preserve
* times if 'pflag' is set
*/
int download_dir(struct sftp_conn *, const char *, const char *,
@@ -124,7 +133,7 @@ int download_dir(struct sftp_conn *, const char *, const char *,
int do_upload(struct sftp_conn *, const char *, const char *, int, int, int);
/*
- * Recursively upload 'local_directory' to 'remote_directory'. Preserve
+ * Recursively upload 'local_directory' to 'remote_directory'. Preserve
* times if 'pflag' is set
*/
int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int,
diff --git a/sftp-common.c b/sftp-common.c
index 9dc1f983..677f27d6 100644
--- a/sftp-common.c
+++ b/sftp-common.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-common.c,v 1.28 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: sftp-common.c,v 1.31 2018/09/13 15:23:32 millert Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2001 Damien Miller. All rights reserved.
@@ -26,7 +26,6 @@
#include "includes.h"
-#include <sys/param.h> /* MAX */
#include <sys/types.h>
#include <sys/stat.h>
@@ -37,6 +36,7 @@
#include <string.h>
#include <time.h>
#include <stdarg.h>
+#include <unistd.h>
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
@@ -45,6 +45,7 @@
#include "ssherr.h"
#include "sshbuf.h"
#include "log.h"
+#include "misc.h"
#include "sftp.h"
#include "sftp-common.h"
@@ -215,23 +216,22 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units)
{
int ulen, glen, sz = 0;
struct tm *ltime = localtime(&st->st_mtime);
- char *user, *group;
- char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
+ const char *user, *group;
+ char buf[1024], lc[8], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
char sbuf[FMT_SCALED_STRSIZE];
time_t now;
strmode(st->st_mode, mode);
- if (!remote) {
- user = user_from_uid(st->st_uid, 0);
- } else {
+ if (remote) {
snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
user = ubuf;
- }
- if (!remote) {
- group = group_from_gid(st->st_gid, 0);
- } else {
snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
group = gbuf;
+ strlcpy(lc, "?", sizeof(lc));
+ } else {
+ user = user_from_uid(st->st_uid, 0);
+ group = group_from_gid(st->st_gid, 0);
+ snprintf(lc, sizeof(lc), "%u", (u_int)st->st_nlink);
}
if (ltime != NULL) {
now = time(NULL);
@@ -243,16 +243,16 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units)
}
if (sz == 0)
tbuf[0] = '\0';
- ulen = MAX(strlen(user), 8);
- glen = MAX(strlen(group), 8);
+ ulen = MAXIMUM(strlen(user), 8);
+ glen = MAXIMUM(strlen(group), 8);
if (si_units) {
fmt_scaled((long long)st->st_size, sbuf);
- snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8s %s %s", mode,
- (u_int)st->st_nlink, ulen, user, glen, group,
+ snprintf(buf, sizeof buf, "%s %3s %-*s %-*s %8s %s %s",
+ mode, lc, ulen, user, glen, group,
sbuf, tbuf, name);
} else {
- snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8llu %s %s", mode,
- (u_int)st->st_nlink, ulen, user, glen, group,
+ snprintf(buf, sizeof buf, "%s %3s %-*s %-*s %8llu %s %s",
+ mode, lc, ulen, user, glen, group,
(unsigned long long)st->st_size, tbuf, name);
}
return xstrdup(buf);
diff --git a/sftp-glob.c b/sftp-glob.c
index 43a1beba..f573f98f 100644
--- a/sftp-glob.c
+++ b/sftp-glob.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-glob.c,v 1.27 2015/01/14 13:54:13 djm Exp $ */
+/* $OpenBSD: sftp-glob.c,v 1.29 2019/11/13 04:47:52 deraadt Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@@ -25,7 +25,7 @@
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
-#include <stdlib.h>
+#include <stdarg.h>
#include "xmalloc.h"
#include "sftp.h"
diff --git a/openbsd-compat/realpath.c b/sftp-realpath.c
index b6120d03..9ac40181 100644
--- a/openbsd-compat/realpath.c
+++ b/sftp-realpath.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: realpath.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
+/* $OpenBSD: sftp-realpath.c,v 1.1 2019/07/05 04:55:40 djm Exp $ */
/*
* Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
*
@@ -27,19 +27,26 @@
* SUCH DAMAGE.
*/
-/* OPENBSD ORIGINAL: lib/libc/stdlib/realpath.c */
-
#include "includes.h"
-#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH)
-
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
+#include <stddef.h>
#include <string.h>
#include <unistd.h>
+#include <limits.h>
+
+#ifndef SYMLOOP_MAX
+# define SYMLOOP_MAX 32
+#endif
+
+/* XXX rewrite sftp-server to use POSIX realpath and remove this hack */
+
+char *sftp_realpath(const char *path, char *resolved);
/*
* char *realpath(const char *path, char resolved[PATH_MAX]);
@@ -49,16 +56,30 @@
* in which case the path which caused trouble is left in (resolved).
*/
char *
-realpath(const char *path, char resolved[PATH_MAX])
+sftp_realpath(const char *path, char *resolved)
{
struct stat sb;
char *p, *q, *s;
size_t left_len, resolved_len;
unsigned symlinks;
- int serrno, slen;
+ int serrno, slen, mem_allocated;
char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
+ if (path[0] == '\0') {
+ errno = ENOENT;
+ return (NULL);
+ }
+
serrno = errno;
+
+ if (resolved == NULL) {
+ resolved = malloc(PATH_MAX);
+ if (resolved == NULL)
+ return (NULL);
+ mem_allocated = 1;
+ } else
+ mem_allocated = 0;
+
symlinks = 0;
if (path[0] == '/') {
resolved[0] = '/';
@@ -69,7 +90,10 @@ realpath(const char *path, char resolved[PATH_MAX])
left_len = strlcpy(left, path + 1, sizeof(left));
} else {
if (getcwd(resolved, PATH_MAX) == NULL) {
- strlcpy(resolved, ".", PATH_MAX);
+ if (mem_allocated)
+ free(resolved);
+ else
+ strlcpy(resolved, ".", PATH_MAX);
return (NULL);
}
resolved_len = strlen(resolved);
@@ -77,7 +101,7 @@ realpath(const char *path, char resolved[PATH_MAX])
}
if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto err;
}
/*
@@ -90,9 +114,9 @@ realpath(const char *path, char resolved[PATH_MAX])
*/
p = strchr(left, '/');
s = p ? p : left + left_len;
- if (s - left >= sizeof(next_token)) {
+ if (s - left >= (ptrdiff_t)sizeof(next_token)) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto err;
}
memcpy(next_token, left, s - left);
next_token[s - left] = '\0';
@@ -102,7 +126,7 @@ realpath(const char *path, char resolved[PATH_MAX])
if (resolved[resolved_len - 1] != '/') {
if (resolved_len + 1 >= PATH_MAX) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto err;
}
resolved[resolved_len++] = '/';
resolved[resolved_len] = '\0';
@@ -133,23 +157,23 @@ realpath(const char *path, char resolved[PATH_MAX])
resolved_len = strlcat(resolved, next_token, PATH_MAX);
if (resolved_len >= PATH_MAX) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto err;
}
if (lstat(resolved, &sb) != 0) {
if (errno == ENOENT && p == NULL) {
errno = serrno;
return (resolved);
}
- return (NULL);
+ goto err;
}
if (S_ISLNK(sb.st_mode)) {
- if (symlinks++ > MAXSYMLINKS) {
+ if (symlinks++ > SYMLOOP_MAX) {
errno = ELOOP;
- return (NULL);
+ goto err;
}
slen = readlink(resolved, symlink, sizeof(symlink) - 1);
if (slen < 0)
- return (NULL);
+ goto err;
symlink[slen] = '\0';
if (symlink[0] == '/') {
resolved[1] = 0;
@@ -169,17 +193,18 @@ realpath(const char *path, char resolved[PATH_MAX])
*/
if (p != NULL) {
if (symlink[slen - 1] != '/') {
- if (slen + 1 >= sizeof(symlink)) {
+ if (slen + 1 >=
+ (ptrdiff_t)sizeof(symlink)) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto err;
}
symlink[slen] = '/';
symlink[slen + 1] = 0;
}
- left_len = strlcat(symlink, left, sizeof(left));
- if (left_len >= sizeof(left)) {
+ left_len = strlcat(symlink, left, sizeof(symlink));
+ if (left_len >= sizeof(symlink)) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto err;
}
}
left_len = strlcpy(left, symlink, sizeof(left));
@@ -193,5 +218,9 @@ realpath(const char *path, char resolved[PATH_MAX])
if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
resolved[resolved_len - 1] = '\0';
return (resolved);
+
+err:
+ if (mem_allocated)
+ free(resolved);
+ return (NULL);
}
-#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */
diff --git a/sftp-server-main.c b/sftp-server-main.c
index 7e644ab8..06566d36 100644
--- a/sftp-server-main.c
+++ b/sftp-server-main.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-server-main.c,v 1.4 2009/02/21 19:32:04 tobias Exp $ */
+/* $OpenBSD: sftp-server-main.c,v 1.6 2019/06/06 05:13:13 otto Exp $ */
/*
* Copyright (c) 2008 Markus Friedl. All rights reserved.
*
@@ -26,6 +26,7 @@
#include "log.h"
#include "sftp.h"
#include "misc.h"
+#include "xmalloc.h"
void
cleanup_exit(int i)
@@ -41,6 +42,8 @@ main(int argc, char **argv)
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
+ seed_rng();
+
if ((user_pw = getpwuid(getuid())) == NULL) {
fprintf(stderr, "No user found for uid %lu\n",
(u_long)getuid());
diff --git a/sftp-server.0 b/sftp-server.0
deleted file mode 100644
index 77b6bb50..00000000
--- a/sftp-server.0
+++ /dev/null
@@ -1,96 +0,0 @@
-SFTP-SERVER(8) System Manager's Manual SFTP-SERVER(8)
-
-NAME
- sftp-server M-bM-^@M-^S SFTP server subsystem
-
-SYNOPSIS
- sftp-server [-ehR] [-d start_directory] [-f log_facility] [-l log_level]
- [-P blacklisted_requests] [-p whitelisted_requests]
- [-u umask]
- sftp-server -Q protocol_feature
-
-DESCRIPTION
- sftp-server is a program that speaks the server side of SFTP protocol to
- stdout and expects client requests from stdin. sftp-server is not
- intended to be called directly, but from sshd(8) using the Subsystem
- option.
-
- Command-line flags to sftp-server should be specified in the Subsystem
- declaration. See sshd_config(5) for more information.
-
- Valid options are:
-
- -d start_directory
- specifies an alternate starting directory for users. The
- pathname may contain the following tokens that are expanded at
- runtime: %% is replaced by a literal '%', %d is replaced by the
- home directory of the user being authenticated, and %u is
- replaced by the username of that user. The default is to use the
- user's home directory. This option is useful in conjunction with
- the sshd_config(5) ChrootDirectory option.
-
- -e Causes sftp-server to print logging information to stderr instead
- of syslog for debugging.
-
- -f log_facility
- Specifies the facility code that is used when logging messages
- from sftp-server. The possible values are: DAEMON, USER, AUTH,
- LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
- The default is AUTH.
-
- -h Displays sftp-server usage information.
-
- -l log_level
- Specifies which messages will be logged by sftp-server. The
- possible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG,
- DEBUG1, DEBUG2, and DEBUG3. INFO and VERBOSE log transactions
- that sftp-server performs on behalf of the client. DEBUG and
- DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher
- levels of debugging output. The default is ERROR.
-
- -P blacklisted_requests
- Specify a comma-separated list of SFTP protocol requests that are
- banned by the server. sftp-server will reply to any blacklisted
- request with a failure. The -Q flag can be used to determine the
- supported request types. If both a blacklist and a whitelist are
- specified, then the blacklist is applied before the whitelist.
-
- -p whitelisted_requests
- Specify a comma-separated list of SFTP protocol requests that are
- permitted by the server. All request types that are not on the
- whitelist will be logged and replied to with a failure message.
-
- Care must be taken when using this feature to ensure that
- requests made implicitly by SFTP clients are permitted.
-
- -Q protocol_feature
- Query protocol features supported by sftp-server. At present the
- only feature that may be queried is M-bM-^@M-^\requestsM-bM-^@M-^], which may be used
- for black or whitelisting (flags -P and -p respectively).
-
- -R Places this instance of sftp-server into a read-only mode.
- Attempts to open files for writing, as well as other operations
- that change the state of the filesystem, will be denied.
-
- -u umask
- Sets an explicit umask(2) to be applied to newly-created files
- and directories, instead of the user's default mask.
-
- On some systems, sftp-server must be able to access /dev/log for logging
- to work, and use of sftp-server in a chroot configuration therefore
- requires that syslogd(8) establish a logging socket inside the chroot
- directory.
-
-SEE ALSO
- sftp(1), ssh(1), sshd_config(5), sshd(8)
-
- T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh-
- filexfer-02.txt, October 2001, work in progress material.
-
-HISTORY
- sftp-server first appeared in OpenBSD 2.8.
-
-AUTHORS
- Markus Friedl <markus@openbsd.org>
-
-OpenBSD 5.7 December 11, 2014 OpenBSD 5.7
diff --git a/sftp-server.8 b/sftp-server.8
index c117398e..4a55dab2 100644
--- a/sftp-server.8
+++ b/sftp-server.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sftp-server.8,v 1.27 2014/12/11 04:16:14 djm Exp $
+.\" $OpenBSD: sftp-server.8,v 1.28 2019/11/30 07:07:59 jmc Exp $
.\"
.\" Copyright (c) 2000 Markus Friedl. All rights reserved.
.\"
@@ -22,12 +22,12 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: December 11 2014 $
+.Dd $Mdocdate: November 30 2019 $
.Dt SFTP-SERVER 8
.Os
.Sh NAME
.Nm sftp-server
-.Nd SFTP server subsystem
+.Nd OpenSSH SFTP server subsystem
.Sh SYNOPSIS
.Nm sftp-server
.Bk -words
diff --git a/sftp-server.c b/sftp-server.c
index 4f735cd9..359204fa 100644
--- a/sftp-server.c
+++ b/sftp-server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-server.c,v 1.105 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: sftp-server.c,v 1.117 2019/07/05 04:55:40 djm Exp $ */
/*
* Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
*
@@ -17,7 +17,6 @@
#include "includes.h"
-#include <sys/param.h> /* MIN */
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_TIME_H
@@ -29,9 +28,6 @@
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#endif
#include <dirent.h>
#include <errno.h>
@@ -40,7 +36,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include <pwd.h>
#include <time.h>
#include <unistd.h>
#include <stdarg.h>
@@ -56,6 +51,8 @@
#include "sftp.h"
#include "sftp-common.h"
+char *sftp_realpath(const char *, char *); /* sftp-realpath.c */
+
/* Our verbosity */
static LogLevel log_level = SYSLOG_LEVEL_ERROR;
@@ -112,6 +109,7 @@ static void process_extended_statvfs(u_int32_t id);
static void process_extended_fstatvfs(u_int32_t id);
static void process_extended_hardlink(u_int32_t id);
static void process_extended_fsync(u_int32_t id);
+static void process_extended_lsetstat(u_int32_t id);
static void process_extended(u_int32_t id);
struct sftp_handler {
@@ -122,7 +120,7 @@ struct sftp_handler {
int does_write; /* if nonzero, banned for readonly mode */
};
-struct sftp_handler handlers[] = {
+static const struct sftp_handler handlers[] = {
/* NB. SSH2_FXP_OPEN does the readonly check in the handler itself */
{ "open", NULL, SSH2_FXP_OPEN, process_open, 0 },
{ "close", NULL, SSH2_FXP_CLOSE, process_close, 0 },
@@ -146,18 +144,19 @@ struct sftp_handler handlers[] = {
};
/* SSH2_FXP_EXTENDED submessages */
-struct sftp_handler extended_handlers[] = {
+static const struct sftp_handler extended_handlers[] = {
{ "posix-rename", "posix-rename@openssh.com", 0,
process_extended_posix_rename, 1 },
{ "statvfs", "statvfs@openssh.com", 0, process_extended_statvfs, 0 },
{ "fstatvfs", "fstatvfs@openssh.com", 0, process_extended_fstatvfs, 0 },
{ "hardlink", "hardlink@openssh.com", 0, process_extended_hardlink, 1 },
{ "fsync", "fsync@openssh.com", 0, process_extended_fsync, 1 },
+ { "lsetstat", "lsetstat@openssh.com", 0, process_extended_lsetstat, 1 },
{ NULL, NULL, 0, NULL, 0 }
};
static int
-request_permitted(struct sftp_handler *h)
+request_permitted(const struct sftp_handler *h)
{
char *result;
@@ -290,9 +289,9 @@ enum {
HANDLE_FILE
};
-Handle *handles = NULL;
-u_int num_handles = 0;
-int first_unused_handle = -1;
+static Handle *handles = NULL;
+static u_int num_handles = 0;
+static int first_unused_handle = -1;
static void handle_unused(int i)
{
@@ -310,7 +309,7 @@ handle_new(int use, const char *name, int fd, int flags, DIR *dirp)
if (num_handles + 1 <= num_handles)
return -1;
num_handles++;
- handles = xrealloc(handles, num_handles, sizeof(Handle));
+ handles = xreallocarray(handles, num_handles, sizeof(Handle));
handle_unused(num_handles - 1);
}
@@ -509,7 +508,7 @@ status_to_message(u_int32_t status)
"Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */
"Unknown error" /* Others */
};
- return (status_messages[MIN(status,SSH2_FX_MAX)]);
+ return (status_messages[MINIMUM(status,SSH2_FX_MAX)]);
}
static void
@@ -671,6 +670,8 @@ process_init(void)
(r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
/* fsync extension */
(r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
+ (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
+ (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
(r = sshbuf_put_cstring(msg, "1")) != 0) /* version */
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(msg);
@@ -696,13 +697,13 @@ process_open(u_int32_t id)
logit("open \"%s\" flags %s mode 0%o",
name, string_from_portable(pflags), mode);
if (readonly &&
- ((flags & O_ACCMODE) == O_WRONLY ||
- (flags & O_ACCMODE) == O_RDWR)) {
+ ((flags & O_ACCMODE) != O_RDONLY ||
+ (flags & (O_CREAT|O_TRUNC)) != 0)) {
verbose("Refusing open request in read-only mode");
status = SSH2_FX_PERMISSION_DENIED;
} else {
fd = open(name, flags, mode);
- if (fd < 0) {
+ if (fd == -1) {
status = errno_to_portable(errno);
} else {
handle = handle_new(HANDLE_FILE, name, fd, flags, NULL);
@@ -755,12 +756,12 @@ process_read(u_int32_t id)
}
fd = handle_to_fd(handle);
if (fd >= 0) {
- if (lseek(fd, off, SEEK_SET) < 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 < 0) {
+ if (ret == -1) {
status = errno_to_portable(errno);
} else if (ret == 0) {
status = SSH2_FX_EOF;
@@ -796,13 +797,13 @@ process_write(u_int32_t id)
status = SSH2_FX_FAILURE;
else {
if (!(handle_to_flags(handle) & O_APPEND) &&
- lseek(fd, off, SEEK_SET) < 0) {
+ lseek(fd, off, SEEK_SET) == -1) {
status = errno_to_portable(errno);
error("process_write: seek failed");
} else {
/* XXX ATOMICIO ? */
ret = write(fd, data, len);
- if (ret < 0) {
+ if (ret == -1) {
error("process_write: write failed");
status = errno_to_portable(errno);
} else if ((size_t)ret == len) {
@@ -832,7 +833,7 @@ process_do_stat(u_int32_t id, int do_lstat)
debug3("request %u: %sstat", id, do_lstat ? "l" : "");
verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
r = do_lstat ? lstat(name, &st) : stat(name, &st);
- if (r < 0) {
+ if (r == -1) {
status = errno_to_portable(errno);
} else {
stat_to_attrib(&st, &a);
@@ -870,7 +871,7 @@ process_fstat(u_int32_t id)
fd = handle_to_fd(handle);
if (fd >= 0) {
r = fstat(fd, &st);
- if (r < 0) {
+ if (r == -1) {
status = errno_to_portable(errno);
} else {
stat_to_attrib(&st, &a);
@@ -894,6 +895,18 @@ attrib_to_tv(const Attrib *a)
return tv;
}
+static struct timespec *
+attrib_to_ts(const Attrib *a)
+{
+ static struct timespec ts[2];
+
+ ts[0].tv_sec = a->atime;
+ ts[0].tv_nsec = 0;
+ ts[1].tv_sec = a->mtime;
+ ts[1].tv_nsec = 0;
+ return ts;
+}
+
static void
process_setstat(u_int32_t id)
{
@@ -1063,12 +1076,12 @@ process_readdir(u_int32_t id)
while ((dp = readdir(dirp)) != NULL) {
if (count >= nstats) {
nstats *= 2;
- stats = xrealloc(stats, nstats, sizeof(Stat));
+ stats = xreallocarray(stats, nstats, sizeof(Stat));
}
/* XXX OVERFLOW ? */
snprintf(pathname, sizeof pathname, "%s%s%s", path,
strcmp(path, "/") ? "/" : "", dp->d_name);
- if (lstat(pathname, &st) < 0)
+ if (lstat(pathname, &st) == -1)
continue;
stat_to_attrib(&st, &(stats[count].attrib));
stats[count].name = xstrdup(dp->d_name);
@@ -1163,7 +1176,7 @@ process_realpath(u_int32_t id)
}
debug3("request %u: realpath", id);
verbose("realpath \"%s\"", path);
- if (realpath(path, resolvedname) == NULL) {
+ if (sftp_realpath(path, resolvedname) == NULL) {
send_status(id, errno_to_portable(errno));
} else {
Stat s;
@@ -1375,6 +1388,55 @@ process_extended_fsync(u_int32_t id)
}
static void
+process_extended_lsetstat(u_int32_t id)
+{
+ Attrib a;
+ char *name;
+ int r, status = SSH2_FX_OK;
+
+ if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
+ (r = decode_attrib(iqueue, &a)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
+ debug("request %u: lsetstat name \"%s\"", id, name);
+ if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
+ /* nonsensical for links */
+ status = SSH2_FX_BAD_MESSAGE;
+ goto out;
+ }
+ if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
+ logit("set \"%s\" mode %04o", name, a.perm);
+ r = fchmodat(AT_FDCWD, name,
+ a.perm & 07777, AT_SYMLINK_NOFOLLOW);
+ if (r == -1)
+ status = errno_to_portable(errno);
+ }
+ if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
+ char buf[64];
+ time_t t = a.mtime;
+
+ strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
+ localtime(&t));
+ logit("set \"%s\" modtime %s", name, buf);
+ r = utimensat(AT_FDCWD, name,
+ attrib_to_ts(&a), AT_SYMLINK_NOFOLLOW);
+ if (r == -1)
+ status = errno_to_portable(errno);
+ }
+ if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
+ logit("set \"%s\" owner %lu group %lu", name,
+ (u_long)a.uid, (u_long)a.gid);
+ r = fchownat(AT_FDCWD, name, a.uid, a.gid,
+ AT_SYMLINK_NOFOLLOW);
+ if (r == -1)
+ status = errno_to_portable(errno);
+ }
+ out:
+ send_status(id, status);
+ free(name);
+}
+
+static void
process_extended(u_int32_t id)
{
char *request;
@@ -1508,7 +1570,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0;
ssize_t len, olen, set_size;
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
- char *cp, *homedir = NULL, buf[4*4096];
+ char *cp, *homedir = NULL, uidstr[32], buf[4*4096];
long mask;
extern char *optarg;
@@ -1558,8 +1620,10 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
break;
case 'd':
cp = tilde_expand_filename(optarg, user_pw->pw_uid);
+ snprintf(uidstr, sizeof(uidstr), "%llu",
+ (unsigned long long)pw->pw_uid);
homedir = percent_expand(cp, "d", user_pw->pw_dir,
- "u", user_pw->pw_name, (char *)NULL);
+ "u", user_pw->pw_name, "U", uidstr, (char *)NULL);
free(cp);
break;
case 'p':
@@ -1588,16 +1652,16 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
log_init(__progname, log_level, log_facility, log_stderr);
-#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
/*
- * On Linux, we should try to avoid making /proc/self/{mem,maps}
+ * On platforms where we can, avoid making /proc/self/{mem,maps}
* available to the user so that sftp access doesn't automatically
* imply arbitrary code execution access that will break
* restricted configurations.
*/
- if (prctl(PR_SET_DUMPABLE, 0) != 0)
- fatal("unable to make the process undumpable");
-#endif /* defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) */
+ platform_disable_tracing(1); /* strict */
+
+ /* Drop any fine-grained privileges we don't need */
+ platform_pledge_sftp_server();
if ((cp = getenv("SSH_CONNECTION")) != NULL) {
client_addr = xstrdup(cp);
@@ -1632,9 +1696,8 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
if ((oqueue = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
- rset = (fd_set *)xmalloc(set_size);
- wset = (fd_set *)xmalloc(set_size);
+ rset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask));
+ wset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask));
if (homedir != NULL) {
if (chdir(homedir) != 0) {
@@ -1643,6 +1706,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
}
}
+ set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
for (;;) {
memset(rset, 0, set_size);
memset(wset, 0, set_size);
@@ -1664,7 +1728,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
if (olen > 0)
FD_SET(out, wset);
- if (select(max+1, rset, wset, NULL, NULL) < 0) {
+ if (select(max+1, rset, wset, NULL, NULL) == -1) {
if (errno == EINTR)
continue;
error("select: %s", strerror(errno));
@@ -1677,7 +1741,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
if (len == 0) {
debug("read eof");
sftp_server_cleanup_exit(0);
- } else if (len < 0) {
+ } else if (len == -1) {
error("read: %s", strerror(errno));
sftp_server_cleanup_exit(1);
} else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
@@ -1688,7 +1752,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
/* send oqueue to stdout */
if (FD_ISSET(out, wset)) {
len = write(out, sshbuf_ptr(oqueue), olen);
- if (len < 0) {
+ if (len == -1) {
error("write: %s", strerror(errno));
sftp_server_cleanup_exit(1);
} else if ((r = sshbuf_consume(oqueue, len)) != 0) {
diff --git a/sftp.0 b/sftp.0
deleted file mode 100644
index 24fd9916..00000000
--- a/sftp.0
+++ /dev/null
@@ -1,383 +0,0 @@
-SFTP(1) General Commands Manual SFTP(1)
-
-NAME
- sftp M-bM-^@M-^S secure file transfer program
-
-SYNOPSIS
- sftp [-1246aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]
- [-D sftp_server_path] [-F ssh_config] [-i identity_file] [-l limit]
- [-o ssh_option] [-P port] [-R num_requests] [-S program]
- [-s subsystem | sftp_server] host
- sftp [user@]host[:file ...]
- sftp [user@]host[:dir[/]]
- sftp -b batchfile [user@]host
-
-DESCRIPTION
- sftp is an interactive file transfer program, similar to ftp(1), which
- performs all operations over an encrypted ssh(1) transport. It may also
- use many features of ssh, such as public key authentication and
- compression. sftp connects and logs into the specified host, then enters
- an interactive command mode.
-
- The second usage format will retrieve files automatically if a non-
- interactive authentication method is used; otherwise it will do so after
- successful interactive authentication.
-
- The third usage format allows sftp to start in a remote directory.
-
- The final usage format allows for automated sessions using the -b option.
- In such cases, it is necessary to configure non-interactive
- authentication to obviate the need to enter a password at connection time
- (see sshd(8) and ssh-keygen(1) for details).
-
- Since some usage formats use colon characters to delimit host names from
- path names, IPv6 addresses must be enclosed in square brackets to avoid
- ambiguity.
-
- The options are as follows:
-
- -1 Specify the use of protocol version 1.
-
- -2 Specify the use of protocol version 2.
-
- -4 Forces sftp to use IPv4 addresses only.
-
- -6 Forces sftp to use IPv6 addresses only.
-
- -a Attempt to continue interrupted transfers rather than overwriting
- existing partial or complete copies of files. If the partial
- contents differ from those being transferred, then the resultant
- file is likely to be corrupt.
-
- -B buffer_size
- Specify the size of the buffer that sftp uses when transferring
- files. Larger buffers require fewer round trips at the cost of
- higher memory consumption. The default is 32768 bytes.
-
- -b batchfile
- Batch mode reads a series of commands from an input batchfile
- instead of stdin. Since it lacks user interaction it should be
- used in conjunction with non-interactive authentication. A
- batchfile of M-bM-^@M-^X-M-bM-^@M-^Y may be used to indicate standard input. sftp
- will abort if any of the following commands fail: get, put,
- reget, reput, rename, ln, rm, mkdir, chdir, ls, lchdir, chmod,
- chown, chgrp, lpwd, df, symlink, and lmkdir. Termination on
- error can be suppressed on a command by command basis by
- prefixing the command with a M-bM-^@M-^X-M-bM-^@M-^Y character (for example, -rm
- /tmp/blah*).
-
- -C Enables compression (via ssh's -C flag).
-
- -c cipher
- Selects the cipher to use for encrypting the data transfers.
- This option is directly passed to ssh(1).
-
- -D sftp_server_path
- Connect directly to a local sftp server (rather than via ssh(1)).
- This option may be useful in debugging the client and server.
-
- -F ssh_config
- Specifies an alternative per-user configuration file for ssh(1).
- This option is directly passed to ssh(1).
-
- -f Requests that files be flushed to disk immediately after
- transfer. When uploading files, this feature is only enabled if
- the server implements the "fsync@openssh.com" extension.
-
- -i identity_file
- Selects the file from which the identity (private key) for public
- key authentication is read. This option is directly passed to
- ssh(1).
-
- -l limit
- Limits the used bandwidth, specified in Kbit/s.
-
- -o ssh_option
- Can be used to pass options to ssh in the format used in
- ssh_config(5). This is useful for specifying options for which
- there is no separate sftp command-line flag. For example, to
- specify an alternate port use: sftp -oPort=24. For full details
- of the options listed below, and their possible values, see
- ssh_config(5).
-
- AddressFamily
- BatchMode
- BindAddress
- CanonicalDomains
- CanonicalizeFallbackLocal
- CanonicalizeHostname
- CanonicalizeMaxDots
- CanonicalizePermittedCNAMEs
- ChallengeResponseAuthentication
- CheckHostIP
- Cipher
- Ciphers
- Compression
- CompressionLevel
- ConnectionAttempts
- ConnectTimeout
- ControlMaster
- ControlPath
- ControlPersist
- GlobalKnownHostsFile
- GSSAPIAuthentication
- GSSAPIDelegateCredentials
- HashKnownHosts
- Host
- HostbasedAuthentication
- HostbasedKeyTypes
- HostKeyAlgorithms
- HostKeyAlias
- HostName
- IdentityFile
- IdentitiesOnly
- IPQoS
- KbdInteractiveAuthentication
- KbdInteractiveDevices
- KexAlgorithms
- LogLevel
- MACs
- NoHostAuthenticationForLocalhost
- NumberOfPasswordPrompts
- PasswordAuthentication
- PKCS11Provider
- Port
- PreferredAuthentications
- Protocol
- ProxyCommand
- PubkeyAuthentication
- RekeyLimit
- RhostsRSAAuthentication
- RSAAuthentication
- SendEnv
- ServerAliveInterval
- ServerAliveCountMax
- StrictHostKeyChecking
- TCPKeepAlive
- UpdateHostKeys
- UsePrivilegedPort
- User
- UserKnownHostsFile
- VerifyHostKeyDNS
-
- -P port
- Specifies the port to connect to on the remote host.
-
- -p Preserves modification times, access times, and modes from the
- original files transferred.
-
- -q Quiet mode: disables the progress meter as well as warning and
- diagnostic messages from ssh(1).
-
- -R num_requests
- Specify how many requests may be outstanding at any one time.
- Increasing this may slightly improve file transfer speed but will
- increase memory usage. The default is 64 outstanding requests.
-
- -r Recursively copy entire directories when uploading and
- downloading. Note that sftp does not follow symbolic links
- encountered in the tree traversal.
-
- -S program
- Name of the program to use for the encrypted connection. The
- program must understand ssh(1) options.
-
- -s subsystem | sftp_server
- Specifies the SSH2 subsystem or the path for an sftp server on
- the remote host. A path is useful for using sftp over protocol
- version 1, or when the remote sshd(8) does not have an sftp
- subsystem configured.
-
- -v Raise logging level. This option is also passed to ssh.
-
-INTERACTIVE COMMANDS
- Once in interactive mode, sftp understands a set of commands similar to
- those of ftp(1). Commands are case insensitive. Pathnames that contain
- spaces must be enclosed in quotes. Any special characters contained
- within pathnames that are recognized by glob(3) must be escaped with
- backslashes (M-bM-^@M-^X\M-bM-^@M-^Y).
-
- bye Quit sftp.
-
- cd path
- Change remote directory to path.
-
- chgrp grp path
- Change group of file path to grp. path may contain glob(3)
- characters and may match multiple files. grp must be a numeric
- GID.
-
- chmod mode path
- Change permissions of file path to mode. path may contain
- glob(3) characters and may match multiple files.
-
- chown own path
- Change owner of file path to own. path may contain glob(3)
- characters and may match multiple files. own must be a numeric
- UID.
-
- df [-hi] [path]
- Display usage information for the filesystem holding the current
- directory (or path if specified). If the -h flag is specified,
- the capacity information will be displayed using "human-readable"
- suffixes. The -i flag requests display of inode information in
- addition to capacity information. This command is only supported
- on servers that implement the M-bM-^@M-^\statvfs@openssh.comM-bM-^@M-^] extension.
-
- exit Quit sftp.
-
- get [-afPpr] remote-path [local-path]
- Retrieve the remote-path and store it on the local machine. If
- the local path name is not specified, it is given the same name
- it has on the remote machine. remote-path may contain glob(3)
- characters and may match multiple files. If it does and
- local-path is specified, then local-path must specify a
- directory.
-
- If the -a flag is specified, then attempt to resume partial
- transfers of existing files. Note that resumption assumes that
- any partial copy of the local file matches the remote copy. If
- the remote file contents differ from the partial local copy then
- the resultant file is likely to be corrupt.
-
- If the -f flag is specified, then fsync(2) will be called after
- the file transfer has completed to flush the file to disk.
-
- If either the -P or -p flag is specified, then full file
- permissions and access times are copied too.
-
- If the -r flag is specified then directories will be copied
- recursively. Note that sftp does not follow symbolic links when
- performing recursive transfers.
-
- help Display help text.
-
- lcd path
- Change local directory to path.
-
- lls [ls-options [path]]
- Display local directory listing of either path or current
- directory if path is not specified. ls-options may contain any
- flags supported by the local system's ls(1) command. path may
- contain glob(3) characters and may match multiple files.
-
- lmkdir path
- Create local directory specified by path.
-
- ln [-s] oldpath newpath
- Create a link from oldpath to newpath. If the -s flag is
- specified the created link is a symbolic link, otherwise it is a
- hard link.
-
- lpwd Print local working directory.
-
- ls [-1afhlnrSt] [path]
- Display a remote directory listing of either path or the current
- directory if path is not specified. path may contain glob(3)
- characters and may match multiple files.
-
- The following flags are recognized and alter the behaviour of ls
- accordingly:
-
- -1 Produce single columnar output.
-
- -a List files beginning with a dot (M-bM-^@M-^X.M-bM-^@M-^Y).
-
- -f Do not sort the listing. The default sort order is
- lexicographical.
-
- -h When used with a long format option, use unit suffixes:
- Byte, Kilobyte, Megabyte, Gigabyte, Terabyte, Petabyte,
- and Exabyte in order to reduce the number of digits to
- four or fewer using powers of 2 for sizes (K=1024,
- M=1048576, etc.).
-
- -l Display additional details including permissions and
- ownership information.
-
- -n Produce a long listing with user and group information
- presented numerically.
-
- -r Reverse the sort order of the listing.
-
- -S Sort the listing by file size.
-
- -t Sort the listing by last modification time.
-
- lumask umask
- Set local umask to umask.
-
- mkdir path
- Create remote directory specified by path.
-
- progress
- Toggle display of progress meter.
-
- put [-afPpr] local-path [remote-path]
- Upload local-path and store it on the remote machine. If the
- remote path name is not specified, it is given the same name it
- has on the local machine. local-path may contain glob(3)
- characters and may match multiple files. If it does and
- remote-path is specified, then remote-path must specify a
- directory.
-
- If the -a flag is specified, then attempt to resume partial
- transfers of existing files. Note that resumption assumes that
- any partial copy of the remote file matches the local copy. If
- the local file contents differ from the remote local copy then
- the resultant file is likely to be corrupt.
-
- If the -f flag is specified, then a request will be sent to the
- server to call fsync(2) after the file has been transferred.
- Note that this is only supported by servers that implement the
- "fsync@openssh.com" extension.
-
- If either the -P or -p flag is specified, then full file
- permissions and access times are copied too.
-
- If the -r flag is specified then directories will be copied
- recursively. Note that sftp does not follow symbolic links when
- performing recursive transfers.
-
- pwd Display remote working directory.
-
- quit Quit sftp.
-
- reget [-Ppr] remote-path [local-path]
- Resume download of remote-path. Equivalent to get with the -a
- flag set.
-
- reput [-Ppr] [local-path] remote-path
- Resume upload of [local-path]. Equivalent to put with the -a
- flag set.
-
- rename oldpath newpath
- Rename remote file from oldpath to newpath.
-
- rm path
- Delete remote file specified by path.
-
- rmdir path
- Remove remote directory specified by path.
-
- symlink oldpath newpath
- Create a symbolic link from oldpath to newpath.
-
- version
- Display the sftp protocol version.
-
- !command
- Execute command in local shell.
-
- ! Escape to local shell.
-
- ? Synonym for help.
-
-SEE ALSO
- ftp(1), ls(1), scp(1), ssh(1), ssh-add(1), ssh-keygen(1), glob(3),
- ssh_config(5), sftp-server(8), sshd(8)
-
- T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh-
- filexfer-00.txt, January 2001, work in progress material.
-
-OpenBSD 5.7 January 30, 2015 OpenBSD 5.7
diff --git a/sftp.1 b/sftp.1
index 214f0118..a305b37d 100644
--- a/sftp.1
+++ b/sftp.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sftp.1,v 1.101 2015/01/30 11:43:14 djm Exp $
+.\" $OpenBSD: sftp.1,v 1.131 2020/04/23 21:28:09 jmc Exp $
.\"
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
.\"
@@ -22,83 +22,80 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: January 30 2015 $
+.Dd $Mdocdate: April 23 2020 $
.Dt SFTP 1
.Os
.Sh NAME
.Nm sftp
-.Nd secure file transfer program
+.Nd OpenSSH secure file transfer
.Sh SYNOPSIS
.Nm sftp
-.Bk -words
-.Op Fl 1246aCfpqrv
+.Op Fl 46aCfNpqrv
.Op Fl B Ar buffer_size
.Op Fl b Ar batchfile
.Op Fl c Ar cipher
.Op Fl D Ar sftp_server_path
.Op Fl F Ar ssh_config
.Op Fl i Ar identity_file
+.Op Fl J Ar destination
.Op Fl l Ar limit
.Op Fl o Ar ssh_option
.Op Fl P Ar port
.Op Fl R Ar num_requests
.Op Fl S Ar program
.Op Fl s Ar subsystem | sftp_server
-.Ar host
-.Ek
-.Nm sftp
-.Oo Ar user Ns @ Oc Ns
-.Ar host Ns Op : Ns Ar
-.Nm sftp
-.Oo
-.Ar user Ns @ Oc Ns
-.Ar host Ns Oo : Ns Ar dir Ns
-.Op Ar /
-.Oc
-.Nm sftp
-.Fl b Ar batchfile
-.Oo Ar user Ns @ Oc Ns Ar host
+.Ar destination
.Sh DESCRIPTION
.Nm
-is an interactive file transfer program, similar to
+is a file transfer program, similar to
.Xr ftp 1 ,
which performs all operations over an encrypted
.Xr ssh 1
transport.
It may also use many features of ssh, such as public key authentication and
compression.
-.Nm
-connects and logs into the specified
-.Ar host ,
-then enters an interactive command mode.
.Pp
-The second usage format will retrieve files automatically if a non-interactive
+The
+.Ar destination
+may be specified either as
+.Sm off
+.Oo user @ Oc host Op : path
+.Sm on
+or as a URI in the form
+.Sm off
+.No sftp:// Oo user @ Oc host Oo : port Oc Op / path .
+.Sm on
+.Pp
+If the
+.Ar destination
+includes a
+.Ar path
+and it is not a directory,
+.Nm
+will retrieve files automatically if a non-interactive
authentication method is used; otherwise it will do so after
successful interactive authentication.
.Pp
-The third usage format allows
+If no
+.Ar path
+is specified, or if the
+.Ar path
+is a directory,
.Nm
-to start in a remote directory.
-.Pp
-The final usage format allows for automated sessions using the
-.Fl b
-option.
-In such cases, it is necessary to configure non-interactive authentication
-to obviate the need to enter a password at connection time (see
-.Xr sshd 8
-and
-.Xr ssh-keygen 1
-for details).
+will log in to the specified
+.Ar host
+and enter interactive command mode, changing to the remote directory
+if one was specified.
+An optional trailing slash can be used to force the
+.Ar path
+to be interpreted as a directory.
.Pp
-Since some usage formats use colon characters to delimit host names from path
-names, IPv6 addresses must be enclosed in square brackets to avoid ambiguity.
+Since the destination formats use colon characters to delimit host
+names from path names or port numbers, IPv6 addresses must be
+enclosed in square brackets to avoid ambiguity.
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl 1
-Specify the use of protocol version 1.
-.It Fl 2
-Specify the use of protocol version 2.
.It Fl 4
Forces
.Nm
@@ -125,7 +122,13 @@ Batch mode reads a series of commands from an input
instead of
.Em stdin .
Since it lacks user interaction it should be used in conjunction with
-non-interactive authentication.
+non-interactive authentication to obviate the need to enter a password
+at connection time (see
+.Xr sshd 8
+and
+.Xr ssh-keygen 1
+for details).
+.Pp
A
.Ar batchfile
of
@@ -134,17 +137,23 @@ may be used to indicate standard input.
.Nm
will abort if any of the following
commands fail:
-.Ic get , put , reget , reput, rename , ln ,
+.Ic get , put , reget , reput , rename , ln ,
.Ic rm , mkdir , chdir , ls ,
.Ic lchdir , chmod , chown ,
.Ic chgrp , lpwd , df , symlink ,
and
.Ic lmkdir .
+.Pp
Termination on error can be suppressed on a command by command basis by
prefixing the command with a
.Sq \-
character (for example,
.Ic -rm /tmp/blah* ) .
+Echo of the command may be suppressed by prefixing the command with a
+.Sq @
+character.
+These two prefixes may be combined in any order, for example
+.Ic -@ls /bsd .
.It Fl C
Enables compression (via ssh's
.Fl C
@@ -173,8 +182,25 @@ Selects the file from which the identity (private key) for public key
authentication is read.
This option is directly passed to
.Xr ssh 1 .
+.It Fl J Ar destination
+Connect to the target host by first making an
+.Nm
+connection to the jump host described by
+.Ar destination
+and then establishing a TCP forwarding to the ultimate destination from
+there.
+Multiple jump hops may be specified separated by comma characters.
+This is a shortcut to specify a
+.Cm ProxyJump
+configuration directive.
+This option is directly passed to
+.Xr ssh 1 .
.It Fl l Ar limit
Limits the used bandwidth, specified in Kbit/s.
+.It Fl N
+Disables quiet mode, e.g. to override the implicit quiet mode set by the
+.Fl b
+flag.
.It Fl o Ar ssh_option
Can be used to pass options to
.Nm ssh
@@ -193,17 +219,18 @@ For full details of the options listed below, and their possible values, see
.It AddressFamily
.It BatchMode
.It BindAddress
+.It BindInterface
.It CanonicalDomains
.It CanonicalizeFallbackLocal
.It CanonicalizeHostname
.It CanonicalizeMaxDots
.It CanonicalizePermittedCNAMEs
+.It CASignatureAlgorithms
+.It CertificateFile
.It ChallengeResponseAuthentication
.It CheckHostIP
-.It Cipher
.It Ciphers
.It Compression
-.It CompressionLevel
.It ConnectionAttempts
.It ConnectTimeout
.It ControlMaster
@@ -218,9 +245,10 @@ For full details of the options listed below, and their possible values, see
.It HostbasedKeyTypes
.It HostKeyAlgorithms
.It HostKeyAlias
-.It HostName
-.It IdentityFile
+.It Hostname
.It IdentitiesOnly
+.It IdentityAgent
+.It IdentityFile
.It IPQoS
.It KbdInteractiveAuthentication
.It KbdInteractiveDevices
@@ -233,19 +261,18 @@ For full details of the options listed below, and their possible values, see
.It PKCS11Provider
.It Port
.It PreferredAuthentications
-.It Protocol
.It ProxyCommand
+.It ProxyJump
+.It PubkeyAcceptedKeyTypes
.It PubkeyAuthentication
.It RekeyLimit
-.It RhostsRSAAuthentication
-.It RSAAuthentication
.It SendEnv
.It ServerAliveInterval
.It ServerAliveCountMax
+.It SetEnv
.It StrictHostKeyChecking
.It TCPKeepAlive
.It UpdateHostKeys
-.It UsePrivilegedPort
.It User
.It UserKnownHostsFile
.It VerifyHostKeyDNS
@@ -279,9 +306,7 @@ options.
.It Fl s Ar subsystem | sftp_server
Specifies the SSH2 subsystem or the path for an sftp server
on the remote host.
-A path is useful for using
-.Nm
-over protocol version 1, or when the remote
+A path is useful when the remote
.Xr sshd 8
does not have an sftp subsystem configured.
.It Fl v
@@ -303,37 +328,61 @@ must be escaped with backslashes
.It Ic bye
Quit
.Nm sftp .
-.It Ic cd Ar path
+.It Ic cd Op Ar path
Change remote directory to
.Ar path .
-.It Ic chgrp Ar grp Ar path
+If
+.Ar path
+is not specified, then change directory to the one the session started in.
+.It Xo Ic chgrp
+.Op Fl h
+.Ar grp
+.Ar path
+.Xc
Change group of file
.Ar path
to
.Ar grp .
+If the
+.Fl h
+flag is specified, then symlinks will not be followed.
.Ar path
may contain
-.Xr glob 3
+.Xr glob 7
characters and may match multiple files.
.Ar grp
must be a numeric GID.
-.It Ic chmod Ar mode Ar path
+.It Xo Ic chmod
+.Op Fl h
+.Ar mode
+.Ar path
+.Xc
Change permissions of file
.Ar path
to
.Ar mode .
+If the
+.Fl h
+flag is specified, then symlinks will not be followed.
.Ar path
may contain
-.Xr glob 3
+.Xr glob 7
characters and may match multiple files.
-.It Ic chown Ar own Ar path
+.It Xo Ic chown
+.Op Fl h
+.Ar own
+.Ar path
+.Xc
Change owner of file
.Ar path
to
.Ar own .
+If the
+.Fl h
+flag is specified, then symlinks will not be followed.
.Ar path
may contain
-.Xr glob 3
+.Xr glob 7
characters and may match multiple files.
.Ar own
must be a numeric UID.
@@ -359,7 +408,7 @@ extension.
Quit
.Nm sftp .
.It Xo Ic get
-.Op Fl afPpr
+.Op Fl afpR
.Ar remote-path
.Op Ar local-path
.Xc
@@ -371,7 +420,7 @@ path name is not specified, it is given the same name it has on the
remote machine.
.Ar remote-path
may contain
-.Xr glob 3
+.Xr glob 7
characters and may match multiple files.
If it does and
.Ar local-path
@@ -394,24 +443,31 @@ flag is specified, then
will be called after the file transfer has completed to flush the file
to disk.
.Pp
-If either the
-.Fl P
-or
+If the
.Fl p
+.\" undocumented redundant alias
+.\" or
+.\" .Fl P
flag is specified, then full file permissions and access times are
copied too.
.Pp
If the
-.Fl r
+.Fl R
+.\" undocumented redundant alias
+.\" or
+.\" .Fl r
flag is specified then directories will be copied recursively.
Note that
.Nm
does not follow symbolic links when performing recursive transfers.
.It Ic help
Display help text.
-.It Ic lcd Ar path
+.It Ic lcd Op Ar path
Change local directory to
.Ar path .
+If
+.Ar path
+is not specified, then change directory to the local user's home directory.
.It Ic lls Op Ar ls-options Op Ar path
Display local directory listing of either
.Ar path
@@ -424,7 +480,7 @@ may contain any flags supported by the local system's
command.
.Ar path
may contain
-.Xr glob 3
+.Xr glob 7
characters and may match multiple files.
.It Ic lmkdir Ar path
Create local directory specified by
@@ -455,7 +511,7 @@ or the current directory if
is not specified.
.Ar path
may contain
-.Xr glob 3
+.Xr glob 7
characters and may match multiple files.
.Pp
The following flags are recognized and alter the behaviour of
@@ -497,7 +553,7 @@ Create remote directory specified by
.It Ic progress
Toggle display of progress meter.
.It Xo Ic put
-.Op Fl afPpr
+.Op Fl afpR
.Ar local-path
.Op Ar remote-path
.Xc
@@ -508,7 +564,7 @@ If the remote path name is not specified, it is given the same name it has
on the local machine.
.Ar local-path
may contain
-.Xr glob 3
+.Xr glob 7
characters and may match multiple files.
If it does and
.Ar remote-path
@@ -533,15 +589,19 @@ after the file has been transferred.
Note that this is only supported by servers that implement
the "fsync@openssh.com" extension.
.Pp
-If either the
-.Fl P
-or
+If the
.Fl p
+.\" undocumented redundant alias
+.\" or
+.\" .Fl P
flag is specified, then full file permissions and access times are
copied too.
.Pp
If the
-.Fl r
+.Fl R
+.\" undocumented redundant alias
+.\" or
+.\" .Fl r
flag is specified then directories will be copied recursively.
Note that
.Nm
@@ -552,7 +612,7 @@ Display remote working directory.
Quit
.Nm sftp .
.It Xo Ic reget
-.Op Fl Ppr
+.Op Fl fpR
.Ar remote-path
.Op Ar local-path
.Xc
@@ -564,18 +624,18 @@ with the
.Fl a
flag set.
.It Xo Ic reput
-.Op Fl Ppr
-.Op Ar local-path
-.Ar remote-path
+.Op Fl fpR
+.Ar local-path
+.Op Ar remote-path
.Xc
Resume upload of
-.Op Ar local-path .
+.Ar local-path .
Equivalent to
.Ic put
with the
.Fl a
flag set.
-.It Ic rename Ar oldpath Ar newpath
+.It Ic rename Ar oldpath newpath
Rename remote file from
.Ar oldpath
to
@@ -586,7 +646,7 @@ Delete remote file specified by
.It Ic rmdir Ar path
Remove remote directory specified by
.Ar path .
-.It Ic symlink Ar oldpath Ar newpath
+.It Ic symlink Ar oldpath newpath
Create a symbolic link from
.Ar oldpath
to
@@ -611,8 +671,8 @@ Synonym for help.
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-keygen 1 ,
-.Xr glob 3 ,
.Xr ssh_config 5 ,
+.Xr glob 7 ,
.Xr sftp-server 8 ,
.Xr sshd 8
.Rs
diff --git a/sftp.c b/sftp.c
index cb9b967e..2799e4a1 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.170 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: sftp.c,v 1.200 2020/04/03 05:53:52 jmc Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@@ -17,7 +17,6 @@
#include "includes.h"
-#include <sys/param.h> /* MIN MAX */
#include <sys/types.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_STAT_H
@@ -49,11 +48,11 @@ typedef void EditLine;
#endif
#include <limits.h>
#include <signal.h>
+#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-#include <stdarg.h>
#ifdef HAVE_UTIL_H
# include <util.h>
@@ -63,6 +62,7 @@ typedef void EditLine;
#include "log.h"
#include "pathnames.h"
#include "misc.h"
+#include "utf8.h"
#include "sftp.h"
#include "ssherr.h"
@@ -80,7 +80,7 @@ FILE* infile;
int batchmode = 0;
/* PID of ssh transport process */
-static pid_t sshpid = -1;
+static volatile pid_t sshpid = -1;
/* Suppress diagnositic messages */
int quiet = 0;
@@ -105,6 +105,7 @@ volatile sig_atomic_t interrupted = 0;
/* I wish qsort() took a separate ctx for the comparison function...*/
int sort_flag;
+glob_t *sort_glob;
/* Context used for commandline completion */
struct complete_ctx {
@@ -215,15 +216,16 @@ static const struct CMD cmds[] = {
{ NULL, -1, -1 }
};
-int interactive_loop(struct sftp_conn *, char *file1, char *file2);
-
/* ARGSUSED */
static void
killchild(int signo)
{
- if (sshpid > 1) {
- kill(sshpid, SIGTERM);
- waitpid(sshpid, NULL, 0);
+ pid_t pid;
+
+ pid = sshpid;
+ if (pid > 1) {
+ kill(pid, SIGTERM);
+ waitpid(pid, NULL, 0);
}
_exit(1);
@@ -231,6 +233,18 @@ killchild(int signo)
/* ARGSUSED */
static void
+suspchild(int signo)
+{
+ if (sshpid > 1) {
+ kill(sshpid, signo);
+ while (waitpid(sshpid, NULL, WUNTRACED) == -1 && errno == EINTR)
+ continue;
+ }
+ kill(getpid(), SIGSTOP);
+}
+
+/* ARGSUSED */
+static void
cmd_interrupt(int signo)
{
const char msg[] = "\rInterrupt \n";
@@ -241,21 +255,38 @@ cmd_interrupt(int signo)
errno = olderrno;
}
+/*ARGSUSED*/
+static void
+sigchld_handler(int sig)
+{
+ int save_errno = errno;
+ pid_t pid;
+ const char msg[] = "\rConnection closed. \n";
+
+ /* Report if ssh transport process dies. */
+ while ((pid = waitpid(sshpid, NULL, WNOHANG)) == -1 && errno == EINTR)
+ continue;
+ if (pid == sshpid) {
+ (void)write(STDERR_FILENO, msg, sizeof(msg) - 1);
+ sshpid = -1;
+ }
+
+ errno = save_errno;
+}
+
static void
help(void)
{
printf("Available commands:\n"
"bye Quit sftp\n"
"cd path Change remote directory to 'path'\n"
- "chgrp grp path Change group of file 'path' to 'grp'\n"
- "chmod mode path Change permissions of file 'path' to 'mode'\n"
- "chown own path Change owner of file 'path' to 'own'\n"
+ "chgrp [-h] grp path Change group of file 'path' to 'grp'\n"
+ "chmod [-h] mode path Change permissions of file 'path' to 'mode'\n"
+ "chown [-h] own path Change owner of file 'path' to 'own'\n"
"df [-hi] [path] Display statistics for current directory or\n"
" filesystem containing 'path'\n"
"exit Quit sftp\n"
- "get [-afPpRr] remote [local] Download file\n"
- "reget [-fPpRr] remote [local] Resume download file\n"
- "reput [-fPpRr] [local] remote Resume upload file\n"
+ "get [-afpR] remote [local] Download file\n"
"help Display this help text\n"
"lcd path Change local directory to 'path'\n"
"lls [ls-options [path]] Display local directory listing\n"
@@ -266,10 +297,12 @@ help(void)
"lumask umask Set local umask to 'umask'\n"
"mkdir path Create remote directory\n"
"progress Toggle display of progress meter\n"
- "put [-afPpRr] local [remote] Upload file\n"
+ "put [-afpR] local [remote] Upload file\n"
"pwd Display remote working directory\n"
"quit Quit sftp\n"
+ "reget [-fpR] remote [local] Resume download file\n"
"rename oldpath newpath Rename remote file\n"
+ "reput [-fpR] local [remote] Resume upload file\n"
"rm path Delete remote file\n"
"rmdir path Remove remote directory\n"
"symlink oldpath newpath Symlink remote file\n"
@@ -335,7 +368,7 @@ local_do_ls(const char *args)
/* Strip one path (usually the pwd) from the start of another */
static char *
-path_strip(char *path, char *strip)
+path_strip(const char *path, const char *strip)
{
size_t len;
@@ -353,12 +386,12 @@ path_strip(char *path, char *strip)
}
static char *
-make_absolute(char *p, char *pwd)
+make_absolute(char *p, const char *pwd)
{
char *abs_str;
/* Derelativise */
- if (p && p[0] != '/') {
+ if (p && !path_absolute(p)) {
abs_str = path_append(pwd, p);
free(p);
return(abs_str);
@@ -531,6 +564,30 @@ parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag)
}
static int
+parse_ch_flags(const char *cmd, char **argv, int argc, int *hflag)
+{
+ extern int opterr, optind, optopt, optreset;
+ int ch;
+
+ optind = optreset = 1;
+ opterr = 0;
+
+ *hflag = 0;
+ while ((ch = getopt(argc, argv, "h")) != -1) {
+ switch (ch) {
+ case 'h':
+ *hflag = 1;
+ break;
+ default:
+ error("%s: Invalid flag -%c", cmd, optopt);
+ return -1;
+ }
+ }
+
+ return optind;
+}
+
+static int
parse_no_flags(const char *cmd, char **argv, int argc)
{
extern int opterr, optind, optopt, optreset;
@@ -551,7 +608,7 @@ parse_no_flags(const char *cmd, char **argv, int argc)
}
static int
-is_dir(char *path)
+is_dir(const char *path)
{
struct stat sb;
@@ -563,7 +620,7 @@ is_dir(char *path)
}
static int
-remote_is_dir(struct sftp_conn *conn, char *path)
+remote_is_dir(struct sftp_conn *conn, const char *path)
{
Attrib *a;
@@ -577,7 +634,7 @@ remote_is_dir(struct sftp_conn *conn, char *path)
/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
static int
-pathname_is_dir(char *pathname)
+pathname_is_dir(const char *pathname)
{
size_t l = strlen(pathname);
@@ -585,8 +642,8 @@ pathname_is_dir(char *pathname)
}
static int
-process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
- int pflag, int rflag, int resume, int fflag)
+process_get(struct sftp_conn *conn, const char *src, const char *dst,
+ const char *pwd, int pflag, int rflag, int resume, int fflag)
{
char *abs_src = NULL;
char *abs_dst = NULL;
@@ -644,9 +701,11 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
resume |= global_aflag;
if (!quiet && resume)
- printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst);
+ mprintf("Resuming %s to %s\n",
+ g.gl_pathv[i], abs_dst);
else if (!quiet && !resume)
- printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
+ mprintf("Fetching %s to %s\n",
+ g.gl_pathv[i], abs_dst);
if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
pflag || global_pflag, 1, resume,
@@ -669,8 +728,8 @@ out:
}
static int
-process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
- int pflag, int rflag, int resume, int fflag)
+process_put(struct sftp_conn *conn, const char *src, const char *dst,
+ const char *pwd, int pflag, int rflag, int resume, int fflag)
{
char *tmp_dst = NULL;
char *abs_dst = NULL;
@@ -735,10 +794,11 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
resume |= global_aflag;
if (!quiet && resume)
- printf("Resuming upload of %s to %s\n", g.gl_pathv[i],
- abs_dst);
+ mprintf("Resuming upload of %s to %s\n",
+ g.gl_pathv[i], abs_dst);
else if (!quiet && !resume)
- printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
+ mprintf("Uploading %s to %s\n",
+ g.gl_pathv[i], abs_dst);
if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (upload_dir(conn, g.gl_pathv[i], abs_dst,
pflag || global_pflag, 1, resume,
@@ -779,7 +839,8 @@ sdirent_comp(const void *aa, const void *bb)
/* sftp ls.1 replacement for directories */
static int
-do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
+do_ls_dir(struct sftp_conn *conn, const char *path,
+ const char *strip_path, int lflag)
{
int n;
u_int c = 1, colspace = 0, columns = 1;
@@ -796,7 +857,7 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
/* Count entries for sort and find longest filename */
for (n = 0; d[n] != NULL; n++) {
if (d[n]->filename[0] != '.' || (lflag & LS_SHOW_ALL))
- m = MAX(m, strlen(d[n]->filename));
+ m = MAXIMUM(m, strlen(d[n]->filename));
}
/* Add any subpath that also needs to be counted */
@@ -808,9 +869,9 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
width = ws.ws_col;
columns = width / (m + 2);
- columns = MAX(columns, 1);
+ columns = MAXIMUM(columns, 1);
colspace = width / columns;
- colspace = MIN(colspace, width);
+ colspace = MINIMUM(colspace, width);
}
if (lflag & SORT_FLAGS) {
@@ -839,12 +900,12 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
attrib_to_stat(&d[n]->a, &sb);
lname = ls_file(fname, &sb, 1,
(lflag & LS_SI_UNITS));
- printf("%s\n", lname);
+ mprintf("%s\n", lname);
free(lname);
} else
- printf("%s\n", d[n]->longname);
+ mprintf("%s\n", d[n]->longname);
} else {
- printf("%-*s", colspace, fname);
+ mprintf("%-*s", colspace, fname);
if (c >= columns) {
printf("\n");
c = 1;
@@ -862,16 +923,45 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
return (0);
}
+static int
+sglob_comp(const void *aa, const void *bb)
+{
+ u_int a = *(const u_int *)aa;
+ u_int b = *(const u_int *)bb;
+ const char *ap = sort_glob->gl_pathv[a];
+ const char *bp = sort_glob->gl_pathv[b];
+ const struct stat *as = sort_glob->gl_statv[a];
+ const struct stat *bs = sort_glob->gl_statv[b];
+ int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1;
+
+#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1))
+ if (sort_flag & LS_NAME_SORT)
+ return (rmul * strcmp(ap, bp));
+ else if (sort_flag & LS_TIME_SORT) {
+#if defined(HAVE_STRUCT_STAT_ST_MTIM)
+ return (rmul * timespeccmp(&as->st_mtim, &bs->st_mtim, <));
+#elif defined(HAVE_STRUCT_STAT_ST_MTIME)
+ return (rmul * NCMP(as->st_mtime, bs->st_mtime));
+#else
+ return rmul * 1;
+#endif
+ } else if (sort_flag & LS_SIZE_SORT)
+ return (rmul * NCMP(as->st_size, bs->st_size));
+
+ fatal("Unknown ls sort type");
+}
+
/* sftp ls.1 replacement which handles path globs */
static int
-do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
- int lflag)
+do_globbed_ls(struct sftp_conn *conn, const char *path,
+ const char *strip_path, int lflag)
{
char *fname, *lname;
glob_t g;
int err, r;
struct winsize ws;
- u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80;
+ u_int i, j, nentries, *indices = NULL, c = 1;
+ u_int colspace = 0, columns = 1, m = 0, width = 80;
memset(&g, 0, sizeof(g));
@@ -909,14 +999,33 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
if (!(lflag & LS_SHORT_VIEW)) {
/* Count entries for sort and find longest filename */
for (i = 0; g.gl_pathv[i]; i++)
- m = MAX(m, strlen(g.gl_pathv[i]));
+ m = MAXIMUM(m, strlen(g.gl_pathv[i]));
columns = width / (m + 2);
- columns = MAX(columns, 1);
+ columns = MAXIMUM(columns, 1);
colspace = width / columns;
}
- for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
+ /*
+ * Sorting: rather than mess with the contents of glob_t, prepare
+ * an array of indices into it and sort that. For the usual
+ * unsorted case, the indices are just the identity 1=1, 2=2, etc.
+ */
+ for (nentries = 0; g.gl_pathv[nentries] != NULL; nentries++)
+ ; /* count entries */
+ indices = calloc(nentries, sizeof(*indices));
+ for (i = 0; i < nentries; i++)
+ indices[i] = i;
+
+ if (lflag & SORT_FLAGS) {
+ sort_glob = &g;
+ sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT);
+ qsort(indices, nentries, sizeof(*indices), sglob_comp);
+ sort_glob = NULL;
+ }
+
+ for (j = 0; j < nentries && !interrupted; j++) {
+ i = indices[j];
fname = path_strip(g.gl_pathv[i], strip_path);
if (lflag & LS_LONG_VIEW) {
if (g.gl_statv[i] == NULL) {
@@ -925,10 +1034,10 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
}
lname = ls_file(fname, g.gl_statv[i], 1,
(lflag & LS_SI_UNITS));
- printf("%s\n", lname);
+ mprintf("%s\n", lname);
free(lname);
} else {
- printf("%-*s", colspace, fname);
+ mprintf("%-*s", colspace, fname);
if (c >= columns) {
printf("\n");
c = 1;
@@ -944,31 +1053,43 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
out:
if (g.gl_pathc)
globfree(&g);
+ free(indices);
return 0;
}
static int
-do_df(struct sftp_conn *conn, char *path, int hflag, int iflag)
+do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag)
{
struct sftp_statvfs st;
- char s_used[FMT_SCALED_STRSIZE];
- char s_avail[FMT_SCALED_STRSIZE];
- char s_root[FMT_SCALED_STRSIZE];
- char s_total[FMT_SCALED_STRSIZE];
- unsigned long long ffree;
+ char s_used[FMT_SCALED_STRSIZE], s_avail[FMT_SCALED_STRSIZE];
+ char s_root[FMT_SCALED_STRSIZE], s_total[FMT_SCALED_STRSIZE];
+ char s_icapacity[16], s_dcapacity[16];
if (do_statvfs(conn, path, &st, 1) == -1)
return -1;
+ if (st.f_files == 0)
+ strlcpy(s_icapacity, "ERR", sizeof(s_icapacity));
+ else {
+ snprintf(s_icapacity, sizeof(s_icapacity), "%3llu%%",
+ (unsigned long long)(100 * (st.f_files - st.f_ffree) /
+ st.f_files));
+ }
+ if (st.f_blocks == 0)
+ strlcpy(s_dcapacity, "ERR", sizeof(s_dcapacity));
+ else {
+ snprintf(s_dcapacity, sizeof(s_dcapacity), "%3llu%%",
+ (unsigned long long)(100 * (st.f_blocks - st.f_bfree) /
+ st.f_blocks));
+ }
if (iflag) {
- ffree = st.f_files ? (100 * (st.f_files - st.f_ffree) / st.f_files) : 0;
printf(" Inodes Used Avail "
"(root) %%Capacity\n");
- printf("%11llu %11llu %11llu %11llu %3llu%%\n",
+ printf("%11llu %11llu %11llu %11llu %s\n",
(unsigned long long)st.f_files,
(unsigned long long)(st.f_files - st.f_ffree),
(unsigned long long)st.f_favail,
- (unsigned long long)st.f_ffree, ffree);
+ (unsigned long long)st.f_ffree, s_icapacity);
} else if (hflag) {
strlcpy(s_used, "error", sizeof(s_used));
strlcpy(s_avail, "error", sizeof(s_avail));
@@ -979,21 +1100,18 @@ do_df(struct sftp_conn *conn, char *path, int hflag, int iflag)
fmt_scaled(st.f_bfree * st.f_frsize, s_root);
fmt_scaled(st.f_blocks * st.f_frsize, s_total);
printf(" Size Used Avail (root) %%Capacity\n");
- printf("%7sB %7sB %7sB %7sB %3llu%%\n",
- s_total, s_used, s_avail, s_root,
- (unsigned long long)(100 * (st.f_blocks - st.f_bfree) /
- st.f_blocks));
+ printf("%7sB %7sB %7sB %7sB %s\n",
+ s_total, s_used, s_avail, s_root, s_dcapacity);
} else {
printf(" Size Used Avail "
"(root) %%Capacity\n");
- printf("%12llu %12llu %12llu %12llu %3llu%%\n",
+ printf("%12llu %12llu %12llu %12llu %s\n",
(unsigned long long)(st.f_frsize * st.f_blocks / 1024),
(unsigned long long)(st.f_frsize *
(st.f_blocks - st.f_bfree) / 1024),
(unsigned long long)(st.f_frsize * st.f_bavail / 1024),
(unsigned long long)(st.f_frsize * st.f_bfree / 1024),
- (unsigned long long)(100 * (st.f_blocks - st.f_bfree) /
- st.f_blocks));
+ s_dcapacity);
}
return 0;
}
@@ -1204,8 +1322,8 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
}
static int
-parse_args(const char **cpp, int *ignore_errors, int *aflag,
- int *fflag, int *hflag, int *iflag, int *lflag, int *pflag,
+parse_args(const char **cpp, int *ignore_errors, int *disable_echo, int *aflag,
+ int *fflag, int *hflag, int *iflag, int *lflag, int *pflag,
int *rflag, int *sflag,
unsigned long *n_arg, char **path1, char **path2)
{
@@ -1213,18 +1331,28 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag,
char *cp2, **argv;
int base = 0;
long l;
- int i, cmdnum, optidx, argc;
+ int path1_mandatory = 0, i, cmdnum, optidx, argc;
/* Skip leading whitespace */
cp = cp + strspn(cp, WHITESPACE);
- /* Check for leading '-' (disable error processing) */
+ /*
+ * Check for leading '-' (disable error processing) and '@' (suppress
+ * command echo)
+ */
*ignore_errors = 0;
- if (*cp == '-') {
- *ignore_errors = 1;
- cp++;
- cp = cp + strspn(cp, WHITESPACE);
+ *disable_echo = 0;
+ for (;*cp != '\0'; cp++) {
+ if (*cp == '-') {
+ *ignore_errors = 1;
+ } else if (*cp == '@') {
+ *disable_echo = 1;
+ } else {
+ /* all other characters terminate prefix processing */
+ break;
+ }
}
+ cp = cp + strspn(cp, WHITESPACE);
/* Ignore blank lines and lines which begin with comment '#' char */
if (*cp == '\0' || *cp == '#')
@@ -1303,13 +1431,17 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag,
case I_RM:
case I_MKDIR:
case I_RMDIR:
+ case I_LMKDIR:
+ path1_mandatory = 1;
+ /* FALLTHROUGH */
case I_CHDIR:
case I_LCHDIR:
- case I_LMKDIR:
if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
return -1;
/* Get pathname (mandatory) */
if (argc - optidx < 1) {
+ if (!path1_mandatory)
+ break; /* return a NULL path1 */
error("You must specify a path after a %s command.",
cmd);
return -1;
@@ -1347,9 +1479,10 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag,
case I_LUMASK:
case I_CHMOD:
base = 8;
+ /* FALLTHROUGH */
case I_CHOWN:
case I_CHGRP:
- if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
+ if ((optidx = parse_ch_flags(cmd, argv, argc, hflag)) == -1)
return -1;
/* Get numeric arg (mandatory) */
if (argc - optidx < 1)
@@ -1394,11 +1527,12 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag,
static int
parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
- int err_abort)
+ const char *startdir, int err_abort, int echo_command)
{
+ const char *ocmd = cmd;
char *path1, *path2, *tmp;
- int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0,
- iflag = 0;
+ int ignore_errors = 0, disable_echo = 1;
+ int aflag = 0, fflag = 0, hflag = 0, iflag = 0;
int lflag = 0, pflag = 0, rflag = 0, sflag = 0;
int cmdnum, i;
unsigned long n_arg = 0;
@@ -1408,11 +1542,15 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
glob_t g;
path1 = path2 = NULL;
- cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag,
- &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, &path1, &path2);
+ cmdnum = parse_args(&cmd, &ignore_errors, &disable_echo, &aflag, &fflag,
+ &hflag, &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg,
+ &path1, &path2);
if (ignore_errors != 0)
err_abort = 0;
+ if (echo_command && !disable_echo)
+ mprintf("sftp> %s\n", ocmd);
+
memset(&g, 0, sizeof(g));
/* Perform command */
@@ -1445,6 +1583,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
break;
case I_SYMLINK:
sflag = 1;
+ /* FALLTHROUGH */
case I_LINK:
if (!sflag)
path1 = make_absolute(path1, *pwd);
@@ -1456,7 +1595,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
if (!quiet)
- printf("Removing %s\n", g.gl_pathv[i]);
+ mprintf("Removing %s\n", g.gl_pathv[i]);
err = do_rm(conn, g.gl_pathv[i]);
if (err != 0 && err_abort)
break;
@@ -1474,6 +1613,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
err = do_rmdir(conn, path1);
break;
case I_CHDIR:
+ if (path1 == NULL || *path1 == '\0')
+ path1 = xstrdup(startdir);
path1 = make_absolute(path1, *pwd);
if ((tmp = do_realpath(conn, path1)) == NULL) {
err = 1;
@@ -1508,7 +1649,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
/* Strip pwd off beginning of non-absolute paths */
tmp = NULL;
- if (*path1 != '/')
+ if (!path_absolute(path1))
tmp = *pwd;
path1 = make_absolute(path1, *pwd);
@@ -1522,6 +1663,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
err = do_df(conn, path1, hflag, iflag);
break;
case I_LCHDIR:
+ if (path1 == NULL || *path1 == '\0')
+ path1 = xstrdup("~");
tmp = tilde_expand_filename(path1, getuid());
free(path1);
path1 = tmp;
@@ -1556,8 +1699,10 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
if (!quiet)
- printf("Changing mode on %s\n", g.gl_pathv[i]);
- err = do_setstat(conn, g.gl_pathv[i], &a);
+ mprintf("Changing mode on %s\n",
+ g.gl_pathv[i]);
+ err = (hflag ? do_lsetstat : do_setstat)(conn,
+ g.gl_pathv[i], &a);
if (err != 0 && err_abort)
break;
}
@@ -1567,7 +1712,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
path1 = make_absolute(path1, *pwd);
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
- if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) {
+ if (!(aa = (hflag ? do_lstat : do_stat)(conn,
+ g.gl_pathv[i], 0))) {
if (err_abort) {
err = -1;
break;
@@ -1586,22 +1732,23 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
if (cmdnum == I_CHOWN) {
if (!quiet)
- printf("Changing owner on %s\n",
+ mprintf("Changing owner on %s\n",
g.gl_pathv[i]);
aa->uid = n_arg;
} else {
if (!quiet)
- printf("Changing group on %s\n",
+ mprintf("Changing group on %s\n",
g.gl_pathv[i]);
aa->gid = n_arg;
}
- err = do_setstat(conn, g.gl_pathv[i], aa);
+ err = (hflag ? do_lsetstat : do_setstat)(conn,
+ g.gl_pathv[i], aa);
if (err != 0 && err_abort)
break;
}
break;
case I_PWD:
- printf("Remote working directory: %s\n", *pwd);
+ mprintf("Remote working directory: %s\n", *pwd);
break;
case I_LPWD:
if (!getcwd(path_buf, sizeof(path_buf))) {
@@ -1609,7 +1756,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
err = -1;
break;
}
- printf("Local working directory: %s\n", path_buf);
+ mprintf("Local working directory: %s\n", path_buf);
break;
case I_QUIT:
/* Processed below */
@@ -1662,23 +1809,23 @@ complete_display(char **list, u_int len)
/* Count entries for sort and find longest */
for (y = 0; list[y]; y++)
- m = MAX(m, strlen(list[y]));
+ m = MAXIMUM(m, strlen(list[y]));
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
width = ws.ws_col;
m = m > len ? m - len : 0;
columns = width / (m + 2);
- columns = MAX(columns, 1);
+ columns = MAXIMUM(columns, 1);
colspace = width / columns;
- colspace = MIN(colspace, width);
+ colspace = MINIMUM(colspace, width);
printf("\n");
m = 1;
for (y = 0; list[y]; y++) {
llen = strlen(list[y]);
tmp = llen > len ? list[y] + len : "";
- printf("%-*s", colspace, tmp);
+ mprintf("%-*s", colspace, tmp);
if (m >= columns) {
printf("\n");
m = 1;
@@ -1762,7 +1909,7 @@ complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
return 0;
}
- /* Complete ambigious command */
+ /* Complete ambiguous command */
tmp = complete_ambiguous(cmd, list, count);
if (count > 1)
complete_display(list, 0);
@@ -1833,7 +1980,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
xasprintf(&tmp, "%s*", file);
/* Check if the path is absolute. */
- isabs = tmp[0] == '/';
+ isabs = path_absolute(tmp);
memset(&g, 0, sizeof(g));
if (remote != LOCAL) {
@@ -1958,7 +2105,7 @@ complete(EditLine *el, int ch)
/* Figure out which argument the cursor points to */
cursor = lf->cursor - lf->buffer;
- line = (char *)xmalloc(cursor + 1);
+ line = xmalloc(cursor + 1);
memcpy(line, lf->buffer, cursor);
line[cursor] = '\0';
argv = makeargv(line, &carg, 1, &quote, &terminated);
@@ -1966,7 +2113,7 @@ complete(EditLine *el, int ch)
/* Get all the arguments on the line */
len = lf->lastchar - lf->buffer;
- line = (char *)xmalloc(len + 1);
+ line = xmalloc(len + 1);
memcpy(line, lf->buffer, len);
line[len] = '\0';
argv = makeargv(line, &argc, 1, NULL, NULL);
@@ -2007,11 +2154,11 @@ complete(EditLine *el, int ch)
}
#endif /* USE_LIBEDIT */
-int
+static int
interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
{
char *remote_path;
- char *dir = NULL;
+ char *dir = NULL, *startdir = NULL;
char cmd[2048];
int err, interactive;
EditLine *el = NULL;
@@ -2044,7 +2191,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
el_set(el, EL_BIND, "^I", "ftp-complete", NULL);
/* enable ctrl-left-arrow and ctrl-right-arrow */
el_set(el, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
- el_set(el, EL_BIND, "\\e[5C", "em-next-word", NULL);
+ el_set(el, EL_BIND, "\\e\\e[C", "em-next-word", NULL);
el_set(el, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
el_set(el, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
/* make ^w match ksh behaviour */
@@ -2055,6 +2202,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
remote_path = do_realpath(conn, ".");
if (remote_path == NULL)
fatal("Need cwd");
+ startdir = xstrdup(remote_path);
if (file1 != NULL) {
dir = xstrdup(file1);
@@ -2062,11 +2210,12 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
if (remote_is_dir(conn, dir) && file2 == NULL) {
if (!quiet)
- printf("Changing to: %s\n", dir);
+ mprintf("Changing to: %s\n", dir);
snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
if (parse_dispatch_command(conn, cmd,
- &remote_path, 1) != 0) {
+ &remote_path, startdir, 1, 0) != 0) {
free(dir);
+ free(startdir);
free(remote_path);
free(conn);
return (-1);
@@ -2078,8 +2227,9 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
file2 == NULL ? "" : " ",
file2 == NULL ? "" : file2);
err = parse_dispatch_command(conn, cmd,
- &remote_path, 1);
+ &remote_path, startdir, 1, 0);
free(dir);
+ free(startdir);
free(remote_path);
free(conn);
return (err);
@@ -2093,9 +2243,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
interactive = !batchmode && isatty(STDIN_FILENO);
err = 0;
for (;;) {
- char *cp;
-
- signal(SIGINT, SIG_IGN);
+ ssh_signal(SIGINT, SIG_IGN);
if (el == NULL) {
if (interactive)
@@ -2105,12 +2253,6 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
printf("\n");
break;
}
- if (!interactive) { /* Echo command */
- printf("sftp> %s", cmd);
- if (strlen(cmd) > 0 &&
- cmd[strlen(cmd) - 1] != '\n')
- printf("\n");
- }
} else {
#ifdef USE_LIBEDIT
const char *line;
@@ -2129,20 +2271,20 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
#endif /* USE_LIBEDIT */
}
- cp = strrchr(cmd, '\n');
- if (cp)
- *cp = '\0';
+ cmd[strcspn(cmd, "\n")] = '\0';
/* Handle user interrupts gracefully during commands */
interrupted = 0;
- signal(SIGINT, cmd_interrupt);
+ ssh_signal(SIGINT, cmd_interrupt);
err = parse_dispatch_command(conn, cmd, &remote_path,
- batchmode);
+ startdir, batchmode, !interactive && el == NULL);
if (err != 0)
break;
}
+ ssh_signal(SIGCHLD, SIG_DFL);
free(remote_path);
+ free(startdir);
free(conn);
#ifdef USE_LIBEDIT
@@ -2197,16 +2339,20 @@ connect_to_server(char *path, char **args, int *in, int *out)
* kill it too. Contrawise, since sftp sends SIGTERMs to the
* underlying ssh, it must *not* ignore that signal.
*/
- signal(SIGINT, SIG_IGN);
- signal(SIGTERM, SIG_DFL);
+ ssh_signal(SIGINT, SIG_IGN);
+ ssh_signal(SIGTERM, SIG_DFL);
execvp(path, args);
fprintf(stderr, "exec: %s: %s\n", path, strerror(errno));
_exit(1);
}
- signal(SIGTERM, killchild);
- signal(SIGINT, killchild);
- signal(SIGHUP, killchild);
+ ssh_signal(SIGTERM, killchild);
+ ssh_signal(SIGINT, killchild);
+ ssh_signal(SIGHUP, killchild);
+ ssh_signal(SIGTSTP, suspchild);
+ ssh_signal(SIGTTIN, suspchild);
+ ssh_signal(SIGTTOU, suspchild);
+ ssh_signal(SIGCHLD, sigchld_handler);
close(c_in);
close(c_out);
}
@@ -2217,25 +2363,21 @@ usage(void)
extern char *__progname;
fprintf(stderr,
- "usage: %s [-1246aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
- " [-D sftp_server_path] [-F ssh_config] "
- "[-i identity_file] [-l limit]\n"
- " [-o ssh_option] [-P port] [-R num_requests] "
- "[-S program]\n"
- " [-s subsystem | sftp_server] host\n"
- " %s [user@]host[:file ...]\n"
- " %s [user@]host[:dir[/]]\n"
- " %s -b batchfile [user@]host\n",
- __progname, __progname, __progname, __progname);
+ "usage: %s [-46aCfNpqrv] [-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"
+ " destination\n",
+ __progname);
exit(1);
}
int
main(int argc, char **argv)
{
- int in, out, ch, err;
- char *host = NULL, *userhost, *cp, *file2 = NULL;
- int debug_level = 0, sshver = 2;
+ int in, out, ch, err, tmp, port = -1, noisy = 0;
+ char *host = NULL, *user, *cp, *file2 = NULL;
+ int debug_level = 0;
char *file1 = NULL, *sftp_server = NULL;
char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL;
const char *errstr;
@@ -2250,7 +2392,9 @@ main(int argc, char **argv)
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
- setlocale(LC_CTYPE, "");
+ msetlocale();
+
+ seed_rng();
__progname = ssh_get_progname(argv[0]);
memset(&args, '\0', sizeof(args));
@@ -2265,7 +2409,7 @@ main(int argc, char **argv)
infile = stdin;
while ((ch = getopt(argc, argv,
- "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
+ "1246afhNpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:")) != -1) {
switch (ch) {
/* Passed through to ssh(1) */
case '4':
@@ -2275,6 +2419,7 @@ main(int argc, char **argv)
break;
/* Passed through to ssh(1) with argument */
case 'F':
+ case 'J':
case 'c':
case 'i':
case 'o':
@@ -2288,7 +2433,9 @@ main(int argc, char **argv)
addargs(&args, "-%c", ch);
break;
case 'P':
- addargs(&args, "-oPort %s", optarg);
+ port = a2port(optarg);
+ if (port <= 0)
+ fatal("Bad port \"%s\"\n", optarg);
break;
case 'v':
if (debug_level < 3) {
@@ -2298,12 +2445,10 @@ main(int argc, char **argv)
debug_level++;
break;
case '1':
- sshver = 1;
- if (sftp_server == NULL)
- sftp_server = _PATH_SFTP_SERVER;
+ fatal("SSH protocol v.1 is no longer supported");
break;
case '2':
- sshver = 2;
+ /* accept silently */
break;
case 'a':
global_aflag = 1;
@@ -2328,6 +2473,9 @@ main(int argc, char **argv)
case 'f':
global_fflag = 1;
break;
+ case 'N':
+ noisy = 1; /* Used to clear quiet mode after getopt */
+ break;
case 'p':
global_pflag = 1;
break;
@@ -2366,39 +2514,51 @@ main(int argc, char **argv)
if (!isatty(STDERR_FILENO))
showprogress = 0;
+ if (noisy)
+ quiet = 0;
+
log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
if (sftp_direct == NULL) {
if (optind == argc || argc > (optind + 2))
usage();
+ argv += optind;
- userhost = xstrdup(argv[optind]);
- file2 = argv[optind+1];
-
- if ((host = strrchr(userhost, '@')) == NULL)
- host = userhost;
- else {
- *host++ = '\0';
- if (!userhost[0]) {
- fprintf(stderr, "Missing username\n");
- usage();
- }
- addargs(&args, "-l");
- addargs(&args, "%s", userhost);
- }
-
- if ((cp = colon(host)) != NULL) {
- *cp++ = '\0';
- file1 = cp;
+ switch (parse_uri("sftp", *argv, &user, &host, &tmp, &file1)) {
+ case -1:
+ usage();
+ break;
+ case 0:
+ if (tmp != -1)
+ port = tmp;
+ break;
+ default:
+ /* Try with user, host and path. */
+ if (parse_user_host_path(*argv, &user, &host,
+ &file1) == 0)
+ break;
+ /* Try with user and host. */
+ if (parse_user_host_port(*argv, &user, &host, NULL)
+ == 0)
+ break;
+ /* Treat as a plain hostname. */
+ host = xstrdup(*argv);
+ host = cleanhostname(host);
+ break;
}
+ file2 = *(argv + 1);
- host = cleanhostname(host);
if (!*host) {
fprintf(stderr, "Missing hostname\n");
usage();
}
- addargs(&args, "-oProtocol %d", sshver);
+ if (port != -1)
+ addargs(&args, "-oPort %d", port);
+ if (user != NULL) {
+ addargs(&args, "-l");
+ addargs(&args, "%s", user);
+ }
/* no subsystem if the server-spec contains a '/' */
if (sftp_server == NULL || strchr(sftp_server, '/') == NULL)
@@ -2441,7 +2601,7 @@ main(int argc, char **argv)
if (batchmode)
fclose(infile);
- while (waitpid(sshpid, NULL, 0) == -1)
+ while (waitpid(sshpid, NULL, 0) == -1 && sshpid > 1)
if (errno != EINTR)
fatal("Couldn't wait for ssh process: %s",
strerror(errno));
diff --git a/sk-api.h b/sk-api.h
new file mode 100644
index 00000000..1ecaa353
--- /dev/null
+++ b/sk-api.h
@@ -0,0 +1,95 @@
+/* $OpenBSD: sk-api.h,v 1.9 2020/04/28 04:02:29 djm Exp $ */
+/*
+ * Copyright (c) 2019 Google LLC
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SK_API_H
+#define _SK_API_H 1
+
+#include <stddef.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+/* Flags */
+#define SSH_SK_USER_PRESENCE_REQD 0x01
+#define SSH_SK_USER_VERIFICATION_REQD 0x04
+#define SSH_SK_RESIDENT_KEY 0x20
+
+/* Algs */
+#define SSH_SK_ECDSA 0x00
+#define SSH_SK_ED25519 0x01
+
+/* Error codes */
+#define SSH_SK_ERR_GENERAL -1
+#define SSH_SK_ERR_UNSUPPORTED -2
+#define SSH_SK_ERR_PIN_REQUIRED -3
+#define SSH_SK_ERR_DEVICE_NOT_FOUND -4
+
+struct sk_enroll_response {
+ uint8_t *public_key;
+ size_t public_key_len;
+ uint8_t *key_handle;
+ size_t key_handle_len;
+ uint8_t *signature;
+ size_t signature_len;
+ uint8_t *attestation_cert;
+ size_t attestation_cert_len;
+};
+
+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 required;
+};
+
+#define SSH_SK_VERSION_MAJOR 0x00050000 /* current API version */
+#define SSH_SK_VERSION_MAJOR_MASK 0xffff0000
+
+/* Return the version of the middleware API */
+uint32_t sk_api_version(void);
+
+/* Enroll a U2F key (private key generation) */
+int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
+ const char *application, uint8_t flags, const char *pin,
+ struct sk_option **options, struct sk_enroll_response **enroll_response);
+
+/* Sign a challenge */
+int sk_sign(uint32_t alg, const uint8_t *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);
+
+#endif /* _SK_API_H */
diff --git a/sk-usbhid.c b/sk-usbhid.c
new file mode 100644
index 00000000..25250824
--- /dev/null
+++ b/sk-usbhid.c
@@ -0,0 +1,1055 @@
+/*
+ * Copyright (c) 2019 Markus Friedl
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#ifdef ENABLE_SK_INTERNAL
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+#ifdef HAVE_SHA2_H
+#include <sha2.h>
+#endif
+
+#ifdef WITH_OPENSSL
+#include <openssl/opensslv.h>
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+#endif /* WITH_OPENSSL */
+
+#include <fido.h>
+#include <fido/credman.h>
+
+#ifndef SK_STANDALONE
+# include "log.h"
+# include "xmalloc.h"
+/*
+ * If building as part of OpenSSH, then rename exported functions.
+ * This must be done before including sk-api.h.
+ */
+# define sk_api_version ssh_sk_api_version
+# define sk_enroll ssh_sk_enroll
+# define sk_sign ssh_sk_sign
+# define sk_load_resident_keys ssh_sk_load_resident_keys
+#endif /* !SK_STANDALONE */
+
+#include "sk-api.h"
+
+/* #define SK_DEBUG 1 */
+
+#define MAX_FIDO_DEVICES 256
+
+/* Compatibility with OpenSSH 1.0.x */
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
+#define ECDSA_SIG_get0(sig, pr, ps) \
+ do { \
+ (*pr) = sig->r; \
+ (*ps) = sig->s; \
+ } while (0)
+#endif
+
+/* 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);
+
+/* Load resident keys */
+int sk_load_resident_keys(const char *pin, struct sk_option **options,
+ struct sk_resident_key ***rks, size_t *nrks);
+
+static void skdebug(const char *func, const char *fmt, ...)
+ __attribute__((__format__ (printf, 2, 3)));
+
+static void
+skdebug(const char *func, const char *fmt, ...)
+{
+#if !defined(SK_STANDALONE)
+ char *msg;
+ va_list ap;
+
+ va_start(ap, fmt);
+ xvasprintf(&msg, fmt, ap);
+ va_end(ap);
+ debug("%s: %s", func, msg);
+ free(msg);
+#elif defined(SK_DEBUG)
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "%s: ", func);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+#else
+ (void)func; /* XXX */
+ (void)fmt; /* XXX */
+#endif
+}
+
+uint32_t
+sk_api_version(void)
+{
+ return SSH_SK_VERSION_MAJOR;
+}
+
+/* Select the first identified FIDO device attached to the system */
+static char *
+pick_first_device(void)
+{
+ char *ret = NULL;
+ fido_dev_info_t *devlist = NULL;
+ size_t olen = 0;
+ 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 ((r = fido_dev_info_manifest(devlist, 1, &olen)) != FIDO_OK) {
+ skdebug(__func__, "fido_dev_info_manifest failed: %s",
+ fido_strerr(r));
+ goto out;
+ }
+ if (olen != 1) {
+ skdebug(__func__, "fido_dev_info_manifest bad len %zu", olen);
+ goto out;
+ }
+ 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;
+ }
+ out:
+ fido_dev_info_free(&devlist, 1);
+ return ret;
+}
+
+/* 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)
+{
+ fido_assert_t *assert = NULL;
+ int r = FIDO_ERR_INTERNAL;
+
+ 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) {
+ skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
+ fido_strerr(r));
+ goto out;
+ }
+ if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) {
+ skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r));
+ goto out;
+ }
+ if ((r = fido_assert_allow_cred(assert, key_handle,
+ key_handle_len)) != FIDO_OK) {
+ skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r));
+ goto out;
+ }
+ if ((r = fido_assert_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) {
+ skdebug(__func__, "fido_assert_up: %s", fido_strerr(r));
+ goto out;
+ }
+ r = fido_dev_get_assert(dev, assert, NULL);
+ skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
+ if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) {
+ /* U2F tokens may return this */
+ r = FIDO_OK;
+ }
+ out:
+ fido_assert_free(&assert);
+
+ return r != FIDO_OK ? -1 : 0;
+}
+
+/* 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,
+ 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;
+
+ 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;
+ }
+ return dev;
+ }
+
+ 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,
+ &devlist_len)) != FIDO_OK) {
+ skdebug(__func__, "fido_dev_info_manifest: %s", fido_strerr(r));
+ 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;
+ }
+ if (try_device(dev, message, message_len, application,
+ key_handle, key_handle_len) == 0) {
+ skdebug(__func__, "found key");
+ break;
+ }
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+ }
+
+ out:
+ if (devlist != NULL)
+ fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
+
+ return dev;
+}
+
+#ifdef WITH_OPENSSL
+/*
+ * The key returned via fido_cred_pubkey_ptr() is in affine coordinates,
+ * but the API expects a SEC1 octet string.
+ */
+static int
+pack_public_key_ecdsa(const fido_cred_t *cred,
+ struct sk_enroll_response *response)
+{
+ const uint8_t *ptr;
+ BIGNUM *x = NULL, *y = NULL;
+ EC_POINT *q = NULL;
+ EC_GROUP *g = NULL;
+ int ret = -1;
+
+ response->public_key = NULL;
+ response->public_key_len = 0;
+
+ if ((x = BN_new()) == NULL ||
+ (y = BN_new()) == NULL ||
+ (g = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL ||
+ (q = EC_POINT_new(g)) == NULL) {
+ skdebug(__func__, "libcrypto setup failed");
+ goto out;
+ }
+ if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
+ skdebug(__func__, "fido_cred_pubkey_ptr failed");
+ goto out;
+ }
+ if (fido_cred_pubkey_len(cred) != 64) {
+ skdebug(__func__, "bad fido_cred_pubkey_len %zu",
+ fido_cred_pubkey_len(cred));
+ goto out;
+ }
+
+ if (BN_bin2bn(ptr, 32, x) == NULL ||
+ BN_bin2bn(ptr + 32, 32, y) == NULL) {
+ skdebug(__func__, "BN_bin2bn failed");
+ goto out;
+ }
+ if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) {
+ skdebug(__func__, "EC_POINT_set_affine_coordinates_GFp failed");
+ goto out;
+ }
+ response->public_key_len = EC_POINT_point2oct(g, q,
+ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+ if (response->public_key_len == 0 || response->public_key_len > 2048) {
+ skdebug(__func__, "bad pubkey length %zu",
+ response->public_key_len);
+ goto out;
+ }
+ if ((response->public_key = malloc(response->public_key_len)) == NULL) {
+ skdebug(__func__, "malloc pubkey failed");
+ goto out;
+ }
+ if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED,
+ response->public_key, response->public_key_len, NULL) == 0) {
+ skdebug(__func__, "EC_POINT_point2oct failed");
+ goto out;
+ }
+ /* success */
+ ret = 0;
+ out:
+ if (ret != 0 && response->public_key != NULL) {
+ memset(response->public_key, 0, response->public_key_len);
+ free(response->public_key);
+ response->public_key = NULL;
+ }
+ EC_POINT_free(q);
+ EC_GROUP_free(g);
+ BN_clear_free(x);
+ BN_clear_free(y);
+ return ret;
+}
+#endif /* WITH_OPENSSL */
+
+static int
+pack_public_key_ed25519(const fido_cred_t *cred,
+ struct sk_enroll_response *response)
+{
+ const uint8_t *ptr;
+ size_t len;
+ int ret = -1;
+
+ response->public_key = NULL;
+ response->public_key_len = 0;
+
+ if ((len = fido_cred_pubkey_len(cred)) != 32) {
+ skdebug(__func__, "bad fido_cred_pubkey_len len %zu", len);
+ goto out;
+ }
+ if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
+ skdebug(__func__, "fido_cred_pubkey_ptr failed");
+ goto out;
+ }
+ response->public_key_len = len;
+ if ((response->public_key = malloc(response->public_key_len)) == NULL) {
+ skdebug(__func__, "malloc pubkey failed");
+ goto out;
+ }
+ memcpy(response->public_key, ptr, len);
+ ret = 0;
+ out:
+ if (ret != 0)
+ free(response->public_key);
+ return ret;
+}
+
+static int
+pack_public_key(uint32_t alg, const fido_cred_t *cred,
+ struct sk_enroll_response *response)
+{
+ switch(alg) {
+#ifdef WITH_OPENSSL
+ case SSH_SK_ECDSA:
+ return pack_public_key_ecdsa(cred, response);
+#endif /* WITH_OPENSSL */
+ case SSH_SK_ED25519:
+ return pack_public_key_ed25519(cred, response);
+ default:
+ return -1;
+ }
+}
+
+static int
+fidoerr_to_skerr(int fidoerr)
+{
+ switch (fidoerr) {
+ case FIDO_ERR_UNSUPPORTED_OPTION:
+ case FIDO_ERR_UNSUPPORTED_ALGORITHM:
+ return SSH_SK_ERR_UNSUPPORTED;
+ case FIDO_ERR_PIN_REQUIRED:
+ case FIDO_ERR_PIN_INVALID:
+ return SSH_SK_ERR_PIN_REQUIRED;
+ default:
+ return -1;
+ }
+}
+
+static int
+check_enroll_options(struct sk_option **options, char **devicep,
+ uint8_t *user_id, size_t user_id_len)
+{
+ size_t i;
+
+ if (options == NULL)
+ return 0;
+ for (i = 0; options[i] != NULL; i++) {
+ if (strcmp(options[i]->name, "device") == 0) {
+ if ((*devicep = strdup(options[i]->value)) == NULL) {
+ skdebug(__func__, "strdup device failed");
+ return -1;
+ }
+ skdebug(__func__, "requested device %s", *devicep);
+ } else if (strcmp(options[i]->name, "user") == 0) {
+ if (strlcpy(user_id, options[i]->value, user_id_len) >=
+ user_id_len) {
+ skdebug(__func__, "user too long");
+ return -1;
+ }
+ skdebug(__func__, "requested user %s",
+ (char *)user_id);
+ } else {
+ skdebug(__func__, "requested unsupported option %s",
+ options[i]->name);
+ if (options[i]->required) {
+ skdebug(__func__, "unknown required option");
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+int
+sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
+ const char *application, uint8_t flags, const char *pin,
+ struct sk_option **options, struct sk_enroll_response **enroll_response)
+{
+ fido_cred_t *cred = NULL;
+ fido_dev_t *dev = NULL;
+ const uint8_t *ptr;
+ uint8_t user_id[32];
+ struct sk_enroll_response *response = NULL;
+ size_t len;
+ int cose_alg;
+ int ret = SSH_SK_ERR_GENERAL;
+ int r;
+ char *device = NULL;
+
+#ifdef SK_DEBUG
+ fido_init(FIDO_DEBUG);
+#endif
+ if (enroll_response == NULL) {
+ skdebug(__func__, "enroll_response == NULL");
+ goto out;
+ }
+ memset(user_id, 0, sizeof(user_id));
+ 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:
+ cose_alg = COSE_ES256;
+ break;
+#endif /* WITH_OPENSSL */
+ case SSH_SK_ED25519:
+ cose_alg = COSE_EDDSA;
+ break;
+ default:
+ skdebug(__func__, "unsupported key type %d", alg);
+ goto out;
+ }
+ if (device == NULL && (device = pick_first_device()) == NULL) {
+ ret = SSH_SK_ERR_DEVICE_NOT_FOUND;
+ skdebug(__func__, "pick_first_device failed");
+ goto out;
+ }
+ skdebug(__func__, "using device %s", device);
+ if ((cred = fido_cred_new()) == NULL) {
+ skdebug(__func__, "fido_cred_new failed");
+ goto out;
+ }
+ if ((r = fido_cred_set_type(cred, cose_alg)) != FIDO_OK) {
+ skdebug(__func__, "fido_cred_set_type: %s", fido_strerr(r));
+ goto out;
+ }
+ if ((r = fido_cred_set_clientdata_hash(cred, challenge,
+ challenge_len)) != FIDO_OK) {
+ skdebug(__func__, "fido_cred_set_clientdata_hash: %s",
+ fido_strerr(r));
+ goto out;
+ }
+ if ((r = fido_cred_set_rk(cred, (flags & SSH_SK_RESIDENT_KEY) != 0 ?
+ FIDO_OPT_TRUE : FIDO_OPT_OMIT)) != FIDO_OK) {
+ skdebug(__func__, "fido_cred_set_rk: %s", fido_strerr(r));
+ goto out;
+ }
+ if ((r = fido_cred_set_user(cred, user_id, sizeof(user_id),
+ "openssh", "openssh", NULL)) != FIDO_OK) {
+ skdebug(__func__, "fido_cred_set_user: %s", fido_strerr(r));
+ goto out;
+ }
+ if ((r = fido_cred_set_rp(cred, application, NULL)) != FIDO_OK) {
+ skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r));
+ goto out;
+ }
+ if ((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));
+ goto out;
+ }
+ if ((r = fido_dev_make_cred(dev, cred, pin)) != FIDO_OK) {
+ skdebug(__func__, "fido_dev_make_cred: %s", fido_strerr(r));
+ ret = fidoerr_to_skerr(r);
+ goto out;
+ }
+ if (fido_cred_x5c_ptr(cred) != NULL) {
+ if ((r = fido_cred_verify(cred)) != FIDO_OK) {
+ skdebug(__func__, "fido_cred_verify: %s",
+ fido_strerr(r));
+ goto out;
+ }
+ } else {
+ skdebug(__func__, "self-attested credential");
+ if ((r = fido_cred_verify_self(cred)) != FIDO_OK) {
+ skdebug(__func__, "fido_cred_verify_self: %s",
+ fido_strerr(r));
+ goto out;
+ }
+ }
+ if ((response = calloc(1, sizeof(*response))) == NULL) {
+ skdebug(__func__, "calloc response failed");
+ goto out;
+ }
+ if (pack_public_key(alg, cred, response) != 0) {
+ skdebug(__func__, "pack_public_key failed");
+ goto out;
+ }
+ if ((ptr = fido_cred_id_ptr(cred)) != NULL) {
+ len = fido_cred_id_len(cred);
+ if ((response->key_handle = calloc(1, len)) == NULL) {
+ skdebug(__func__, "calloc key handle failed");
+ goto out;
+ }
+ memcpy(response->key_handle, ptr, len);
+ response->key_handle_len = len;
+ }
+ if ((ptr = fido_cred_sig_ptr(cred)) != NULL) {
+ len = fido_cred_sig_len(cred);
+ if ((response->signature = calloc(1, len)) == NULL) {
+ skdebug(__func__, "calloc signature failed");
+ goto out;
+ }
+ memcpy(response->signature, ptr, len);
+ response->signature_len = len;
+ }
+ if ((ptr = fido_cred_x5c_ptr(cred)) != NULL) {
+ len = fido_cred_x5c_len(cred);
+ debug3("%s: attestation cert len=%zu", __func__, len);
+ if ((response->attestation_cert = calloc(1, len)) == NULL) {
+ skdebug(__func__, "calloc attestation cert failed");
+ goto out;
+ }
+ memcpy(response->attestation_cert, ptr, len);
+ response->attestation_cert_len = len;
+ }
+ *enroll_response = response;
+ response = NULL;
+ ret = 0;
+ out:
+ free(device);
+ if (response != NULL) {
+ free(response->public_key);
+ free(response->key_handle);
+ free(response->signature);
+ free(response->attestation_cert);
+ free(response);
+ }
+ if (dev != NULL) {
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+ }
+ if (cred != NULL) {
+ fido_cred_free(&cred);
+ }
+ return ret;
+}
+
+#ifdef WITH_OPENSSL
+static int
+pack_sig_ecdsa(fido_assert_t *assert, struct sk_sign_response *response)
+{
+ ECDSA_SIG *sig = NULL;
+ const BIGNUM *sig_r, *sig_s;
+ const unsigned char *cp;
+ size_t sig_len;
+ int ret = -1;
+
+ cp = fido_assert_sig_ptr(assert, 0);
+ sig_len = fido_assert_sig_len(assert, 0);
+ if ((sig = d2i_ECDSA_SIG(NULL, &cp, sig_len)) == NULL) {
+ skdebug(__func__, "d2i_ECDSA_SIG failed");
+ goto out;
+ }
+ ECDSA_SIG_get0(sig, &sig_r, &sig_s);
+ response->sig_r_len = BN_num_bytes(sig_r);
+ response->sig_s_len = BN_num_bytes(sig_s);
+ if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL ||
+ (response->sig_s = calloc(1, response->sig_s_len)) == NULL) {
+ skdebug(__func__, "calloc signature failed");
+ goto out;
+ }
+ BN_bn2bin(sig_r, response->sig_r);
+ BN_bn2bin(sig_s, response->sig_s);
+ ret = 0;
+ out:
+ ECDSA_SIG_free(sig);
+ if (ret != 0) {
+ free(response->sig_r);
+ free(response->sig_s);
+ response->sig_r = NULL;
+ response->sig_s = NULL;
+ }
+ return ret;
+}
+#endif /* WITH_OPENSSL */
+
+static int
+pack_sig_ed25519(fido_assert_t *assert, struct sk_sign_response *response)
+{
+ const unsigned char *ptr;
+ size_t len;
+ int ret = -1;
+
+ ptr = fido_assert_sig_ptr(assert, 0);
+ len = fido_assert_sig_len(assert, 0);
+ if (len != 64) {
+ skdebug(__func__, "bad length %zu", len);
+ goto out;
+ }
+ response->sig_r_len = len;
+ if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) {
+ skdebug(__func__, "calloc signature failed");
+ goto out;
+ }
+ memcpy(response->sig_r, ptr, len);
+ ret = 0;
+ out:
+ if (ret != 0) {
+ free(response->sig_r);
+ response->sig_r = NULL;
+ }
+ return ret;
+}
+
+static int
+pack_sig(uint32_t alg, fido_assert_t *assert,
+ struct sk_sign_response *response)
+{
+ switch(alg) {
+#ifdef WITH_OPENSSL
+ case SSH_SK_ECDSA:
+ return pack_sig_ecdsa(assert, response);
+#endif /* WITH_OPENSSL */
+ case SSH_SK_ED25519:
+ return pack_sig_ed25519(assert, response);
+ default:
+ return -1;
+ }
+}
+
+/* Checks sk_options for sk_sign() and sk_load_resident_keys() */
+static int
+check_sign_load_resident_options(struct sk_option **options, char **devicep)
+{
+ size_t i;
+
+ if (options == NULL)
+ return 0;
+ for (i = 0; options[i] != NULL; i++) {
+ if (strcmp(options[i]->name, "device") == 0) {
+ if ((*devicep = strdup(options[i]->value)) == NULL) {
+ skdebug(__func__, "strdup device failed");
+ return -1;
+ }
+ skdebug(__func__, "requested device %s", *devicep);
+ } else {
+ skdebug(__func__, "requested unsupported option %s",
+ options[i]->name);
+ if (options[i]->required) {
+ skdebug(__func__, "unknown required option");
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* 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,
+ const uint8_t *key_handle, size_t key_handle_len,
+ uint8_t flags, const char *pin, struct sk_option **options,
+ struct sk_sign_response **sign_response)
+{
+ fido_assert_t *assert = NULL;
+ char *device = NULL;
+ fido_dev_t *dev = 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
+
+ if (sign_response == NULL) {
+ skdebug(__func__, "sign_response == NULL");
+ goto out;
+ }
+ *sign_response = NULL;
+ if (check_sign_load_resident_options(options, &device) != 0)
+ goto out; /* error already logged */
+ /* hash data to be signed before it goes to the security key */
+ if ((r = sha256_mem(data, datalen, message, sizeof(message))) != 0) {
+ skdebug(__func__, "hash message failed");
+ goto out;
+ }
+ if ((dev = find_device(device, message, sizeof(message),
+ application, key_handle, key_handle_len)) == NULL) {
+ skdebug(__func__, "couldn't find device for key handle");
+ goto out;
+ }
+ if ((assert = fido_assert_new()) == NULL) {
+ skdebug(__func__, "fido_assert_new failed");
+ goto out;
+ }
+ if ((r = fido_assert_set_clientdata_hash(assert, message,
+ sizeof(message))) != FIDO_OK) {
+ skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
+ fido_strerr(r));
+ goto out;
+ }
+ if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) {
+ skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r));
+ goto out;
+ }
+ if ((r = fido_assert_allow_cred(assert, key_handle,
+ key_handle_len)) != FIDO_OK) {
+ skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r));
+ goto out;
+ }
+ if ((r = fido_assert_set_up(assert,
+ (flags & SSH_SK_USER_PRESENCE_REQD) ?
+ FIDO_OPT_TRUE : FIDO_OPT_FALSE)) != FIDO_OK) {
+ skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r));
+ goto out;
+ }
+ if ((r = fido_dev_get_assert(dev, assert, NULL)) != FIDO_OK) {
+ skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
+ goto out;
+ }
+ if ((response = calloc(1, sizeof(*response))) == NULL) {
+ skdebug(__func__, "calloc response failed");
+ goto out;
+ }
+ response->flags = fido_assert_flags(assert, 0);
+ response->counter = fido_assert_sigcount(assert, 0);
+ if (pack_sig(alg, assert, response) != 0) {
+ skdebug(__func__, "pack_sig failed");
+ goto out;
+ }
+ *sign_response = response;
+ response = NULL;
+ ret = 0;
+ out:
+ explicit_bzero(message, sizeof(message));
+ free(device);
+ if (response != NULL) {
+ free(response->sig_r);
+ free(response->sig_s);
+ free(response);
+ }
+ if (dev != NULL) {
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+ }
+ if (assert != NULL) {
+ fido_assert_free(&assert);
+ }
+ return ret;
+}
+
+static int
+read_rks(const char *devpath, 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;
+ size_t i, j, nrp, nrk;
+ 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 ((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_ERR_INVALID_COMMAND) {
+ skdebug(__func__, "device %s does not support "
+ "resident keys", devpath);
+ ret = 0;
+ goto out;
+ }
+ skdebug(__func__, "get metadata for %s failed: %s",
+ devpath, fido_strerr(r));
+ ret = fidoerr_to_skerr(r);
+ goto out;
+ }
+ skdebug(__func__, "existing %llu, remaining %llu",
+ (unsigned long long)fido_credman_rk_existing(metadata),
+ (unsigned long long)fido_credman_rk_remaining(metadata));
+ if ((rp = fido_credman_rp_new()) == NULL) {
+ skdebug(__func__, "alloc rp failed");
+ goto out;
+ }
+ if ((r = fido_credman_get_dev_rp(dev, rp, pin)) != 0) {
+ skdebug(__func__, "get RPs for %s failed: %s",
+ devpath, fido_strerr(r));
+ goto out;
+ }
+ nrp = fido_credman_rp_count(rp);
+ skdebug(__func__, "Device %s has resident keys for %zu RPs",
+ devpath, nrp);
+
+ /* Iterate over RP IDs that have resident keys */
+ for (i = 0; i < nrp; i++) {
+ skdebug(__func__, "rp %zu: name=\"%s\" id=\"%s\" hashlen=%zu",
+ i, fido_credman_rp_name(rp, i), fido_credman_rp_id(rp, i),
+ fido_credman_rp_id_hash_len(rp, i));
+
+ /* Skip non-SSH RP IDs */
+ if (strncasecmp(fido_credman_rp_id(rp, i), "ssh:", 4) != 0)
+ continue;
+
+ fido_credman_rk_free(&rk);
+ if ((rk = fido_credman_rk_new()) == NULL) {
+ skdebug(__func__, "alloc rk failed");
+ goto out;
+ }
+ if ((r = fido_credman_get_dev_rk(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));
+ goto out;
+ }
+ nrk = fido_credman_rk_count(rk);
+ skdebug(__func__, "RP \"%s\" has %zu resident keys",
+ fido_credman_rp_id(rp, i), nrk);
+
+ /* Iterate over resident keys for this RP ID */
+ for (j = 0; j < nrk; j++) {
+ if ((cred = fido_credman_rk(rk, j)) == NULL) {
+ skdebug(__func__, "no RK in slot %zu", j);
+ continue;
+ }
+ skdebug(__func__, "Device %s RP \"%s\" slot %zu: "
+ "type %d", devpath, fido_credman_rp_id(rp, i), j,
+ fido_cred_type(cred));
+
+ /* build response entry */
+ if ((srk = calloc(1, sizeof(*srk))) == NULL ||
+ (srk->key.key_handle = calloc(1,
+ fido_cred_id_len(cred))) == NULL ||
+ (srk->application = strdup(fido_credman_rp_id(rp,
+ i))) == NULL) {
+ skdebug(__func__, "alloc sk_resident_key");
+ goto out;
+ }
+
+ srk->key.key_handle_len = fido_cred_id_len(cred);
+ memcpy(srk->key.key_handle,
+ fido_cred_id_ptr(cred),
+ srk->key.key_handle_len);
+
+ switch (fido_cred_type(cred)) {
+ case COSE_ES256:
+ srk->alg = SSH_SK_ECDSA;
+ break;
+ case COSE_EDDSA:
+ srk->alg = SSH_SK_ED25519;
+ break;
+ default:
+ skdebug(__func__, "unsupported key type %d",
+ fido_cred_type(cred));
+ goto out; /* XXX free rk and continue */
+ }
+
+ if ((r = pack_public_key(srk->alg, cred,
+ &srk->key)) != 0) {
+ skdebug(__func__, "pack public key failed");
+ goto out;
+ }
+ /* append */
+ if ((tmp = recallocarray(*rksp, *nrksp, (*nrksp) + 1,
+ sizeof(**rksp))) == NULL) {
+ skdebug(__func__, "alloc rksp");
+ goto out;
+ }
+ *rksp = tmp;
+ (*rksp)[(*nrksp)++] = srk;
+ srk = NULL;
+ }
+ }
+ /* Success */
+ ret = 0;
+ out:
+ if (srk != NULL) {
+ free(srk->application);
+ freezero(srk->key.public_key, srk->key.public_key_len);
+ freezero(srk->key.key_handle, srk->key.key_handle_len);
+ freezero(srk, sizeof(*srk));
+ }
+ fido_credman_rp_free(&rp);
+ fido_credman_rk_free(&rk);
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+ fido_credman_metadata_free(&metadata);
+ return ret;
+}
+
+int
+sk_load_resident_keys(const char *pin, struct sk_option **options,
+ struct sk_resident_key ***rksp, size_t *nrksp)
+{
+ int ret = SSH_SK_ERR_GENERAL, r = -1;
+ fido_dev_info_t *devlist = NULL;
+ size_t i, ndev = 0, nrks = 0;
+ const fido_dev_info_t *di;
+ struct sk_resident_key **rks = NULL;
+ char *device = NULL;
+ *rksp = NULL;
+ *nrksp = 0;
+
+ 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;
+ }
+ }
+ }
+ /* success, unless we have no keys but a specific error */
+ if (nrks > 0 || ret == SSH_SK_ERR_GENERAL)
+ ret = 0;
+ *rksp = rks;
+ *nrksp = nrks;
+ rks = NULL;
+ nrks = 0;
+ out:
+ free(device);
+ for (i = 0; i < nrks; i++) {
+ free(rks[i]->application);
+ freezero(rks[i]->key.public_key, rks[i]->key.public_key_len);
+ freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len);
+ freezero(rks[i], sizeof(*rks[i]));
+ }
+ free(rks);
+ fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
+ return ret;
+}
+
+#endif /* ENABLE_SK_INTERNAL */
diff --git a/sntrup4591761.c b/sntrup4591761.c
new file mode 100644
index 00000000..61fe2483
--- /dev/null
+++ b/sntrup4591761.c
@@ -0,0 +1,1083 @@
+/* $OpenBSD: sntrup4591761.c,v 1.3 2019/01/30 19:51:15 markus Exp $ */
+
+/*
+ * Public Domain, Authors:
+ * - Daniel J. Bernstein
+ * - Chitchanok Chuengsatiansup
+ * - Tanja Lange
+ * - Christine van Vredendaal
+ */
+
+#include "includes.h"
+
+#include <string.h>
+#include "crypto_api.h"
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/int32_sort.h */
+#ifndef int32_sort_h
+#define int32_sort_h
+
+
+static void int32_sort(crypto_int32 *,int);
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/int32_sort.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void minmax(crypto_int32 *x,crypto_int32 *y)
+{
+ crypto_uint32 xi = *x;
+ crypto_uint32 yi = *y;
+ crypto_uint32 xy = xi ^ yi;
+ crypto_uint32 c = yi - xi;
+ c ^= xy & (c ^ yi);
+ c >>= 31;
+ c = -c;
+ c &= xy;
+ *x = xi ^ c;
+ *y = yi ^ c;
+}
+
+static void int32_sort(crypto_int32 *x,int n)
+{
+ int top,p,q,i;
+
+ if (n < 2) return;
+ top = 1;
+ while (top < n - top) top += top;
+
+ for (p = top;p > 0;p >>= 1) {
+ for (i = 0;i < n - p;++i)
+ if (!(i & p))
+ minmax(x + i,x + i + p);
+ for (q = top;q > p;q >>= 1)
+ for (i = 0;i < n - q;++i)
+ if (!(i & p))
+ minmax(x + i + p,x + i + q);
+ }
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/small.h */
+#ifndef small_h
+#define small_h
+
+
+typedef crypto_int8 small;
+
+static void small_encode(unsigned char *,const small *);
+
+static void small_decode(small *,const unsigned char *);
+
+
+static void small_random(small *);
+
+static void small_random_weightw(small *);
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/mod3.h */
+#ifndef mod3_h
+#define mod3_h
+
+
+/* -1 if x is nonzero, 0 otherwise */
+static inline int mod3_nonzero_mask(small x)
+{
+ return -x*x;
+}
+
+/* input between -100000 and 100000 */
+/* output between -1 and 1 */
+static inline small mod3_freeze(crypto_int32 a)
+{
+ a -= 3 * ((10923 * a) >> 15);
+ a -= 3 * ((89478485 * a + 134217728) >> 28);
+ return a;
+}
+
+static inline small mod3_minusproduct(small a,small b,small c)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ crypto_int32 C = c;
+ return mod3_freeze(A - B * C);
+}
+
+static inline small mod3_plusproduct(small a,small b,small c)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ crypto_int32 C = c;
+ return mod3_freeze(A + B * C);
+}
+
+static inline small mod3_product(small a,small b)
+{
+ return a * b;
+}
+
+static inline small mod3_sum(small a,small b)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ return mod3_freeze(A + B);
+}
+
+static inline small mod3_reciprocal(small a1)
+{
+ return a1;
+}
+
+static inline small mod3_quotient(small num,small den)
+{
+ return mod3_product(num,mod3_reciprocal(den));
+}
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/modq.h */
+#ifndef modq_h
+#define modq_h
+
+
+typedef crypto_int16 modq;
+
+/* -1 if x is nonzero, 0 otherwise */
+static inline int modq_nonzero_mask(modq x)
+{
+ crypto_int32 r = (crypto_uint16) x;
+ r = -r;
+ r >>= 30;
+ return r;
+}
+
+/* input between -9000000 and 9000000 */
+/* output between -2295 and 2295 */
+static inline modq modq_freeze(crypto_int32 a)
+{
+ a -= 4591 * ((228 * a) >> 20);
+ a -= 4591 * ((58470 * a + 134217728) >> 28);
+ return a;
+}
+
+static inline modq modq_minusproduct(modq a,modq b,modq c)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ crypto_int32 C = c;
+ return modq_freeze(A - B * C);
+}
+
+static inline modq modq_plusproduct(modq a,modq b,modq c)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ crypto_int32 C = c;
+ return modq_freeze(A + B * C);
+}
+
+static inline modq modq_product(modq a,modq b)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ return modq_freeze(A * B);
+}
+
+static inline modq modq_square(modq a)
+{
+ crypto_int32 A = a;
+ return modq_freeze(A * A);
+}
+
+static inline modq modq_sum(modq a,modq b)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ return modq_freeze(A + B);
+}
+
+static inline modq modq_reciprocal(modq a1)
+{
+ modq a2 = modq_square(a1);
+ modq a3 = modq_product(a2,a1);
+ modq a4 = modq_square(a2);
+ modq a8 = modq_square(a4);
+ modq a16 = modq_square(a8);
+ modq a32 = modq_square(a16);
+ modq a35 = modq_product(a32,a3);
+ modq a70 = modq_square(a35);
+ modq a140 = modq_square(a70);
+ modq a143 = modq_product(a140,a3);
+ modq a286 = modq_square(a143);
+ modq a572 = modq_square(a286);
+ modq a1144 = modq_square(a572);
+ modq a1147 = modq_product(a1144,a3);
+ modq a2294 = modq_square(a1147);
+ modq a4588 = modq_square(a2294);
+ modq a4589 = modq_product(a4588,a1);
+ return a4589;
+}
+
+static inline modq modq_quotient(modq num,modq den)
+{
+ return modq_product(num,modq_reciprocal(den));
+}
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/params.h */
+#ifndef params_h
+#define params_h
+
+#define q 4591
+/* XXX: also built into modq in various ways */
+
+#define qshift 2295
+#define p 761
+#define w 286
+
+#define rq_encode_len 1218
+#define small_encode_len 191
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3.h */
+#ifndef r3_h
+#define r3_h
+
+
+static void r3_mult(small *,const small *,const small *);
+
+extern int r3_recip(small *,const small *);
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq.h */
+#ifndef rq_h
+#define rq_h
+
+
+static void rq_encode(unsigned char *,const modq *);
+
+static void rq_decode(modq *,const unsigned char *);
+
+static void rq_encoderounded(unsigned char *,const modq *);
+
+static void rq_decoderounded(modq *,const unsigned char *);
+
+static void rq_round3(modq *,const modq *);
+
+static void rq_mult(modq *,const modq *,const small *);
+
+int rq_recip3(modq *,const small *);
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/swap.h */
+#ifndef swap_h
+#define swap_h
+
+static void swap(void *,void *,int,int);
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/dec.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+#ifdef KAT
+#endif
+
+
+int crypto_kem_sntrup4591761_dec(
+ unsigned char *k,
+ const unsigned char *cstr,
+ const unsigned char *sk
+)
+{
+ small f[p];
+ modq h[p];
+ small grecip[p];
+ modq c[p];
+ modq t[p];
+ small t3[p];
+ small r[p];
+ modq hr[p];
+ unsigned char rstr[small_encode_len];
+ unsigned char hash[64];
+ int i;
+ int result = 0;
+ int weight;
+
+ small_decode(f,sk);
+ small_decode(grecip,sk + small_encode_len);
+ rq_decode(h,sk + 2 * small_encode_len);
+
+ rq_decoderounded(c,cstr + 32);
+
+ rq_mult(t,c,f);
+ for (i = 0;i < p;++i) t3[i] = mod3_freeze(modq_freeze(3*t[i]));
+
+ r3_mult(r,t3,grecip);
+
+#ifdef KAT
+ {
+ int j;
+ printf("decrypt r:");
+ for (j = 0;j < p;++j)
+ if (r[j] == 1) printf(" +%d",j);
+ else if (r[j] == -1) printf(" -%d",j);
+ printf("\n");
+ }
+#endif
+
+ weight = 0;
+ for (i = 0;i < p;++i) weight += (1 & r[i]);
+ weight -= w;
+ result |= modq_nonzero_mask(weight); /* XXX: puts limit on p */
+
+ rq_mult(hr,h,r);
+ rq_round3(hr,hr);
+ for (i = 0;i < p;++i) result |= modq_nonzero_mask(hr[i] - c[i]);
+
+ small_encode(rstr,r);
+ crypto_hash_sha512(hash,rstr,sizeof rstr);
+ result |= crypto_verify_32(hash,cstr);
+
+ for (i = 0;i < 32;++i) k[i] = (hash[32 + i] & ~result);
+ return result;
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/enc.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+#ifdef KAT
+#endif
+
+
+int crypto_kem_sntrup4591761_enc(
+ unsigned char *cstr,
+ unsigned char *k,
+ const unsigned char *pk
+)
+{
+ small r[p];
+ modq h[p];
+ modq c[p];
+ unsigned char rstr[small_encode_len];
+ unsigned char hash[64];
+
+ small_random_weightw(r);
+
+#ifdef KAT
+ {
+ int i;
+ printf("encrypt r:");
+ for (i = 0;i < p;++i)
+ if (r[i] == 1) printf(" +%d",i);
+ else if (r[i] == -1) printf(" -%d",i);
+ printf("\n");
+ }
+#endif
+
+ small_encode(rstr,r);
+ crypto_hash_sha512(hash,rstr,sizeof rstr);
+
+ rq_decode(h,pk);
+ rq_mult(c,h,r);
+ rq_round3(c,c);
+
+ memcpy(k,hash + 32,32);
+ memcpy(cstr,hash,32);
+ rq_encoderounded(cstr + 32,c);
+
+ return 0;
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/keypair.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+#if crypto_kem_sntrup4591761_PUBLICKEYBYTES != rq_encode_len
+#error "crypto_kem_sntrup4591761_PUBLICKEYBYTES must match rq_encode_len"
+#endif
+#if crypto_kem_sntrup4591761_SECRETKEYBYTES != rq_encode_len + 2 * small_encode_len
+#error "crypto_kem_sntrup4591761_SECRETKEYBYTES must match rq_encode_len + 2 * small_encode_len"
+#endif
+
+int crypto_kem_sntrup4591761_keypair(unsigned char *pk,unsigned char *sk)
+{
+ small g[p];
+ small grecip[p];
+ small f[p];
+ modq f3recip[p];
+ modq h[p];
+
+ do
+ small_random(g);
+ while (r3_recip(grecip,g) != 0);
+
+ small_random_weightw(f);
+ rq_recip3(f3recip,f);
+
+ rq_mult(h,f3recip,g);
+
+ rq_encode(pk,h);
+ small_encode(sk,f);
+ small_encode(sk + small_encode_len,grecip);
+ memcpy(sk + 2 * small_encode_len,pk,rq_encode_len);
+
+ return 0;
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3_mult.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void r3_mult(small *h,const small *f,const small *g)
+{
+ small fg[p + p - 1];
+ small result;
+ int i, j;
+
+ for (i = 0;i < p;++i) {
+ result = 0;
+ for (j = 0;j <= i;++j)
+ result = mod3_plusproduct(result,f[j],g[i - j]);
+ fg[i] = result;
+ }
+ for (i = p;i < p + p - 1;++i) {
+ result = 0;
+ for (j = i - p + 1;j < p;++j)
+ result = mod3_plusproduct(result,f[j],g[i - j]);
+ fg[i] = result;
+ }
+
+ for (i = p + p - 2;i >= p;--i) {
+ fg[i - p] = mod3_sum(fg[i - p],fg[i]);
+ fg[i - p + 1] = mod3_sum(fg[i - p + 1],fg[i]);
+ }
+
+ for (i = 0;i < p;++i)
+ h[i] = fg[i];
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3_recip.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+/* caller must ensure that x-y does not overflow */
+static int smaller_mask_r3_recip(int x,int y)
+{
+ return (x - y) >> 31;
+}
+
+static void vectormod3_product(small *z,int len,const small *x,const small c)
+{
+ int i;
+ for (i = 0;i < len;++i) z[i] = mod3_product(x[i],c);
+}
+
+static void vectormod3_minusproduct(small *z,int len,const small *x,const small *y,const small c)
+{
+ int i;
+ for (i = 0;i < len;++i) z[i] = mod3_minusproduct(x[i],y[i],c);
+}
+
+static void vectormod3_shift(small *z,int len)
+{
+ int i;
+ for (i = len - 1;i > 0;--i) z[i] = z[i - 1];
+ z[0] = 0;
+}
+
+/*
+r = s^(-1) mod m, returning 0, if s is invertible mod m
+or returning -1 if s is not invertible mod m
+r,s are polys of degree <p
+m is x^p-x-1
+*/
+int r3_recip(small *r,const small *s)
+{
+ const int loops = 2*p + 1;
+ int loop;
+ small f[p + 1];
+ small g[p + 1];
+ small u[2*p + 2];
+ small v[2*p + 2];
+ small c;
+ int i;
+ int d = p;
+ int e = p;
+ int swapmask;
+
+ for (i = 2;i < p;++i) f[i] = 0;
+ f[0] = -1;
+ f[1] = -1;
+ f[p] = 1;
+ /* generalization: can initialize f to any polynomial m */
+ /* requirements: m has degree exactly p, nonzero constant coefficient */
+
+ for (i = 0;i < p;++i) g[i] = s[i];
+ g[p] = 0;
+
+ for (i = 0;i <= loops;++i) u[i] = 0;
+
+ v[0] = 1;
+ for (i = 1;i <= loops;++i) v[i] = 0;
+
+ loop = 0;
+ for (;;) {
+ /* e == -1 or d + e + loop <= 2*p */
+
+ /* f has degree p: i.e., f[p]!=0 */
+ /* f[i]==0 for i < p-d */
+
+ /* g has degree <=p (so it fits in p+1 coefficients) */
+ /* g[i]==0 for i < p-e */
+
+ /* u has degree <=loop (so it fits in loop+1 coefficients) */
+ /* u[i]==0 for i < p-d */
+ /* if invertible: u[i]==0 for i < loop-p (so can look at just p+1 coefficients) */
+
+ /* v has degree <=loop (so it fits in loop+1 coefficients) */
+ /* v[i]==0 for i < p-e */
+ /* v[i]==0 for i < loop-p (so can look at just p+1 coefficients) */
+
+ if (loop >= loops) break;
+
+ c = mod3_quotient(g[p],f[p]);
+
+ vectormod3_minusproduct(g,p + 1,g,f,c);
+ vectormod3_shift(g,p + 1);
+
+#ifdef SIMPLER
+ vectormod3_minusproduct(v,loops + 1,v,u,c);
+ vectormod3_shift(v,loops + 1);
+#else
+ if (loop < p) {
+ vectormod3_minusproduct(v,loop + 1,v,u,c);
+ vectormod3_shift(v,loop + 2);
+ } else {
+ vectormod3_minusproduct(v + loop - p,p + 1,v + loop - p,u + loop - p,c);
+ vectormod3_shift(v + loop - p,p + 2);
+ }
+#endif
+
+ e -= 1;
+
+ ++loop;
+
+ swapmask = smaller_mask_r3_recip(e,d) & mod3_nonzero_mask(g[p]);
+ swap(&e,&d,sizeof e,swapmask);
+ swap(f,g,(p + 1) * sizeof(small),swapmask);
+
+#ifdef SIMPLER
+ swap(u,v,(loops + 1) * sizeof(small),swapmask);
+#else
+ if (loop < p) {
+ swap(u,v,(loop + 1) * sizeof(small),swapmask);
+ } else {
+ swap(u + loop - p,v + loop - p,(p + 1) * sizeof(small),swapmask);
+ }
+#endif
+ }
+
+ c = mod3_reciprocal(f[p]);
+ vectormod3_product(r,p,u + p,c);
+ return smaller_mask_r3_recip(0,d);
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/randomsmall.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void small_random(small *g)
+{
+ int i;
+
+ for (i = 0;i < p;++i) {
+ crypto_uint32 r = small_random32();
+ g[i] = (small) (((1073741823 & r) * 3) >> 30) - 1;
+ }
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/randomweightw.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void small_random_weightw(small *f)
+{
+ crypto_int32 r[p];
+ int i;
+
+ for (i = 0;i < p;++i) r[i] = small_random32();
+ for (i = 0;i < w;++i) r[i] &= -2;
+ for (i = w;i < p;++i) r[i] = (r[i] & -3) | 1;
+ int32_sort(r,p);
+ for (i = 0;i < p;++i) f[i] = ((small) (r[i] & 3)) - 1;
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void rq_encode(unsigned char *c,const modq *f)
+{
+ crypto_int32 f0, f1, f2, f3, f4;
+ int i;
+
+ for (i = 0;i < p/5;++i) {
+ f0 = *f++ + qshift;
+ f1 = *f++ + qshift;
+ f2 = *f++ + qshift;
+ f3 = *f++ + qshift;
+ f4 = *f++ + qshift;
+ /* now want f0 + 6144*f1 + ... as a 64-bit integer */
+ f1 *= 3;
+ f2 *= 9;
+ f3 *= 27;
+ f4 *= 81;
+ /* now want f0 + f1<<11 + f2<<22 + f3<<33 + f4<<44 */
+ f0 += f1 << 11;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0; f0 >>= 8;
+ f0 += f2 << 6;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0; f0 >>= 8;
+ f0 += f3 << 1;
+ *c++ = f0; f0 >>= 8;
+ f0 += f4 << 4;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0;
+ }
+ /* XXX: using p mod 5 = 1 */
+ f0 = *f++ + qshift;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0;
+}
+
+static void rq_decode(modq *f,const unsigned char *c)
+{
+ crypto_uint32 c0, c1, c2, c3, c4, c5, c6, c7;
+ crypto_uint32 f0, f1, f2, f3, f4;
+ int i;
+
+ for (i = 0;i < p/5;++i) {
+ c0 = *c++;
+ c1 = *c++;
+ c2 = *c++;
+ c3 = *c++;
+ c4 = *c++;
+ c5 = *c++;
+ c6 = *c++;
+ c7 = *c++;
+
+ /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 + f4*6144^4 */
+ /* = c0 + c1*256 + ... + c6*256^6 + c7*256^7 */
+ /* with each f between 0 and 4590 */
+
+ c6 += c7 << 8;
+ /* c6 <= 23241 = floor(4591*6144^4/2^48) */
+ /* f4 = (16/81)c6 + (1/1296)(c5+[0,1]) - [0,0.75] */
+ /* claim: 2^19 f4 < x < 2^19(f4+1) */
+ /* where x = 103564 c6 + 405(c5+1) */
+ /* proof: x - 2^19 f4 = (76/81)c6 + (37/81)c5 + 405 - (32768/81)[0,1] + 2^19[0,0.75] */
+ /* at least 405 - 32768/81 > 0 */
+ /* at most (76/81)23241 + (37/81)255 + 405 + 2^19 0.75 < 2^19 */
+ f4 = (103564*c6 + 405*(c5+1)) >> 19;
+
+ c5 += c6 << 8;
+ c5 -= (f4 * 81) << 4;
+ c4 += c5 << 8;
+
+ /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 */
+ /* = c0 + c1*256 + c2*256^2 + c3*256^3 + c4*256^4 */
+ /* c4 <= 247914 = floor(4591*6144^3/2^32) */
+ /* f3 = (1/54)(c4+[0,1]) - [0,0.75] */
+ /* claim: 2^19 f3 < x < 2^19(f3+1) */
+ /* where x = 9709(c4+2) */
+ /* proof: x - 2^19 f3 = 19418 - (1/27)c4 - (262144/27)[0,1] + 2^19[0,0.75] */
+ /* at least 19418 - 247914/27 - 262144/27 > 0 */
+ /* at most 19418 + 2^19 0.75 < 2^19 */
+ f3 = (9709*(c4+2)) >> 19;
+
+ c4 -= (f3 * 27) << 1;
+ c3 += c4 << 8;
+ /* f0 + f1*6144 + f2*6144^2 */
+ /* = c0 + c1*256 + c2*256^2 + c3*256^3 */
+ /* c3 <= 10329 = floor(4591*6144^2/2^24) */
+ /* f2 = (4/9)c3 + (1/576)c2 + (1/147456)c1 + (1/37748736)c0 - [0,0.75] */
+ /* claim: 2^19 f2 < x < 2^19(f2+1) */
+ /* where x = 233017 c3 + 910(c2+2) */
+ /* proof: x - 2^19 f2 = 1820 + (1/9)c3 - (2/9)c2 - (32/9)c1 - (1/72)c0 + 2^19[0,0.75] */
+ /* at least 1820 - (2/9)255 - (32/9)255 - (1/72)255 > 0 */
+ /* at most 1820 + (1/9)10329 + 2^19 0.75 < 2^19 */
+ f2 = (233017*c3 + 910*(c2+2)) >> 19;
+
+ c2 += c3 << 8;
+ c2 -= (f2 * 9) << 6;
+ c1 += c2 << 8;
+ /* f0 + f1*6144 */
+ /* = c0 + c1*256 */
+ /* c1 <= 110184 = floor(4591*6144/2^8) */
+ /* f1 = (1/24)c1 + (1/6144)c0 - (1/6144)f0 */
+ /* claim: 2^19 f1 < x < 2^19(f1+1) */
+ /* where x = 21845(c1+2) + 85 c0 */
+ /* proof: x - 2^19 f1 = 43690 - (1/3)c1 - (1/3)c0 + 2^19 [0,0.75] */
+ /* at least 43690 - (1/3)110184 - (1/3)255 > 0 */
+ /* at most 43690 + 2^19 0.75 < 2^19 */
+ f1 = (21845*(c1+2) + 85*c0) >> 19;
+
+ c1 -= (f1 * 3) << 3;
+ c0 += c1 << 8;
+ f0 = c0;
+
+ *f++ = modq_freeze(f0 + q - qshift);
+ *f++ = modq_freeze(f1 + q - qshift);
+ *f++ = modq_freeze(f2 + q - qshift);
+ *f++ = modq_freeze(f3 + q - qshift);
+ *f++ = modq_freeze(f4 + q - qshift);
+ }
+
+ c0 = *c++;
+ c1 = *c++;
+ c0 += c1 << 8;
+ *f++ = modq_freeze(c0 + q - qshift);
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_mult.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void rq_mult(modq *h,const modq *f,const small *g)
+{
+ modq fg[p + p - 1];
+ modq result;
+ int i, j;
+
+ for (i = 0;i < p;++i) {
+ result = 0;
+ for (j = 0;j <= i;++j)
+ result = modq_plusproduct(result,f[j],g[i - j]);
+ fg[i] = result;
+ }
+ for (i = p;i < p + p - 1;++i) {
+ result = 0;
+ for (j = i - p + 1;j < p;++j)
+ result = modq_plusproduct(result,f[j],g[i - j]);
+ fg[i] = result;
+ }
+
+ for (i = p + p - 2;i >= p;--i) {
+ fg[i - p] = modq_sum(fg[i - p],fg[i]);
+ fg[i - p + 1] = modq_sum(fg[i - p + 1],fg[i]);
+ }
+
+ for (i = 0;i < p;++i)
+ h[i] = fg[i];
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_recip3.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+/* caller must ensure that x-y does not overflow */
+static int smaller_mask_rq_recip3(int x,int y)
+{
+ return (x - y) >> 31;
+}
+
+static void vectormodq_product(modq *z,int len,const modq *x,const modq c)
+{
+ int i;
+ for (i = 0;i < len;++i) z[i] = modq_product(x[i],c);
+}
+
+static void vectormodq_minusproduct(modq *z,int len,const modq *x,const modq *y,const modq c)
+{
+ int i;
+ for (i = 0;i < len;++i) z[i] = modq_minusproduct(x[i],y[i],c);
+}
+
+static void vectormodq_shift(modq *z,int len)
+{
+ int i;
+ for (i = len - 1;i > 0;--i) z[i] = z[i - 1];
+ z[0] = 0;
+}
+
+/*
+r = (3s)^(-1) mod m, returning 0, if s is invertible mod m
+or returning -1 if s is not invertible mod m
+r,s are polys of degree <p
+m is x^p-x-1
+*/
+int rq_recip3(modq *r,const small *s)
+{
+ const int loops = 2*p + 1;
+ int loop;
+ modq f[p + 1];
+ modq g[p + 1];
+ modq u[2*p + 2];
+ modq v[2*p + 2];
+ modq c;
+ int i;
+ int d = p;
+ int e = p;
+ int swapmask;
+
+ for (i = 2;i < p;++i) f[i] = 0;
+ f[0] = -1;
+ f[1] = -1;
+ f[p] = 1;
+ /* generalization: can initialize f to any polynomial m */
+ /* requirements: m has degree exactly p, nonzero constant coefficient */
+
+ for (i = 0;i < p;++i) g[i] = 3 * s[i];
+ g[p] = 0;
+
+ for (i = 0;i <= loops;++i) u[i] = 0;
+
+ v[0] = 1;
+ for (i = 1;i <= loops;++i) v[i] = 0;
+
+ loop = 0;
+ for (;;) {
+ /* e == -1 or d + e + loop <= 2*p */
+
+ /* f has degree p: i.e., f[p]!=0 */
+ /* f[i]==0 for i < p-d */
+
+ /* g has degree <=p (so it fits in p+1 coefficients) */
+ /* g[i]==0 for i < p-e */
+
+ /* u has degree <=loop (so it fits in loop+1 coefficients) */
+ /* u[i]==0 for i < p-d */
+ /* if invertible: u[i]==0 for i < loop-p (so can look at just p+1 coefficients) */
+
+ /* v has degree <=loop (so it fits in loop+1 coefficients) */
+ /* v[i]==0 for i < p-e */
+ /* v[i]==0 for i < loop-p (so can look at just p+1 coefficients) */
+
+ if (loop >= loops) break;
+
+ c = modq_quotient(g[p],f[p]);
+
+ vectormodq_minusproduct(g,p + 1,g,f,c);
+ vectormodq_shift(g,p + 1);
+
+#ifdef SIMPLER
+ vectormodq_minusproduct(v,loops + 1,v,u,c);
+ vectormodq_shift(v,loops + 1);
+#else
+ if (loop < p) {
+ vectormodq_minusproduct(v,loop + 1,v,u,c);
+ vectormodq_shift(v,loop + 2);
+ } else {
+ vectormodq_minusproduct(v + loop - p,p + 1,v + loop - p,u + loop - p,c);
+ vectormodq_shift(v + loop - p,p + 2);
+ }
+#endif
+
+ e -= 1;
+
+ ++loop;
+
+ swapmask = smaller_mask_rq_recip3(e,d) & modq_nonzero_mask(g[p]);
+ swap(&e,&d,sizeof e,swapmask);
+ swap(f,g,(p + 1) * sizeof(modq),swapmask);
+
+#ifdef SIMPLER
+ swap(u,v,(loops + 1) * sizeof(modq),swapmask);
+#else
+ if (loop < p) {
+ swap(u,v,(loop + 1) * sizeof(modq),swapmask);
+ } else {
+ swap(u + loop - p,v + loop - p,(p + 1) * sizeof(modq),swapmask);
+ }
+#endif
+ }
+
+ c = modq_reciprocal(f[p]);
+ vectormodq_product(r,p,u + p,c);
+ return smaller_mask_rq_recip3(0,d);
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_round3.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void rq_round3(modq *h,const modq *f)
+{
+ int i;
+
+ for (i = 0;i < p;++i)
+ h[i] = ((21846 * (f[i] + 2295) + 32768) >> 16) * 3 - 2295;
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_rounded.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void rq_encoderounded(unsigned char *c,const modq *f)
+{
+ crypto_int32 f0, f1, f2;
+ int i;
+
+ for (i = 0;i < p/3;++i) {
+ f0 = *f++ + qshift;
+ f1 = *f++ + qshift;
+ f2 = *f++ + qshift;
+ f0 = (21846 * f0) >> 16;
+ f1 = (21846 * f1) >> 16;
+ f2 = (21846 * f2) >> 16;
+ /* now want f0 + f1*1536 + f2*1536^2 as a 32-bit integer */
+ f2 *= 3;
+ f1 += f2 << 9;
+ f1 *= 3;
+ f0 += f1 << 9;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0;
+ }
+ /* XXX: using p mod 3 = 2 */
+ f0 = *f++ + qshift;
+ f1 = *f++ + qshift;
+ f0 = (21846 * f0) >> 16;
+ f1 = (21846 * f1) >> 16;
+ f1 *= 3;
+ f0 += f1 << 9;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0;
+}
+
+static void rq_decoderounded(modq *f,const unsigned char *c)
+{
+ crypto_uint32 c0, c1, c2, c3;
+ crypto_uint32 f0, f1, f2;
+ int i;
+
+ for (i = 0;i < p/3;++i) {
+ c0 = *c++;
+ c1 = *c++;
+ c2 = *c++;
+ c3 = *c++;
+
+ /* f0 + f1*1536 + f2*1536^2 */
+ /* = c0 + c1*256 + c2*256^2 + c3*256^3 */
+ /* with each f between 0 and 1530 */
+
+ /* f2 = (64/9)c3 + (1/36)c2 + (1/9216)c1 + (1/2359296)c0 - [0,0.99675] */
+ /* claim: 2^21 f2 < x < 2^21(f2+1) */
+ /* where x = 14913081*c3 + 58254*c2 + 228*(c1+2) */
+ /* proof: x - 2^21 f2 = 456 - (8/9)c0 + (4/9)c1 - (2/9)c2 + (1/9)c3 + 2^21 [0,0.99675] */
+ /* at least 456 - (8/9)255 - (2/9)255 > 0 */
+ /* at most 456 + (4/9)255 + (1/9)255 + 2^21 0.99675 < 2^21 */
+ f2 = (14913081*c3 + 58254*c2 + 228*(c1+2)) >> 21;
+
+ c2 += c3 << 8;
+ c2 -= (f2 * 9) << 2;
+ /* f0 + f1*1536 */
+ /* = c0 + c1*256 + c2*256^2 */
+ /* c2 <= 35 = floor((1530+1530*1536)/256^2) */
+ /* f1 = (128/3)c2 + (1/6)c1 + (1/1536)c0 - (1/1536)f0 */
+ /* claim: 2^21 f1 < x < 2^21(f1+1) */
+ /* where x = 89478485*c2 + 349525*c1 + 1365*(c0+1) */
+ /* proof: x - 2^21 f1 = 1365 - (1/3)c2 - (1/3)c1 - (1/3)c0 + (4096/3)f0 */
+ /* at least 1365 - (1/3)35 - (1/3)255 - (1/3)255 > 0 */
+ /* at most 1365 + (4096/3)1530 < 2^21 */
+ f1 = (89478485*c2 + 349525*c1 + 1365*(c0+1)) >> 21;
+
+ c1 += c2 << 8;
+ c1 -= (f1 * 3) << 1;
+
+ c0 += c1 << 8;
+ f0 = c0;
+
+ *f++ = modq_freeze(f0 * 3 + q - qshift);
+ *f++ = modq_freeze(f1 * 3 + q - qshift);
+ *f++ = modq_freeze(f2 * 3 + q - qshift);
+ }
+
+ c0 = *c++;
+ c1 = *c++;
+ c2 = *c++;
+
+ f1 = (89478485*c2 + 349525*c1 + 1365*(c0+1)) >> 21;
+
+ c1 += c2 << 8;
+ c1 -= (f1 * 3) << 1;
+
+ c0 += c1 << 8;
+ f0 = c0;
+
+ *f++ = modq_freeze(f0 * 3 + q - qshift);
+ *f++ = modq_freeze(f1 * 3 + q - qshift);
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/small.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+/* XXX: these functions rely on p mod 4 = 1 */
+
+/* all coefficients in -1, 0, 1 */
+static void small_encode(unsigned char *c,const small *f)
+{
+ small c0;
+ int i;
+
+ for (i = 0;i < p/4;++i) {
+ c0 = *f++ + 1;
+ c0 += (*f++ + 1) << 2;
+ c0 += (*f++ + 1) << 4;
+ c0 += (*f++ + 1) << 6;
+ *c++ = c0;
+ }
+ c0 = *f++ + 1;
+ *c++ = c0;
+}
+
+static void small_decode(small *f,const unsigned char *c)
+{
+ unsigned char c0;
+ int i;
+
+ for (i = 0;i < p/4;++i) {
+ c0 = *c++;
+ *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2;
+ *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2;
+ *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2;
+ *f++ = ((small) (c0 & 3)) - 1;
+ }
+ c0 = *c++;
+ *f++ = ((small) (c0 & 3)) - 1;
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/swap.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void swap(void *x,void *y,int bytes,int mask)
+{
+ int i;
+ char xi, yi, c, t;
+
+ c = mask;
+
+ for (i = 0;i < bytes;++i) {
+ xi = i[(char *) x];
+ yi = i[(char *) y];
+ t = c & (xi ^ yi);
+ xi ^= t;
+ yi ^= t;
+ i[(char *) x] = xi;
+ i[(char *) y] = yi;
+ }
+}
+
diff --git a/sntrup4591761.sh b/sntrup4591761.sh
new file mode 100644
index 00000000..e684c332
--- /dev/null
+++ b/sntrup4591761.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# $OpenBSD: sntrup4591761.sh,v 1.3 2019/01/30 19:51:15 markus Exp $
+# Placed in the Public Domain.
+#
+AUTHOR="libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/implementors"
+FILES="
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/int32_sort.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/int32_sort.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/small.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/mod3.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/modq.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/params.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/swap.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/dec.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/enc.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/keypair.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3_mult.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3_recip.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/randomsmall.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/randomweightw.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_mult.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_recip3.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_round3.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_rounded.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/small.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/swap.c
+"
+###
+
+set -e
+cd $1
+echo -n '/* $'
+echo 'OpenBSD: $ */'
+echo
+echo '/*'
+echo ' * Public Domain, Authors:'
+sed -e '/Alphabetical order:/d' -e 's/^/ * - /' < $AUTHOR
+echo ' */'
+echo
+echo '#include <string.h>'
+echo '#include "crypto_api.h"'
+echo
+for i in $FILES; do
+ echo "/* from $i */"
+ b=$(basename $i .c)
+ grep \
+ -v '#include' $i | \
+ grep -v "extern crypto_int32 small_random32" |
+ sed -e "s/crypto_kem_/crypto_kem_sntrup4591761_/g" \
+ -e "s/smaller_mask/smaller_mask_${b}/g" \
+ -e "s/^extern void /static void /" \
+ -e "s/^void /static void /"
+ echo
+done
diff --git a/ssh-add.0 b/ssh-add.0
deleted file mode 100644
index 8ee39470..00000000
--- a/ssh-add.0
+++ /dev/null
@@ -1,128 +0,0 @@
-SSH-ADD(1) General Commands Manual SSH-ADD(1)
-
-NAME
- ssh-add M-bM-^@M-^S adds private key identities to the authentication agent
-
-SYNOPSIS
- ssh-add [-cDdkLlXx] [-E fingerprint_hash] [-t life] [file ...]
- ssh-add -s pkcs11
- ssh-add -e pkcs11
-
-DESCRIPTION
- ssh-add adds private key identities to the authentication agent,
- ssh-agent(1). When run without arguments, it adds the files
- ~/.ssh/id_rsa, ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and
- ~/.ssh/identity. After loading a private key, ssh-add will try to load
- corresponding certificate information from the filename obtained by
- appending -cert.pub to the name of the private key file. Alternative
- file names can be given on the command line.
-
- If any file requires a passphrase, ssh-add asks for the passphrase from
- the user. The passphrase is read from the user's tty. ssh-add retries
- the last passphrase if multiple identity files are given.
-
- The authentication agent must be running and the SSH_AUTH_SOCK
- environment variable must contain the name of its socket for ssh-add to
- work.
-
- The options are as follows:
-
- -c Indicates that added identities should be subject to confirmation
- before being used for authentication. Confirmation is performed
- by the SSH_ASKPASS program mentioned below. Successful
- confirmation is signaled by a zero exit status from the
- SSH_ASKPASS program, rather than text entered into the requester.
-
- -D Deletes all identities from the agent.
-
- -d Instead of adding identities, removes identities from the agent.
- If ssh-add has been run without arguments, the keys for the
- default identities and their corresponding certificates will be
- removed. Otherwise, the argument list will be interpreted as a
- list of paths to public key files to specify keys and
- certificates to be removed from the agent. If no public key is
- found at a given path, ssh-add will append .pub and retry.
-
- -E fingerprint_hash
- Specifies the hash algorithm used when displaying key
- fingerprints. Valid options are: M-bM-^@M-^\md5M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The
- default is M-bM-^@M-^\sha256M-bM-^@M-^].
-
- -e pkcs11
- Remove keys provided by the PKCS#11 shared library pkcs11.
-
- -k When loading keys into or deleting keys from the agent, process
- plain private keys only and skip certificates.
-
- -L Lists public key parameters of all identities currently
- represented by the agent.
-
- -l Lists fingerprints of all identities currently represented by the
- agent.
-
- -s pkcs11
- Add keys provided by the PKCS#11 shared library pkcs11.
-
- -t life
- Set a maximum lifetime when adding identities to an agent. The
- lifetime may be specified in seconds or in a time format
- specified in sshd_config(5).
-
- -X Unlock the agent.
-
- -x Lock the agent with a password.
-
-ENVIRONMENT
- DISPLAY and SSH_ASKPASS
- If ssh-add needs a passphrase, it will read the passphrase from
- the current terminal if it was run from a terminal. If ssh-add
- does not have a terminal associated with it but DISPLAY and
- SSH_ASKPASS are set, it will execute the program specified by
- SSH_ASKPASS and open an X11 window to read the passphrase. This
- is particularly useful when calling ssh-add from a .xsession or
- related script. (Note that on some machines it may be necessary
- to redirect the input from /dev/null to make this work.)
-
- SSH_AUTH_SOCK
- Identifies the path of a UNIX-domain socket used to communicate
- with the agent.
-
-FILES
- ~/.ssh/identity
- Contains the protocol version 1 RSA authentication identity of
- the user.
-
- ~/.ssh/id_dsa
- Contains the protocol version 2 DSA authentication identity of
- the user.
-
- ~/.ssh/id_ecdsa
- Contains the protocol version 2 ECDSA authentication identity of
- the user.
-
- ~/.ssh/id_ed25519
- Contains the protocol version 2 Ed25519 authentication identity
- of the user.
-
- ~/.ssh/id_rsa
- Contains the protocol version 2 RSA authentication identity of
- the user.
-
- Identity files should not be readable by anyone but the user. Note that
- ssh-add ignores identity files if they are accessible by others.
-
-EXIT STATUS
- Exit status is 0 on success, 1 if the specified command fails, and 2 if
- ssh-add is unable to contact the authentication agent.
-
-SEE ALSO
- ssh(1), ssh-agent(1), ssh-keygen(1), sshd(8)
-
-AUTHORS
- OpenSSH is a derivative of the original and free ssh 1.2.12 release by
- Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
- de Raadt and Dug Song removed many bugs, re-added newer features and
- created OpenSSH. Markus Friedl contributed the support for SSH protocol
- versions 1.5 and 2.0.
-
-OpenBSD 5.7 December 21, 2014 OpenBSD 5.7
diff --git a/ssh-add.1 b/ssh-add.1
index 926456f0..58d42138 100644
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-add.1,v 1.61 2014/12/21 22:27:56 djm Exp $
+.\" $OpenBSD: ssh-add.1,v 1.79 2020/02/07 03:57:31 djm Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,22 +35,26 @@
.\" (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 2014 $
+.Dd $Mdocdate: February 7 2020 $
.Dt SSH-ADD 1
.Os
.Sh NAME
.Nm ssh-add
-.Nd adds private key identities to the authentication agent
+.Nd adds private key identities to the OpenSSH authentication agent
.Sh SYNOPSIS
.Nm ssh-add
-.Op Fl cDdkLlXx
+.Op Fl cDdKkLlqvXx
.Op Fl E Ar fingerprint_hash
+.Op Fl S Ar provider
.Op Fl t Ar life
.Op Ar
.Nm ssh-add
.Fl s Ar pkcs11
.Nm ssh-add
.Fl e Ar pkcs11
+.Nm ssh-add
+.Fl T
+.Ar pubkey ...
.Sh DESCRIPTION
.Nm
adds private key identities to the authentication agent,
@@ -59,9 +63,10 @@ When run without arguments, it adds the files
.Pa ~/.ssh/id_rsa ,
.Pa ~/.ssh/id_dsa ,
.Pa ~/.ssh/id_ecdsa ,
-.Pa ~/.ssh/id_ed25519
+.Pa ~/.ssh/id_ecdsa_sk ,
+.Pa ~/.ssh/id_ed25519 ,
and
-.Pa ~/.ssh/identity .
+.Pa ~/.ssh/id_ed25519_sk .
After loading a private key,
.Nm
will try to load corresponding certificate information from the
@@ -88,12 +93,11 @@ The options are as follows:
.It Fl c
Indicates that added identities should be subject to confirmation before
being used for authentication.
-Confirmation is performed by the
-.Ev SSH_ASKPASS
-program mentioned below.
-Successful confirmation is signaled by a zero exit status from the
-.Ev SSH_ASKPASS
-program, rather than text entered into the requester.
+Confirmation is performed by
+.Xr ssh-askpass 1 .
+Successful confirmation is signaled by a zero exit status from
+.Xr ssh-askpass 1 ,
+rather than text entered into the requester.
.It Fl D
Deletes all identities from the agent.
.It Fl d
@@ -120,6 +124,8 @@ The default is
.It Fl e Ar pkcs11
Remove keys provided by the PKCS#11 shared library
.Ar pkcs11 .
+.It Fl K
+Load resident keys from a FIDO authenticator.
.It Fl k
When loading keys into or deleting keys from the agent, process plain private
keys only and skip certificates.
@@ -128,14 +134,34 @@ Lists public key parameters of all identities currently represented
by the agent.
.It Fl l
Lists fingerprints of all identities currently represented by the agent.
+.It Fl q
+Be quiet after a successful operation.
+.It Fl S Ar provider
+Specifies a path to a library that will be used when adding
+FIDO authenticator-hosted keys, overriding the default of using the
+internal USB HID support.
.It Fl s Ar pkcs11
Add keys provided by the PKCS#11 shared library
.Ar pkcs11 .
+.It Fl T Ar pubkey ...
+Tests whether the private keys that correspond to the specified
+.Ar pubkey
+files are usable by performing sign and verify operations on each.
.It Fl t Ar life
Set a maximum lifetime when adding identities to an agent.
The lifetime may be specified in seconds or in a time format
specified in
.Xr sshd_config 5 .
+.It Fl v
+Verbose mode.
+Causes
+.Nm
+to print debugging messages about its progress.
+This is helpful in debugging problems.
+Multiple
+.Fl v
+options increase the verbosity.
+The maximum is 3.
.It Fl X
Unlock the agent.
.It Fl x
@@ -156,6 +182,8 @@ and
.Ev SSH_ASKPASS
are set, it will execute the program specified by
.Ev SSH_ASKPASS
+(by default
+.Dq ssh-askpass )
and open an X11 window to read the passphrase.
This is particularly useful when calling
.Nm
@@ -170,19 +198,21 @@ to make this work.)
Identifies the path of a
.Ux Ns -domain
socket used to communicate with the agent.
+.It Ev SSH_SK_PROVIDER
+Specifies a path to a library that will be used when loading any
+FIDO authenticator-hosted keys, overriding the default of using
+the built-in USB HID support.
.El
.Sh FILES
-.Bl -tag -width Ds
-.It Pa ~/.ssh/identity
-Contains the protocol version 1 RSA authentication identity of the user.
+.Bl -tag -width Ds -compact
.It Pa ~/.ssh/id_dsa
-Contains the protocol version 2 DSA authentication identity of the user.
.It Pa ~/.ssh/id_ecdsa
-Contains the protocol version 2 ECDSA authentication identity of the user.
+.It Pa ~/.ssh/id_ecdsa_sk
.It Pa ~/.ssh/id_ed25519
-Contains the protocol version 2 Ed25519 authentication identity of the user.
+.It Pa ~/.ssh/id_ed25519_sk
.It Pa ~/.ssh/id_rsa
-Contains the protocol version 2 RSA authentication identity of the user.
+Contains the DSA, ECDSA, authenticator-hosted ECDSA, Ed25519,
+authenticator-hosted Ed25519 or RSA authentication identity of the user.
.El
.Pp
Identity files should not be readable by anyone but the user.
@@ -197,6 +227,7 @@ is unable to contact the authentication agent.
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-agent 1 ,
+.Xr ssh-askpass 1 ,
.Xr ssh-keygen 1 ,
.Xr sshd 8
.Sh AUTHORS
diff --git a/ssh-add.c b/ssh-add.c
index 98d46d3e..a40198ab 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-add.c,v 1.120 2015/02/21 21:46:57 halex Exp $ */
+/* $OpenBSD: ssh-add.c,v 1.155 2020/03/16 02:17:02 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -40,8 +40,10 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <openssl/evp.h>
-#include "openbsd-compat/openssl-compat.h"
+#ifdef WITH_OPENSSL
+# include <openssl/evp.h>
+# include "openbsd-compat/openssl-compat.h"
+#endif
#include <errno.h>
#include <fcntl.h>
@@ -55,7 +57,6 @@
#include "xmalloc.h"
#include "ssh.h"
-#include "rsa.h"
#include "log.h"
#include "sshkey.h"
#include "sshbuf.h"
@@ -65,6 +66,7 @@
#include "misc.h"
#include "ssherr.h"
#include "digest.h"
+#include "ssh-sk.h"
/* argv0 */
extern char *__progname;
@@ -76,35 +78,40 @@ static char *default_files[] = {
_PATH_SSH_CLIENT_ID_DSA,
#ifdef OPENSSL_HAS_ECC
_PATH_SSH_CLIENT_ID_ECDSA,
+ _PATH_SSH_CLIENT_ID_ECDSA_SK,
#endif
#endif /* WITH_OPENSSL */
_PATH_SSH_CLIENT_ID_ED25519,
- _PATH_SSH_CLIENT_IDENTITY,
+ _PATH_SSH_CLIENT_ID_ED25519_SK,
+ _PATH_SSH_CLIENT_ID_XMSS,
NULL
};
static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
/* Default lifetime (0 == forever) */
-static int lifetime = 0;
+static long lifetime = 0;
/* User has to confirm key use */
static int confirm = 0;
-/* we keep a cache of one passphrases */
+/* Maximum number of signatures (XMSS) */
+static u_int maxsign = 0;
+static u_int minleft = 0;
+
+/* we keep a cache of one passphrase */
static char *pass = NULL;
static void
clear_pass(void)
{
if (pass) {
- explicit_bzero(pass, strlen(pass));
- free(pass);
+ freezero(pass, strlen(pass));
pass = NULL;
}
}
static int
-delete_file(int agent_fd, const char *filename, int key_only)
+delete_file(int agent_fd, const char *filename, int key_only, int qflag)
{
struct sshkey *public, *cert = NULL;
char *certpath = NULL, *comment = NULL;
@@ -115,7 +122,10 @@ delete_file(int agent_fd, const char *filename, int key_only)
return -1;
}
if ((r = ssh_remove_identity(agent_fd, public)) == 0) {
- fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
+ if (!qflag) {
+ fprintf(stderr, "Identity removed: %s (%s)\n",
+ filename, comment);
+ }
ret = 0;
} else
fprintf(stderr, "Could not remove identity \"%s\": %s\n",
@@ -140,18 +150,18 @@ delete_file(int agent_fd, const char *filename, int key_only)
certpath, filename);
if ((r = ssh_remove_identity(agent_fd, cert)) == 0) {
- fprintf(stderr, "Identity removed: %s (%s)\n", certpath,
- comment);
+ if (!qflag) {
+ fprintf(stderr, "Identity removed: %s (%s)\n",
+ certpath, comment);
+ }
ret = 0;
} else
fprintf(stderr, "Could not remove identity \"%s\": %s\n",
certpath, ssh_err(r));
out:
- if (cert != NULL)
- sshkey_free(cert);
- if (public != NULL)
- sshkey_free(public);
+ sshkey_free(cert);
+ sshkey_free(public);
free(certpath);
free(comment);
@@ -160,37 +170,45 @@ delete_file(int agent_fd, const char *filename, int key_only)
/* Send a request to remove all identities. */
static int
-delete_all(int agent_fd)
+delete_all(int agent_fd, int qflag)
{
int ret = -1;
- if (ssh_remove_all_identities(agent_fd, 1) == 0)
+ /*
+ * Since the agent might be forwarded, old or non-OpenSSH, when asked
+ * to remove all keys, attempt to remove both protocol v.1 and v.2
+ * keys.
+ */
+ if (ssh_remove_all_identities(agent_fd, 2) == 0)
ret = 0;
- /* ignore error-code for ssh2 */
- /* XXX revisit */
- ssh_remove_all_identities(agent_fd, 2);
+ /* ignore error-code for ssh1 */
+ ssh_remove_all_identities(agent_fd, 1);
- if (ret == 0)
- fprintf(stderr, "All identities removed.\n");
- else
+ if (ret != 0)
fprintf(stderr, "Failed to remove all identities.\n");
+ else if (!qflag)
+ fprintf(stderr, "All identities removed.\n");
return ret;
}
static int
-add_file(int agent_fd, const char *filename, int key_only)
+add_file(int agent_fd, const char *filename, int key_only, int qflag,
+ const char *skprovider)
{
struct sshkey *private, *cert;
char *comment = NULL;
char msg[1024], *certpath = NULL;
int r, fd, ret = -1;
+ size_t i;
+ u_int32_t left;
struct sshbuf *keyblob;
+ struct ssh_identitylist *idlist;
if (strcmp(filename, "-") == 0) {
fd = STDIN_FILENO;
filename = "(stdin)";
- } else if ((fd = open(filename, O_RDONLY)) < 0) {
+ } else if ((fd = open(filename, O_RDONLY)) == -1) {
perror(filename);
return -1;
}
@@ -205,9 +223,7 @@ add_file(int agent_fd, const char *filename, int key_only)
return -1;
}
}
- if ((keyblob = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
- if ((r = sshkey_load_file(fd, keyblob)) != 0) {
+ if ((r = sshbuf_load_fd(fd, &keyblob)) != 0) {
fprintf(stderr, "Error loading key \"%s\": %s\n",
filename, ssh_err(r));
sshbuf_free(keyblob);
@@ -217,35 +233,32 @@ add_file(int agent_fd, const char *filename, int key_only)
close(fd);
/* At first, try empty passphrase */
- if ((r = sshkey_parse_private_fileblob(keyblob, "", filename,
- &private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
+ if ((r = sshkey_parse_private_fileblob(keyblob, "", &private,
+ &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
fprintf(stderr, "Error loading key \"%s\": %s\n",
filename, ssh_err(r));
goto fail_load;
}
/* try last */
if (private == NULL && pass != NULL) {
- if ((r = sshkey_parse_private_fileblob(keyblob, pass, filename,
- &private, &comment)) != 0 &&
- r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
+ if ((r = sshkey_parse_private_fileblob(keyblob, pass, &private,
+ &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
fprintf(stderr, "Error loading key \"%s\": %s\n",
filename, ssh_err(r));
goto fail_load;
}
}
- if (comment == NULL)
- comment = xstrdup(filename);
if (private == NULL) {
/* clear passphrase since it did not work */
clear_pass();
- snprintf(msg, sizeof msg, "Enter passphrase for %.200s%s: ",
- comment, confirm ? " (will confirm each use)" : "");
+ snprintf(msg, sizeof msg, "Enter passphrase for %s%s: ",
+ filename, confirm ? " (will confirm each use)" : "");
for (;;) {
pass = read_passphrase(msg, RP_ALLOW_STDIN);
if (strcmp(pass, "") == 0)
goto fail_load;
if ((r = sshkey_parse_private_fileblob(keyblob, pass,
- filename, &private, NULL)) == 0)
+ &private, &comment)) == 0)
break;
else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
fprintf(stderr,
@@ -253,28 +266,74 @@ add_file(int agent_fd, const char *filename, int key_only)
filename, ssh_err(r));
fail_load:
clear_pass();
- free(comment);
sshbuf_free(keyblob);
return -1;
}
clear_pass();
snprintf(msg, sizeof msg,
- "Bad passphrase, try again for %.200s%s: ", comment,
+ "Bad passphrase, try again for %s%s: ", filename,
confirm ? " (will confirm each use)" : "");
}
}
+ if (comment == NULL || *comment == '\0')
+ comment = xstrdup(filename);
sshbuf_free(keyblob);
+ /* For XMSS */
+ if ((r = sshkey_set_filename(private, filename)) != 0) {
+ fprintf(stderr, "Could not add filename to private key: %s (%s)\n",
+ filename, comment);
+ goto out;
+ }
+ if (maxsign && minleft &&
+ (r = ssh_fetch_identitylist(agent_fd, &idlist)) == 0) {
+ for (i = 0; i < idlist->nkeys; i++) {
+ if (!sshkey_equal_public(idlist->keys[i], private))
+ continue;
+ left = sshkey_signatures_left(idlist->keys[i]);
+ if (left < minleft) {
+ fprintf(stderr,
+ "Only %d signatures left.\n", left);
+ break;
+ }
+ fprintf(stderr, "Skipping update: ");
+ if (left == minleft) {
+ fprintf(stderr,
+ "required signatures left (%d).\n", left);
+ } else {
+ fprintf(stderr,
+ "more signatures left (%d) than"
+ " required (%d).\n", left, minleft);
+ }
+ ssh_free_identitylist(idlist);
+ goto out;
+ }
+ ssh_free_identitylist(idlist);
+ }
+
+ if (!sshkey_is_sk(private))
+ 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 ((r = ssh_add_identity_constrained(agent_fd, private, comment,
- lifetime, confirm)) == 0) {
- fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
+ lifetime, confirm, maxsign, skprovider)) == 0) {
ret = 0;
- if (lifetime != 0)
- fprintf(stderr,
- "Lifetime set to %d seconds\n", lifetime);
- if (confirm != 0)
- fprintf(stderr,
- "The user must confirm each use of the key\n");
+ if (!qflag) {
+ fprintf(stderr, "Identity added: %s (%s)\n",
+ filename, comment);
+ if (lifetime != 0) {
+ fprintf(stderr,
+ "Lifetime set to %ld seconds\n", lifetime);
+ }
+ if (confirm != 0) {
+ fprintf(stderr, "The user must confirm "
+ "each use of the key\n");
+ }
+ }
} else {
fprintf(stderr, "Could not add identity \"%s\": %s\n",
filename, ssh_err(r));
@@ -301,31 +360,38 @@ add_file(int agent_fd, const char *filename, int key_only)
}
/* Graft with private bits */
- if ((r = sshkey_to_certified(private,
- sshkey_cert_is_legacy(cert))) != 0) {
+ if ((r = sshkey_to_certified(private)) != 0) {
error("%s: sshkey_to_certified: %s", __func__, ssh_err(r));
sshkey_free(cert);
goto out;
}
if ((r = sshkey_cert_copy(cert, private)) != 0) {
- error("%s: key_cert_copy: %s", __func__, ssh_err(r));
+ error("%s: sshkey_cert_copy: %s", __func__, ssh_err(r));
sshkey_free(cert);
goto out;
}
sshkey_free(cert);
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
- lifetime, confirm)) != 0) {
+ lifetime, confirm, maxsign, skprovider)) != 0) {
error("Certificate %s (%s) add failed: %s", certpath,
private->cert->key_id, ssh_err(r));
goto out;
}
- fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
- private->cert->key_id);
- if (lifetime != 0)
- fprintf(stderr, "Lifetime set to %d seconds\n", lifetime);
- if (confirm != 0)
- fprintf(stderr, "The user must confirm each use of the key\n");
+ /* success */
+ if (!qflag) {
+ fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
+ private->cert->key_id);
+ if (lifetime != 0) {
+ fprintf(stderr, "Lifetime set to %ld seconds\n",
+ lifetime);
+ }
+ if (confirm != 0) {
+ fprintf(stderr, "The user must confirm each use "
+ "of the key\n");
+ }
+ }
+
out:
free(certpath);
free(comment);
@@ -335,7 +401,7 @@ add_file(int agent_fd, const char *filename, int key_only)
}
static int
-update_card(int agent_fd, int add, const char *id)
+update_card(int agent_fd, int add, const char *id, int qflag)
{
char *pin = NULL;
int r, ret = -1;
@@ -348,9 +414,11 @@ update_card(int agent_fd, int add, const char *id)
if ((r = ssh_update_card(agent_fd, add, id, pin == NULL ? "" : pin,
lifetime, confirm)) == 0) {
- fprintf(stderr, "Card %s: %s\n",
- add ? "added" : "removed", id);
ret = 0;
+ if (!qflag) {
+ fprintf(stderr, "Card %s: %s\n",
+ add ? "added" : "removed", id);
+ }
} else {
fprintf(stderr, "Could not %s card \"%s\": %s\n",
add ? "add" : "remove", id, ssh_err(r));
@@ -361,48 +429,79 @@ update_card(int agent_fd, int add, const char *id)
}
static int
+test_key(int agent_fd, const char *filename)
+{
+ struct sshkey *key = NULL;
+ u_char *sig = NULL;
+ size_t slen = 0;
+ int r, ret = -1;
+ char data[1024];
+
+ if ((r = sshkey_load_public(filename, &key, NULL)) != 0) {
+ error("Couldn't read public key %s: %s", filename, ssh_err(r));
+ return -1;
+ }
+ arc4random_buf(data, sizeof(data));
+ if ((r = ssh_agent_sign(agent_fd, key, &sig, &slen, data, sizeof(data),
+ NULL, 0)) != 0) {
+ error("Agent signature failed for %s: %s",
+ filename, ssh_err(r));
+ goto done;
+ }
+ if ((r = sshkey_verify(key, sig, slen, data, sizeof(data),
+ NULL, 0, NULL)) != 0) {
+ error("Signature verification failed for %s: %s",
+ filename, ssh_err(r));
+ goto done;
+ }
+ /* success */
+ ret = 0;
+ done:
+ free(sig);
+ sshkey_free(key);
+ return ret;
+}
+
+static int
list_identities(int agent_fd, int do_fp)
{
char *fp;
- int version, r, had_identities = 0;
+ int r;
struct ssh_identitylist *idlist;
+ u_int32_t left;
size_t i;
- for (version = 1; version <= 2; version++) {
- if ((r = ssh_fetch_identitylist(agent_fd, version,
- &idlist)) != 0) {
- if (r != SSH_ERR_AGENT_NO_IDENTITIES)
- fprintf(stderr, "error fetching identities for "
- "protocol %d: %s\n", version, ssh_err(r));
- continue;
- }
- for (i = 0; i < idlist->nkeys; i++) {
- had_identities = 1;
- if (do_fp) {
- fp = sshkey_fingerprint(idlist->keys[i],
- fingerprint_hash, SSH_FP_DEFAULT);
- printf("%d %s %s (%s)\n",
- sshkey_size(idlist->keys[i]),
- fp == NULL ? "(null)" : fp,
- idlist->comments[i],
- sshkey_type(idlist->keys[i]));
- free(fp);
- } else {
- if ((r = sshkey_write(idlist->keys[i],
- stdout)) != 0) {
- fprintf(stderr, "sshkey_write: %s\n",
- ssh_err(r));
- continue;
- }
- fprintf(stdout, " %s\n", idlist->comments[i]);
+ if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) {
+ if (r != SSH_ERR_AGENT_NO_IDENTITIES)
+ fprintf(stderr, "error fetching identities: %s\n",
+ ssh_err(r));
+ else
+ printf("The agent has no identities.\n");
+ return -1;
+ }
+ for (i = 0; i < idlist->nkeys; i++) {
+ if (do_fp) {
+ fp = sshkey_fingerprint(idlist->keys[i],
+ fingerprint_hash, SSH_FP_DEFAULT);
+ printf("%u %s %s (%s)\n", sshkey_size(idlist->keys[i]),
+ fp == NULL ? "(null)" : fp, idlist->comments[i],
+ sshkey_type(idlist->keys[i]));
+ free(fp);
+ } else {
+ if ((r = sshkey_write(idlist->keys[i], stdout)) != 0) {
+ fprintf(stderr, "sshkey_write: %s\n",
+ ssh_err(r));
+ continue;
}
+ fprintf(stdout, " %s", idlist->comments[i]);
+ left = sshkey_signatures_left(idlist->keys[i]);
+ if (left > 0)
+ fprintf(stdout,
+ " [signatures left %d]", left);
+ fprintf(stdout, "\n");
}
- ssh_free_identitylist(idlist);
- }
- if (!had_identities) {
- printf("The agent has no identities.\n");
- return -1;
}
+ ssh_free_identitylist(idlist);
return 0;
}
@@ -421,8 +520,7 @@ lock_agent(int agent_fd, int lock)
fprintf(stderr, "Passwords do not match.\n");
passok = 0;
}
- explicit_bzero(p2, strlen(p2));
- free(p2);
+ freezero(p2, strlen(p2));
}
if (passok) {
if ((r = ssh_lock_agent(agent_fd, lock, p1)) == 0) {
@@ -433,19 +531,68 @@ lock_agent(int agent_fd, int lock)
lock ? "" : "un", ssh_err(r));
}
}
- explicit_bzero(p1, strlen(p1));
- free(p1);
+ freezero(p1, strlen(p1));
return (ret);
}
static int
-do_file(int agent_fd, int deleting, int key_only, char *file)
+load_resident_keys(int agent_fd, const char *skprovider, int qflag)
+{
+ struct sshkey **keys;
+ size_t nkeys, i;
+ int r, ok = 0;
+ char *fp;
+
+ pass = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN);
+ if ((r = sshsk_load_resident(skprovider, NULL, pass,
+ &keys, &nkeys)) != 0) {
+ error("Unable to load resident keys: %s", ssh_err(r));
+ 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__);
+ if ((r = ssh_add_identity_constrained(agent_fd, keys[i], "",
+ lifetime, confirm, maxsign, skprovider)) != 0) {
+ error("Unable to add key %s %s",
+ sshkey_type(keys[i]), fp);
+ free(fp);
+ ok = r;
+ continue;
+ }
+ if (ok == 0)
+ ok = 1;
+ if (!qflag) {
+ fprintf(stderr, "Resident identity added: %s %s\n",
+ sshkey_type(keys[i]), fp);
+ if (lifetime != 0) {
+ fprintf(stderr,
+ "Lifetime set to %ld seconds\n", lifetime);
+ }
+ if (confirm != 0) {
+ fprintf(stderr, "The user must confirm "
+ "each use of the key\n");
+ }
+ }
+ free(fp);
+ sshkey_free(keys[i]);
+ }
+ free(keys);
+ if (nkeys == 0)
+ return SSH_ERR_KEY_NOT_FOUND;
+ return ok == 1 ? 0 : ok;
+}
+
+static int
+do_file(int agent_fd, int deleting, int key_only, char *file, int qflag,
+ const char *skprovider)
{
if (deleting) {
- if (delete_file(agent_fd, file, key_only) == -1)
+ if (delete_file(agent_fd, file, key_only, qflag) == -1)
return -1;
} else {
- if (add_file(agent_fd, file, key_only) == -1)
+ if (add_file(agent_fd, file, key_only, qflag, skprovider) == -1)
return -1;
}
return 0;
@@ -454,20 +601,16 @@ do_file(int agent_fd, int deleting, int key_only, char *file)
static void
usage(void)
{
- fprintf(stderr, "usage: %s [options] [file ...]\n", __progname);
- fprintf(stderr, "Options:\n");
- fprintf(stderr, " -l List fingerprints of all identities.\n");
- fprintf(stderr, " -E hash Specify hash algorithm used for fingerprints.\n");
- fprintf(stderr, " -L List public key parameters of all identities.\n");
- fprintf(stderr, " -k Load only keys and not certificates.\n");
- fprintf(stderr, " -c Require confirmation to sign using identities\n");
- fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n");
- fprintf(stderr, " -d Delete identity.\n");
- fprintf(stderr, " -D Delete all identities.\n");
- fprintf(stderr, " -x Lock agent.\n");
- fprintf(stderr, " -X Unlock agent.\n");
- fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n");
- fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n");
+ fprintf(stderr,
+"usage: ssh-add [-cDdKkLlqvXx] [-E fingerprint_hash] [-S provider] [-t life]\n"
+#ifdef WITH_XMSS
+" [-M maxsign] [-m minleft]\n"
+#endif
+" [file ...]\n"
+" ssh-add -s pkcs11\n"
+" ssh-add -e pkcs11\n"
+" ssh-add -T pubkey ...\n"
+ );
}
int
@@ -476,9 +619,11 @@ main(int argc, char **argv)
extern char *optarg;
extern int optind;
int agent_fd;
- char *pkcs11provider = NULL;
- int r, i, ch, deleting = 0, ret = 0, key_only = 0;
- int xflag = 0, lflag = 0, Dflag = 0;
+ char *pkcs11provider = NULL, *skprovider = NULL;
+ int r, i, ch, deleting = 0, ret = 0, key_only = 0, do_download = 0;
+ int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0;
+ SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
+ LogLevel log_level = SYSLOG_LEVEL_INFO;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@@ -486,9 +631,7 @@ main(int argc, char **argv)
__progname = ssh_get_progname(argv[0]);
seed_rng();
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
-#endif
+ log_init(__progname, log_level, log_facility, 1);
setvbuf(stdout, NULL, _IOLBF, 0);
@@ -505,8 +648,16 @@ main(int argc, char **argv)
exit(2);
}
- while ((ch = getopt(argc, argv, "klLcdDxXE:e:s:t:")) != -1) {
+ skprovider = getenv("SSH_SK_PROVIDER");
+
+ while ((ch = getopt(argc, argv, "vkKlLcdDTxXE:e:M:m:qs:S:t:")) != -1) {
switch (ch) {
+ case 'v':
+ if (log_level == SYSLOG_LEVEL_INFO)
+ log_level = SYSLOG_LEVEL_DEBUG1;
+ else if (log_level < SYSLOG_LEVEL_DEBUG3)
+ log_level++;
+ break;
case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg);
if (fingerprint_hash == -1)
@@ -515,6 +666,9 @@ main(int argc, char **argv)
case 'k':
key_only = 1;
break;
+ case 'K':
+ do_download = 1;
+ break;
case 'l':
case 'L':
if (lflag != 0)
@@ -530,6 +684,22 @@ main(int argc, char **argv)
case 'c':
confirm = 1;
break;
+ case 'm':
+ minleft = (int)strtonum(optarg, 1, UINT_MAX, NULL);
+ if (minleft == 0) {
+ usage();
+ ret = 1;
+ goto done;
+ }
+ break;
+ case 'M':
+ maxsign = (int)strtonum(optarg, 1, UINT_MAX, NULL);
+ if (maxsign == 0) {
+ usage();
+ ret = 1;
+ goto done;
+ }
+ break;
case 'd':
deleting = 1;
break;
@@ -539,23 +709,34 @@ main(int argc, char **argv)
case 's':
pkcs11provider = optarg;
break;
+ case 'S':
+ skprovider = optarg;
+ break;
case 'e':
deleting = 1;
pkcs11provider = optarg;
break;
case 't':
- if ((lifetime = convtime(optarg)) == -1) {
+ if ((lifetime = convtime(optarg)) == -1 ||
+ lifetime < 0 || (u_long)lifetime > UINT32_MAX) {
fprintf(stderr, "Invalid lifetime\n");
ret = 1;
goto done;
}
break;
+ case 'q':
+ qflag = 1;
+ break;
+ case 'T':
+ Tflag = 1;
+ break;
default:
usage();
ret = 1;
goto done;
}
}
+ log_init(__progname, log_level, log_facility, 1);
if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1)
fatal("Invalid combination of actions");
@@ -568,15 +749,36 @@ main(int argc, char **argv)
ret = 1;
goto done;
} else if (Dflag) {
- if (delete_all(agent_fd) == -1)
+ if (delete_all(agent_fd, qflag) == -1)
ret = 1;
goto done;
}
+#ifdef ENABLE_SK_INTERNAL
+ if (skprovider == NULL)
+ skprovider = "internal";
+#endif
+
argc -= optind;
argv += optind;
+ if (Tflag) {
+ if (argc <= 0)
+ fatal("no keys to test");
+ for (r = i = 0; i < argc; i++)
+ r |= test_key(agent_fd, argv[i]);
+ ret = r == 0 ? 0 : 1;
+ goto done;
+ }
if (pkcs11provider != NULL) {
- if (update_card(agent_fd, !deleting, pkcs11provider) == -1)
+ if (update_card(agent_fd, !deleting, pkcs11provider,
+ qflag) == -1)
+ ret = 1;
+ goto done;
+ }
+ if (do_download) {
+ if (skprovider == NULL)
+ fatal("Cannot download keys without provider");
+ if (load_resident_keys(agent_fd, skprovider, qflag) != 0)
ret = 1;
goto done;
}
@@ -596,9 +798,10 @@ main(int argc, char **argv)
for (i = 0; default_files[i]; i++) {
snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
default_files[i]);
- if (stat(buf, &st) < 0)
+ if (stat(buf, &st) == -1)
continue;
- if (do_file(agent_fd, deleting, key_only, buf) == -1)
+ if (do_file(agent_fd, deleting, key_only, buf,
+ qflag, skprovider) == -1)
ret = 1;
else
count++;
@@ -608,13 +811,12 @@ main(int argc, char **argv)
} else {
for (i = 0; i < argc; i++) {
if (do_file(agent_fd, deleting, key_only,
- argv[i]) == -1)
+ argv[i], qflag, skprovider) == -1)
ret = 1;
}
}
- clear_pass();
-
done:
+ clear_pass();
ssh_close_authentication_socket(agent_fd);
return ret;
}
diff --git a/ssh-agent.0 b/ssh-agent.0
deleted file mode 100644
index 30f4eb3b..00000000
--- a/ssh-agent.0
+++ /dev/null
@@ -1,109 +0,0 @@
-SSH-AGENT(1) General Commands Manual SSH-AGENT(1)
-
-NAME
- ssh-agent M-bM-^@M-^S authentication agent
-
-SYNOPSIS
- ssh-agent [-c | -s] [-d] [-a bind_address] [-E fingerprint_hash]
- [-t life] [command [arg ...]]
- ssh-agent [-c | -s] -k
-
-DESCRIPTION
- ssh-agent is a program to hold private keys used for public key
- authentication (RSA, DSA, ECDSA, Ed25519). ssh-agent is usually started
- in the beginning of an X-session or a login session, and all other
- windows or programs are started as clients to the ssh-agent program.
- Through use of environment variables the agent can be located and
- automatically used for authentication when logging in to other machines
- using ssh(1).
-
- The agent initially does not have any private keys. Keys are added using
- ssh-add(1). Multiple identities may be stored in ssh-agent concurrently
- and ssh(1) will automatically use them if present. ssh-add(1) is also
- used to remove keys from ssh-agent and to query the keys that are held in
- one.
-
- The options are as follows:
-
- -a bind_address
- Bind the agent to the UNIX-domain socket bind_address. The
- default is $TMPDIR/ssh-XXXXXXXXXX/agent.<ppid>.
-
- -c Generate C-shell commands on stdout. This is the default if
- SHELL looks like it's a csh style of shell.
-
- -d Debug mode. When this option is specified ssh-agent will not
- fork.
-
- -E fingerprint_hash
- Specifies the hash algorithm used when displaying key
- fingerprints. Valid options are: M-bM-^@M-^\md5M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The
- default is M-bM-^@M-^\sha256M-bM-^@M-^].
-
- -k Kill the current agent (given by the SSH_AGENT_PID environment
- variable).
-
- -s Generate Bourne shell commands on stdout. This is the default if
- SHELL does not look like it's a csh style of shell.
-
- -t life
- Set a default value for the maximum lifetime of identities added
- to the agent. The lifetime may be specified in seconds or in a
- time format specified in sshd_config(5). A lifetime specified
- for an identity with ssh-add(1) overrides this value. Without
- this option the default maximum lifetime is forever.
-
- If a commandline is given, this is executed as a subprocess of the agent.
- When the command dies, so does the agent.
-
- The idea is that the agent is run in the user's local PC, laptop, or
- terminal. Authentication data need not be stored on any other machine,
- and authentication passphrases never go over the network. However, the
- connection to the agent is forwarded over SSH remote logins, and the user
- can thus use the privileges given by the identities anywhere in the
- network in a secure way.
-
- There are two main ways to get an agent set up: The first is that the
- agent starts a new subcommand into which some environment variables are
- exported, eg ssh-agent xterm &. The second is that the agent prints the
- needed shell commands (either sh(1) or csh(1) syntax can be generated)
- which can be evaluated in the calling shell, eg eval `ssh-agent -s` for
- Bourne-type shells such as sh(1) or ksh(1) and eval `ssh-agent -c` for
- csh(1) and derivatives.
-
- Later ssh(1) looks at these variables and uses them to establish a
- connection to the agent.
-
- The agent will never send a private key over its request channel.
- Instead, operations that require a private key will be performed by the
- agent, and the result will be returned to the requester. This way,
- private keys are not exposed to clients using the agent.
-
- A UNIX-domain socket is created and the name of this socket is stored in
- the SSH_AUTH_SOCK environment variable. The socket is made accessible
- only to the current user. This method is easily abused by root or
- another instance of the same user.
-
- The SSH_AGENT_PID environment variable holds the agent's process ID.
-
- The agent exits automatically when the command given on the command line
- terminates.
-
-FILES
- $TMPDIR/ssh-XXXXXXXXXX/agent.<ppid>
- UNIX-domain sockets used to contain the connection to the
- authentication agent. These sockets should only be readable by
- the owner. The sockets should get automatically removed when the
- agent exits.
-
-SEE ALSO
- ssh(1), ssh-add(1), ssh-keygen(1), sshd(8)
-
-AUTHORS
- OpenSSH is a derivative of the original and free ssh 1.2.12 release by
- Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
- de Raadt and Dug Song removed many bugs, re-added newer features and
- created OpenSSH. Markus Friedl contributed the support for SSH protocol
- versions 1.5 and 2.0.
-
-OpenBSD 5.7 December 21, 2014 OpenBSD 5.7
diff --git a/ssh-agent.1 b/ssh-agent.1
index 6759afec..fff0db6b 100644
--- a/ssh-agent.1
+++ b/ssh-agent.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-agent.1,v 1.57 2014/12/21 22:27:56 djm Exp $
+.\" $OpenBSD: ssh-agent.1,v 1.70 2019/12/21 20:22:34 naddy Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -34,18 +34,19 @@
.\" (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 2014 $
+.Dd $Mdocdate: December 21 2019 $
.Dt SSH-AGENT 1
.Os
.Sh NAME
.Nm ssh-agent
-.Nd authentication agent
+.Nd OpenSSH authentication agent
.Sh SYNOPSIS
.Nm ssh-agent
.Op Fl c | s
-.Op Fl d
+.Op Fl \&Dd
.Op Fl a Ar bind_address
.Op Fl E Ar fingerprint_hash
+.Op Fl P Ar provider_whitelist
.Op Fl t Ar life
.Op Ar command Op Ar arg ...
.Nm ssh-agent
@@ -53,30 +54,12 @@
.Fl k
.Sh DESCRIPTION
.Nm
-is a program to hold private keys used for public key authentication
-(RSA, DSA, ECDSA, Ed25519).
-.Nm
-is usually started in the beginning of an X-session or a login session, and
-all other windows or programs are started as clients to the ssh-agent
-program.
+is a program to hold private keys used for public key authentication.
Through use of environment variables the agent can be located
and automatically used for authentication when logging in to other
machines using
.Xr ssh 1 .
.Pp
-The agent initially does not have any private keys.
-Keys are added using
-.Xr ssh-add 1 .
-Multiple identities may be stored in
-.Nm
-concurrently and
-.Xr ssh 1
-will automatically use them if present.
-.Xr ssh-add 1
-is also used to remove keys from
-.Nm
-and to query the keys that are held in one.
-.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl a Ar bind_address
@@ -92,11 +75,16 @@ Generate C-shell commands on
This is the default if
.Ev SHELL
looks like it's a csh style of shell.
+.It Fl D
+Foreground mode.
+When this option is specified
+.Nm
+will not fork.
.It Fl d
Debug mode.
When this option is specified
.Nm
-will not fork.
+will not fork and will write debug information to standard error.
.It Fl E Ar fingerprint_hash
Specifies the hash algorithm used when displaying key fingerprints.
Valid options are:
@@ -109,6 +97,20 @@ 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
+.Fl S
+or
+.Fl s
+options to
+.Xr ssh-add 1 .
+Libraries that do not match the whitelist will be refused.
+See PATTERNS in
+.Xr ssh_config 5
+for a description of pattern-list syntax.
+The default whitelist is
+.Dq /usr/lib/*,/usr/local/lib/* .
.It Fl s
Generate Bourne shell commands on
.Dv stdout .
@@ -123,67 +125,85 @@ A lifetime specified for an identity with
.Xr ssh-add 1
overrides this value.
Without this option the default maximum lifetime is forever.
+.It Ar command Op Ar arg ...
+If a command (and optional arguments) is given,
+this is executed as a subprocess of the agent.
+The agent exits automatically when the command given on the command
+line terminates.
.El
.Pp
-If a commandline is given, this is executed as a subprocess of the agent.
-When the command dies, so does the agent.
-.Pp
-The idea is that the agent is run in the user's local PC, laptop, or
-terminal.
-Authentication data need not be stored on any other
-machine, and authentication passphrases never go over the network.
-However, the connection to the agent is forwarded over SSH
-remote logins, and the user can thus use the privileges given by the
-identities anywhere in the network in a secure way.
-.Pp
-There are two main ways to get an agent set up:
-The first is that the agent starts a new subcommand into which some environment
-variables are exported, eg
+There are two main ways to get an agent set up.
+The first is at the start of an X session,
+where all other windows or programs are started as children of the
+.Nm
+program.
+The agent starts a command under which its environment
+variables are exported, for example
.Cm ssh-agent xterm & .
-The second is that the agent prints the needed shell commands (either
-.Xr sh 1
-or
-.Xr csh 1
-syntax can be generated) which can be evaluated in the calling shell, eg
-.Cm eval `ssh-agent -s`
-for Bourne-type shells such as
-.Xr sh 1
-or
-.Xr ksh 1
-and
-.Cm eval `ssh-agent -c`
-for
-.Xr csh 1
-and derivatives.
+When the command terminates, so does the agent.
+.Pp
+The second method is used for a login session.
+When
+.Nm
+is started,
+it prints the shell commands required to set its environment variables,
+which in turn can be evaluated in the calling shell, for example
+.Cm eval `ssh-agent -s` .
.Pp
-Later
+In both cases,
.Xr ssh 1
-looks at these 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 will never send a private key over its request channel.
-Instead, operations that require a private key will be performed
-by the agent, and the result will be returned to the requester.
-This way, private keys are not exposed to clients using the agent.
+The agent initially does not have any private keys.
+Keys are added using
+.Xr ssh-add 1
+or by
+.Xr ssh 1
+when
+.Cm AddKeysToAgent
+is set in
+.Xr ssh_config 5 .
+Multiple identities may be stored in
+.Nm
+concurrently and
+.Xr ssh 1
+will automatically use them if present.
+.Xr ssh-add 1
+is also used to remove keys from
+.Nm
+and to query the keys that are held in one.
.Pp
-A
+Connections to
+.Nm
+may be forwarded from further remote hosts using the
+.Fl A
+option to
+.Xr ssh 1
+(but see the caveats documented therein),
+avoiding the need for authentication data to be stored on other machines.
+Authentication passphrases and private keys never go over the network:
+the connection to the agent is forwarded over SSH remote connections
+and the result is returned to the requester,
+allowing the user access to their identities anywhere in the network
+in a secure fashion.
+.Sh ENVIRONMENT
+.Bl -tag -width "SSH_AGENT_PID"
+.It Ev SSH_AGENT_PID
+When
+.Nm
+starts, it stores the name of the agent's process ID (PID) in this variable.
+.It Ev SSH_AUTH_SOCK
+When
+.Nm
+starts, it creates a
.Ux Ns -domain
-socket is created and the name of this socket is stored in the
-.Ev SSH_AUTH_SOCK
-environment
-variable.
-The socket is made accessible only to the current user.
-This method is easily abused by root or another instance of the same
-user.
-.Pp
-The
-.Ev SSH_AGENT_PID
-environment variable holds the agent's process ID.
-.Pp
-The agent exits automatically when the command given on the command
-line terminates.
+socket and stores its pathname in this variable.
+It is accessible only to the current user,
+but is easily abused by root or another instance of the same user.
+.El
.Sh FILES
.Bl -tag -width Ds
-.It Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt
+.It Pa $TMPDIR/ssh-XXXXXXXXXX/agent.<ppid>
.Ux Ns -domain
sockets used to contain the connection to the authentication agent.
These sockets should only be readable by the owner.
@@ -193,13 +213,15 @@ The sockets should get automatically removed when the agent exits.
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-keygen 1 ,
+.Xr ssh_config 5 ,
.Xr sshd 8
.Sh AUTHORS
-OpenSSH is a derivative of the original and free
-ssh 1.2.12 release by Tatu Ylonen.
-Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
-Theo de Raadt and Dug Song
-removed many bugs, re-added newer features and
-created OpenSSH.
-Markus Friedl contributed the support for SSH
-protocol versions 1.5 and 2.0.
+.An -nosplit
+OpenSSH is a derivative of the original and free ssh 1.2.12 release by
+.An Tatu Ylonen .
+.An Aaron Campbell , Bob Beck , Markus Friedl , Niels Provos , Theo de Raadt
+and
+.An Dug Song
+removed many bugs, re-added newer features and created OpenSSH.
+.An Markus Friedl
+contributed the support for SSH protocol versions 1.5 and 2.0.
diff --git a/ssh-agent.c b/ssh-agent.c
index aeda656a..e081413b 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-agent.c,v 1.199 2015/03/04 21:12:59 djm Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.257 2020/03/06 18:28:27 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -36,12 +36,12 @@
#include "includes.h"
-#include <sys/param.h> /* MIN MAX */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/socket.h>
+#include <sys/wait.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
@@ -61,6 +61,9 @@
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
+#ifdef HAVE_POLL_H
+# include <poll.h>
+#endif
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
@@ -68,13 +71,12 @@
#include <time.h>
#include <string.h>
#include <unistd.h>
-
-#include "key.h" /* XXX for typedef */
-#include "buffer.h" /* XXX for typedef */
+#ifdef HAVE_UTIL_H
+# include <util.h>
+#endif
#include "xmalloc.h"
#include "ssh.h"
-#include "rsa.h"
#include "sshbuf.h"
#include "sshkey.h"
#include "authfd.h"
@@ -83,15 +85,22 @@
#include "misc.h"
#include "digest.h"
#include "ssherr.h"
-
-#ifdef ENABLE_PKCS11
+#include "match.h"
+#include "msg.h"
+#include "ssherr.h"
+#include "pathnames.h"
#include "ssh-pkcs11.h"
-#endif
+#include "sk-api.h"
-#if defined(HAVE_SYS_PRCTL_H)
-#include <sys/prctl.h> /* For prctl() and PR_SET_DUMPABLE */
+#ifndef DEFAULT_PROVIDER_WHITELIST
+# define DEFAULT_PROVIDER_WHITELIST "/usr/lib*/*,/usr/local/lib*/*"
#endif
+/* Maximum accepted message length */
+#define AGENT_MAX_LEN (256*1024)
+/* Maximum bytes to read from client socket */
+#define AGENT_RBUF_LEN (4096)
+
typedef enum {
AUTH_UNUSED,
AUTH_SOCKET,
@@ -116,15 +125,16 @@ typedef struct identity {
char *provider;
time_t death;
u_int confirm;
+ char *sk_provider;
} Identity;
-typedef struct {
+struct idtable {
int nentries;
TAILQ_HEAD(idqueue, identity) idlist;
-} Idtab;
+};
-/* private key table, one per protocol version */
-Idtab idtable[3];
+/* private key table */
+struct idtable *idtab;
int max_fd = 0;
@@ -139,9 +149,16 @@ 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;
+
/* locking */
+#define LOCK_SIZE 32
+#define LOCK_SALT_SIZE 16
+#define LOCK_ROUNDS 1
int locked = 0;
-char *lock_passwd = NULL;
+u_char lock_pwhash[LOCK_SIZE];
+u_char lock_salt[LOCK_SALT_SIZE];
extern char *__progname;
@@ -164,21 +181,9 @@ close_socket(SocketEntry *e)
static void
idtab_init(void)
{
- int i;
-
- for (i = 0; i <=2; i++) {
- TAILQ_INIT(&idtable[i].idlist);
- idtable[i].nentries = 0;
- }
-}
-
-/* return private key table for requested protocol version */
-static Idtab *
-idtab_lookup(int version)
-{
- if (version < 1 || version > 2)
- fatal("internal error, bad protocol version %d", version);
- return &idtable[version];
+ idtab = xcalloc(1, sizeof(*idtab));
+ TAILQ_INIT(&idtab->idlist);
+ idtab->nentries = 0;
}
static void
@@ -187,17 +192,17 @@ free_identity(Identity *id)
sshkey_free(id->key);
free(id->provider);
free(id->comment);
+ free(id->sk_provider);
free(id);
}
/* return matching private key for given public key */
static Identity *
-lookup_identity(struct sshkey *key, int version)
+lookup_identity(struct sshkey *key)
{
Identity *id;
- Idtab *tab = idtab_lookup(version);
- TAILQ_FOREACH(id, &tab->idlist, next) {
+ TAILQ_FOREACH(id, &idtab->idlist, next) {
if (sshkey_equal(key, id->key))
return (id);
}
@@ -234,161 +239,74 @@ send_status(SocketEntry *e, int success)
/* send list of supported public keys to 'client' */
static void
-process_request_identities(SocketEntry *e, int version)
+process_request_identities(SocketEntry *e)
{
- Idtab *tab = idtab_lookup(version);
Identity *id;
struct sshbuf *msg;
int r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- if ((r = sshbuf_put_u8(msg, (version == 1) ?
- SSH_AGENT_RSA_IDENTITIES_ANSWER :
- SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
- (r = sshbuf_put_u32(msg, tab->nentries)) != 0)
+ if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
+ (r = sshbuf_put_u32(msg, idtab->nentries)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- TAILQ_FOREACH(id, &tab->idlist, next) {
- if (id->key->type == KEY_RSA1) {
-#ifdef WITH_SSH1
- if ((r = sshbuf_put_u32(msg,
- BN_num_bits(id->key->rsa->n))) != 0 ||
- (r = sshbuf_put_bignum1(msg,
- id->key->rsa->e)) != 0 ||
- (r = sshbuf_put_bignum1(msg,
- id->key->rsa->n)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
-#endif
- } else {
- u_char *blob;
- size_t blen;
-
- if ((r = sshkey_to_blob(id->key, &blob, &blen)) != 0) {
- error("%s: sshkey_to_blob: %s", __func__,
- ssh_err(r));
- continue;
- }
- if ((r = sshbuf_put_string(msg, blob, blen)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
- free(blob);
+ TAILQ_FOREACH(id, &idtab->idlist, next) {
+ if ((r = sshkey_puts_opts(id->key, msg, SSHKEY_SERIALIZE_INFO))
+ != 0 ||
+ (r = sshbuf_put_cstring(msg, id->comment)) != 0) {
+ error("%s: put key/comment: %s", __func__,
+ ssh_err(r));
+ continue;
}
- if ((r = sshbuf_put_cstring(msg, id->comment)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(msg);
}
-#ifdef WITH_SSH1
-/* ssh1 only */
-static void
-process_authentication_challenge1(SocketEntry *e)
-{
- u_char buf[32], mdbuf[16], session_id[16];
- u_int response_type;
- BIGNUM *challenge;
- Identity *id;
- int r, len;
- struct sshbuf *msg;
- struct ssh_digest_ctx *md;
- struct sshkey *key;
-
- if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
- if ((key = sshkey_new(KEY_RSA1)) == NULL)
- fatal("%s: sshkey_new failed", __func__);
- if ((challenge = BN_new()) == NULL)
- fatal("%s: BN_new failed", __func__);
-
- if ((r = sshbuf_get_u32(e->request, NULL)) != 0 || /* ignored */
- (r = sshbuf_get_bignum1(e->request, key->rsa->e)) != 0 ||
- (r = sshbuf_get_bignum1(e->request, key->rsa->n)) != 0 ||
- (r = sshbuf_get_bignum1(e->request, challenge)))
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
-
- /* Only protocol 1.1 is supported */
- if (sshbuf_len(e->request) == 0)
- goto failure;
- if ((r = sshbuf_get(e->request, session_id, sizeof(session_id))) != 0 ||
- (r = sshbuf_get_u32(e->request, &response_type)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (response_type != 1)
- goto failure;
-
- id = lookup_identity(key, 1);
- if (id != NULL && (!id->confirm || confirm_key(id) == 0)) {
- struct sshkey *private = id->key;
- /* Decrypt the challenge using the private key. */
- if ((r = rsa_private_decrypt(challenge, challenge,
- private->rsa) != 0)) {
- fatal("%s: rsa_public_encrypt: %s", __func__,
- ssh_err(r));
- goto failure; /* XXX ? */
- }
- /* The response is MD5 of decrypted challenge plus session id */
- len = BN_num_bytes(challenge);
- if (len <= 0 || len > 32) {
- logit("%s: bad challenge length %d", __func__, len);
- goto failure;
- }
- memset(buf, 0, 32);
- BN_bn2bin(challenge, buf + 32 - len);
- if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
- ssh_digest_update(md, buf, 32) < 0 ||
- ssh_digest_update(md, session_id, 16) < 0 ||
- ssh_digest_final(md, mdbuf, sizeof(mdbuf)) < 0)
- fatal("%s: md5 failed", __func__);
- ssh_digest_free(md);
-
- /* Send the response. */
- if ((r = sshbuf_put_u8(msg, SSH_AGENT_RSA_RESPONSE)) != 0 ||
- (r = sshbuf_put(msg, mdbuf, sizeof(mdbuf))) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- goto send;
+static char *
+agent_decode_alg(struct sshkey *key, u_int flags)
+{
+ if (key->type == KEY_RSA) {
+ if (flags & SSH_AGENT_RSA_SHA2_256)
+ return "rsa-sha2-256";
+ else if (flags & SSH_AGENT_RSA_SHA2_512)
+ return "rsa-sha2-512";
+ } else if (key->type == KEY_RSA_CERT) {
+ if (flags & SSH_AGENT_RSA_SHA2_256)
+ return "rsa-sha2-256-cert-v01@openssh.com";
+ else if (flags & SSH_AGENT_RSA_SHA2_512)
+ return "rsa-sha2-512-cert-v01@openssh.com";
}
-
- failure:
- /* Unknown identity or protocol error. Send failure. */
- if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- send:
- if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- sshkey_free(key);
- BN_clear_free(challenge);
- sshbuf_free(msg);
+ return NULL;
}
-#endif
/* ssh2 only */
static void
process_sign_request2(SocketEntry *e)
{
- u_char *blob, *data, *signature = NULL;
- size_t blen, dlen, slen = 0;
+ const u_char *data;
+ u_char *signature = NULL;
+ size_t dlen, slen = 0;
u_int compat = 0, flags;
int r, ok = -1;
+ char *fp = NULL;
struct sshbuf *msg;
- struct sshkey *key;
+ struct sshkey *key = NULL;
struct identity *id;
+ struct notifier_ctx *notifier = NULL;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0 ||
- (r = sshbuf_get_string(e->request, &data, &dlen)) != 0 ||
- (r = sshbuf_get_u32(e->request, &flags)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (flags & SSH_AGENT_OLD_SIGNATURE)
- compat = SSH_BUG_SIGBLOB;
- if ((r = sshkey_from_blob(blob, blen, &key)) != 0) {
- error("%s: cannot parse key blob: %s", __func__, ssh_err(ok));
+ if ((r = sshkey_froms(e->request, &key)) != 0 ||
+ (r = sshbuf_get_string_direct(e->request, &data, &dlen)) != 0 ||
+ (r = sshbuf_get_u32(e->request, &flags)) != 0) {
+ error("%s: couldn't parse request: %s", __func__, ssh_err(r));
goto send;
}
- if ((id = lookup_identity(key, 2)) == NULL) {
+
+ if ((id = lookup_identity(key)) == NULL) {
verbose("%s: %s key not found", __func__, sshkey_type(key));
goto send;
}
@@ -396,15 +314,27 @@ process_sign_request2(SocketEntry *e)
verbose("%s: user refused key", __func__);
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 ((r = sshkey_sign(id->key, &signature, &slen,
- data, dlen, compat)) != 0) {
- error("%s: sshkey_sign: %s", __func__, ssh_err(ok));
+ data, dlen, agent_decode_alg(key, flags),
+ id->sk_provider, compat)) != 0) {
+ error("%s: sshkey_sign: %s", __func__, ssh_err(r));
goto send;
}
/* Success */
ok = 0;
send:
+ notify_complete(notifier);
sshkey_free(key);
+ free(fp);
if (ok == 0) {
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
(r = sshbuf_put_string(msg, signature, slen)) != 0)
@@ -416,90 +346,52 @@ process_sign_request2(SocketEntry *e)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(msg);
- free(data);
- free(blob);
free(signature);
}
/* shared */
static void
-process_remove_identity(SocketEntry *e, int version)
+process_remove_identity(SocketEntry *e)
{
- size_t blen;
int r, success = 0;
struct sshkey *key = NULL;
- u_char *blob;
-#ifdef WITH_SSH1
- u_int bits;
-#endif /* WITH_SSH1 */
-
- switch (version) {
-#ifdef WITH_SSH1
- case 1:
- if ((key = sshkey_new(KEY_RSA1)) == NULL) {
- error("%s: sshkey_new failed", __func__);
- return;
- }
- if ((r = sshbuf_get_u32(e->request, &bits)) != 0 ||
- (r = sshbuf_get_bignum1(e->request, key->rsa->e)) != 0 ||
- (r = sshbuf_get_bignum1(e->request, key->rsa->n)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ Identity *id;
- if (bits != sshkey_size(key))
- logit("Warning: identity keysize mismatch: "
- "actual %u, announced %u",
- sshkey_size(key), bits);
- break;
-#endif /* WITH_SSH1 */
- case 2:
- if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if ((r = sshkey_from_blob(blob, blen, &key)) != 0)
- error("%s: sshkey_from_blob failed: %s",
- __func__, ssh_err(r));
- free(blob);
- break;
+ if ((r = sshkey_froms(e->request, &key)) != 0) {
+ error("%s: get key: %s", __func__, ssh_err(r));
+ goto done;
}
- if (key != NULL) {
- Identity *id = lookup_identity(key, version);
- if (id != NULL) {
- /*
- * We have this key. Free the old key. Since we
- * don't want to leave empty slots in the middle of
- * the array, we actually free the key there and move
- * all the entries between the empty slot and the end
- * of the array.
- */
- Idtab *tab = idtab_lookup(version);
- if (tab->nentries < 1)
- fatal("process_remove_identity: "
- "internal error: tab->nentries %d",
- tab->nentries);
- TAILQ_REMOVE(&tab->idlist, id, next);
- free_identity(id);
- tab->nentries--;
- success = 1;
- }
- sshkey_free(key);
+ if ((id = lookup_identity(key)) == NULL) {
+ debug("%s: key not found", __func__);
+ goto done;
}
+ /* We have this key, free it. */
+ if (idtab->nentries < 1)
+ fatal("%s: internal error: nentries %d",
+ __func__, idtab->nentries);
+ TAILQ_REMOVE(&idtab->idlist, id, next);
+ free_identity(id);
+ idtab->nentries--;
+ sshkey_free(key);
+ success = 1;
+ done:
send_status(e, success);
}
static void
-process_remove_all_identities(SocketEntry *e, int version)
+process_remove_all_identities(SocketEntry *e)
{
- Idtab *tab = idtab_lookup(version);
Identity *id;
/* Loop over all identities and clear the keys. */
- for (id = TAILQ_FIRST(&tab->idlist); id;
- id = TAILQ_FIRST(&tab->idlist)) {
- TAILQ_REMOVE(&tab->idlist, id, next);
+ for (id = TAILQ_FIRST(&idtab->idlist); id;
+ id = TAILQ_FIRST(&idtab->idlist)) {
+ TAILQ_REMOVE(&idtab->idlist, id, next);
free_identity(id);
}
/* Mark that there are no identities. */
- tab->nentries = 0;
+ idtab->nentries = 0;
/* Send success. */
send_status(e, 1);
@@ -511,24 +403,19 @@ reaper(void)
{
time_t deadline = 0, now = monotime();
Identity *id, *nxt;
- int version;
- Idtab *tab;
-
- for (version = 1; version < 3; version++) {
- tab = idtab_lookup(version);
- for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
- nxt = TAILQ_NEXT(id, next);
- if (id->death == 0)
- continue;
- if (now >= id->death) {
- debug("expiring key '%s'", id->comment);
- TAILQ_REMOVE(&tab->idlist, id, next);
- free_identity(id);
- tab->nentries--;
- } else
- deadline = (deadline == 0) ? id->death :
- MIN(deadline, id->death);
- }
+
+ for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) {
+ nxt = TAILQ_NEXT(id, next);
+ if (id->death == 0)
+ continue;
+ if (now >= id->death) {
+ debug("expiring key '%s'", id->comment);
+ TAILQ_REMOVE(&idtab->idlist, id, next);
+ free_identity(id);
+ idtab->nentries--;
+ } else
+ deadline = (deadline == 0) ? id->death :
+ MINIMUM(deadline, id->death);
}
if (deadline == 0 || deadline <= now)
return 0;
@@ -536,79 +423,25 @@ reaper(void)
return (deadline - now);
}
-/*
- * XXX this and the corresponding serialisation function probably belongs
- * in key.c
- */
-#ifdef WITH_SSH1
-static int
-agent_decode_rsa1(struct sshbuf *m, struct sshkey **kp)
-{
- struct sshkey *k = NULL;
- int r = SSH_ERR_INTERNAL_ERROR;
-
- *kp = NULL;
- if ((k = sshkey_new_private(KEY_RSA1)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
-
- if ((r = sshbuf_get_u32(m, NULL)) != 0 || /* ignored */
- (r = sshbuf_get_bignum1(m, k->rsa->n)) != 0 ||
- (r = sshbuf_get_bignum1(m, k->rsa->e)) != 0 ||
- (r = sshbuf_get_bignum1(m, k->rsa->d)) != 0 ||
- (r = sshbuf_get_bignum1(m, k->rsa->iqmp)) != 0 ||
- /* SSH1 and SSL have p and q swapped */
- (r = sshbuf_get_bignum1(m, k->rsa->q)) != 0 || /* p */
- (r = sshbuf_get_bignum1(m, k->rsa->p)) != 0) /* q */
- goto out;
-
- /* Generate additional parameters */
- if ((r = rsa_generate_additional_parameters(k->rsa)) != 0)
- goto out;
- /* enable blinding */
- if (RSA_blinding_on(k->rsa, NULL) != 1) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
-
- r = 0; /* success */
- out:
- if (r == 0)
- *kp = k;
- else
- sshkey_free(k);
- return r;
-}
-#endif /* WITH_SSH1 */
-
static void
-process_add_identity(SocketEntry *e, int version)
+process_add_identity(SocketEntry *e)
{
- Idtab *tab = idtab_lookup(version);
Identity *id;
int success = 0, confirm = 0;
- u_int seconds;
- char *comment = NULL;
+ 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;
- switch (version) {
-#ifdef WITH_SSH1
- case 1:
- r = agent_decode_rsa1(e->request, &k);
- break;
-#endif /* WITH_SSH1 */
- case 2:
- r = sshkey_private_deserialize(e->request, &k);
- break;
- }
- if (r != 0 || k == NULL ||
+ if ((r = sshkey_private_deserialize(e->request, &k)) != 0 ||
+ k == NULL ||
(r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) {
error("%s: decode private key: %s", __func__, ssh_err(r));
goto err;
}
-
while (sshbuf_len(e->request)) {
if ((r = sshbuf_get_u8(e->request, &ctype)) != 0) {
error("%s: buffer error: %s", __func__, ssh_err(r));
@@ -626,32 +459,115 @@ process_add_identity(SocketEntry *e, int version)
case SSH_AGENT_CONSTRAIN_CONFIRM:
confirm = 1;
break;
+ case SSH_AGENT_CONSTRAIN_MAXSIGN:
+ if ((r = sshbuf_get_u32(e->request, &maxsign)) != 0) {
+ error("%s: bad maxsign constraint: %s",
+ __func__, ssh_err(r));
+ goto err;
+ }
+ if ((r = sshkey_enable_maxsign(k, maxsign)) != 0) {
+ error("%s: cannot enable maxsign: %s",
+ __func__, ssh_err(r));
+ goto err;
+ }
+ break;
+ 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);
+ 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;
}
}
+ 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;
+ }
+ if (strcasecmp(sk_provider, "internal") == 0) {
+ debug("%s: internal provider", __func__);
+ } else {
+ if (realpath(sk_provider, canonical_provider) == NULL) {
+ verbose("failed provider \"%.100s\": "
+ "realpath: %s", sk_provider,
+ strerror(errno));
+ free(sk_provider);
+ goto send;
+ }
+ free(sk_provider);
+ sk_provider = xstrdup(canonical_provider);
+ if (match_pattern_list(sk_provider,
+ provider_whitelist, 0) != 1) {
+ error("Refusing add key: "
+ "provider %s not whitelisted", sk_provider);
+ free(sk_provider);
+ goto send;
+ }
+ }
+ }
+ if ((r = sshkey_shield_private(k)) != 0) {
+ error("%s: shield private key: %s", __func__, ssh_err(r));
+ goto err;
+ }
success = 1;
if (lifetime && !death)
death = monotime() + lifetime;
- if ((id = lookup_identity(k, version)) == NULL) {
+ if ((id = lookup_identity(k)) == NULL) {
id = xcalloc(1, sizeof(Identity));
- id->key = k;
- TAILQ_INSERT_TAIL(&tab->idlist, id, next);
+ TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
/* Increment the number of identities. */
- tab->nentries++;
+ idtab->nentries++;
} else {
- sshkey_free(k);
+ /* key state might have been updated */
+ sshkey_free(id->key);
free(id->comment);
+ free(id->sk_provider);
}
+ id->key = k;
id->comment = comment;
id->death = death;
id->confirm = confirm;
+ id->sk_provider = sk_provider;
+
+ 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);
+ free(fp);
send:
send_status(e, success);
}
@@ -660,39 +576,63 @@ send:
static void
process_lock_agent(SocketEntry *e, int lock)
{
- int r, success = 0;
+ int r, success = 0, delay;
char *passwd;
+ u_char passwdhash[LOCK_SIZE];
+ static u_int fail_count = 0;
+ size_t pwlen;
- if ((r = sshbuf_get_cstring(e->request, &passwd, NULL)) != 0)
+ /*
+ * This is deliberately fatal: the user has requested that we lock,
+ * but we can't parse their request properly. The only safe thing to
+ * do is abort.
+ */
+ if ((r = sshbuf_get_cstring(e->request, &passwd, &pwlen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (locked && !lock && strcmp(passwd, lock_passwd) == 0) {
- locked = 0;
- explicit_bzero(lock_passwd, strlen(lock_passwd));
- free(lock_passwd);
- lock_passwd = NULL;
- success = 1;
+ if (pwlen == 0) {
+ debug("empty password not supported");
+ } else if (locked && !lock) {
+ if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt),
+ passwdhash, sizeof(passwdhash), LOCK_ROUNDS) < 0)
+ fatal("bcrypt_pbkdf");
+ if (timingsafe_bcmp(passwdhash, lock_pwhash, LOCK_SIZE) == 0) {
+ debug("agent unlocked");
+ locked = 0;
+ fail_count = 0;
+ explicit_bzero(lock_pwhash, sizeof(lock_pwhash));
+ success = 1;
+ } else {
+ /* delay in 0.1s increments up to 10s */
+ if (fail_count < 100)
+ fail_count++;
+ delay = 100000 * fail_count;
+ debug("unlock failed, delaying %0.1lf seconds",
+ (double)delay/1000000);
+ usleep(delay);
+ }
+ explicit_bzero(passwdhash, sizeof(passwdhash));
} else if (!locked && lock) {
+ debug("agent locked");
locked = 1;
- lock_passwd = xstrdup(passwd);
+ arc4random_buf(lock_salt, sizeof(lock_salt));
+ if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt),
+ lock_pwhash, sizeof(lock_pwhash), LOCK_ROUNDS) < 0)
+ fatal("bcrypt_pbkdf");
success = 1;
}
- explicit_bzero(passwd, strlen(passwd));
- free(passwd);
+ freezero(passwd, pwlen);
send_status(e, success);
}
static void
-no_identities(SocketEntry *e, u_int type)
+no_identities(SocketEntry *e)
{
struct sshbuf *msg;
int r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- if ((r = sshbuf_put_u8(msg,
- (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ?
- SSH_AGENT_RSA_IDENTITIES_ANSWER :
- SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
+ 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));
@@ -703,100 +643,125 @@ no_identities(SocketEntry *e, u_int type)
static void
process_add_smartcard_key(SocketEntry *e)
{
- char *provider = NULL, *pin;
- int r, i, version, count = 0, success = 0, confirm = 0;
+ char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
+ char **comments = NULL;
+ int r, i, count = 0, success = 0, confirm = 0;
u_int seconds;
time_t death = 0;
u_char type;
struct sshkey **keys = NULL, *k;
Identity *id;
- Idtab *tab;
if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
- (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
+ error("%s: buffer error: %s", __func__, ssh_err(r));
+ goto send;
+ }
while (sshbuf_len(e->request)) {
- if ((r = sshbuf_get_u8(e->request, &type)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ 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)
- fatal("%s: buffer error: %s",
+ 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("process_add_smartcard_key: "
- "Unknown constraint type %d", type);
+ error("%s: Unknown constraint type %d", __func__, type);
goto send;
}
}
+ if (realpath(provider, canonical_provider) == NULL) {
+ verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
+ provider, strerror(errno));
+ goto send;
+ }
+ if (match_pattern_list(canonical_provider, provider_whitelist, 0) != 1) {
+ verbose("refusing PKCS#11 add of \"%.100s\": "
+ "provider not whitelisted", canonical_provider);
+ goto send;
+ }
+ debug("%s: add %.100s", __func__, canonical_provider);
if (lifetime && !death)
death = monotime() + lifetime;
- count = pkcs11_add_provider(provider, pin, &keys);
+ count = pkcs11_add_provider(canonical_provider, pin, &keys, &comments);
for (i = 0; i < count; i++) {
k = keys[i];
- version = k->type == KEY_RSA1 ? 1 : 2;
- tab = idtab_lookup(version);
- if (lookup_identity(k, version) == NULL) {
+ if (lookup_identity(k) == NULL) {
id = xcalloc(1, sizeof(Identity));
id->key = k;
- id->provider = xstrdup(provider);
- id->comment = xstrdup(provider); /* XXX */
+ keys[i] = NULL; /* transferred */
+ id->provider = xstrdup(canonical_provider);
+ if (*comments[i] != '\0') {
+ id->comment = comments[i];
+ comments[i] = NULL; /* transferred */
+ } else {
+ id->comment = xstrdup(canonical_provider);
+ }
id->death = death;
id->confirm = confirm;
- TAILQ_INSERT_TAIL(&tab->idlist, id, next);
- tab->nentries++;
+ TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
+ idtab->nentries++;
success = 1;
- } else {
- sshkey_free(k);
}
- keys[i] = NULL;
+ sshkey_free(keys[i]);
+ free(comments[i]);
}
send:
free(pin);
free(provider);
free(keys);
+ free(comments);
send_status(e, success);
}
static void
process_remove_smartcard_key(SocketEntry *e)
{
- char *provider = NULL, *pin = NULL;
- int r, version, success = 0;
+ char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
+ int r, success = 0;
Identity *id, *nxt;
- Idtab *tab;
if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
- (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
+ error("%s: buffer error: %s", __func__, ssh_err(r));
+ goto send;
+ }
free(pin);
- for (version = 1; version < 3; version++) {
- tab = idtab_lookup(version);
- for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
- nxt = TAILQ_NEXT(id, next);
- /* Skip file--based keys */
- if (id->provider == NULL)
- continue;
- if (!strcmp(provider, id->provider)) {
- TAILQ_REMOVE(&tab->idlist, id, next);
- free_identity(id);
- tab->nentries--;
- }
+ if (realpath(provider, canonical_provider) == NULL) {
+ verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
+ provider, strerror(errno));
+ goto send;
+ }
+
+ debug("%s: remove %.100s", __func__, canonical_provider);
+ for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) {
+ nxt = TAILQ_NEXT(id, next);
+ /* Skip file--based keys */
+ if (id->provider == NULL)
+ continue;
+ if (!strcmp(canonical_provider, id->provider)) {
+ TAILQ_REMOVE(&idtab->idlist, id, next);
+ free_identity(id);
+ idtab->nentries--;
}
}
- if (pkcs11_del_provider(provider) == 0)
+ if (pkcs11_del_provider(canonical_provider) == 0)
success = 1;
else
- error("process_remove_smartcard_key:"
- " pkcs11_del_provider failed");
+ error("%s: pkcs11_del_provider failed", __func__);
+send:
free(provider);
send_status(e, success);
}
@@ -804,88 +769,86 @@ process_remove_smartcard_key(SocketEntry *e)
/* dispatch incoming messages */
-static void
-process_message(SocketEntry *e)
+static int
+process_message(u_int socknum)
{
u_int msg_len;
u_char type;
const u_char *cp;
int r;
+ SocketEntry *e;
+
+ if (socknum >= sockets_alloc) {
+ fatal("%s: socket number %u >= allocated %u",
+ __func__, socknum, sockets_alloc);
+ }
+ e = &sockets[socknum];
if (sshbuf_len(e->input) < 5)
- return; /* Incomplete message. */
+ return 0; /* Incomplete message header. */
cp = sshbuf_ptr(e->input);
msg_len = PEEK_U32(cp);
- if (msg_len > 256 * 1024) {
- close_socket(e);
- return;
+ if (msg_len > AGENT_MAX_LEN) {
+ debug("%s: socket %u (fd=%d) message too long %u > %u",
+ __func__, socknum, e->fd, msg_len, AGENT_MAX_LEN);
+ return -1;
}
if (sshbuf_len(e->input) < msg_len + 4)
- return;
+ return 0; /* Incomplete message body. */
/* move the current input to e->request */
sshbuf_reset(e->request);
if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 ||
- (r = sshbuf_get_u8(e->request, &type)) != 0)
+ (r = sshbuf_get_u8(e->request, &type)) != 0) {
+ if (r == SSH_ERR_MESSAGE_INCOMPLETE ||
+ r == SSH_ERR_STRING_TOO_LARGE) {
+ debug("%s: buffer error: %s", __func__, ssh_err(r));
+ return -1;
+ }
fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ }
+
+ debug("%s: socket %u (fd=%d) type %d", __func__, socknum, e->fd, type);
- /* check wheter agent is locked */
+ /* check whether agent is locked */
if (locked && type != SSH_AGENTC_UNLOCK) {
sshbuf_reset(e->request);
switch (type) {
- case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
case SSH2_AGENTC_REQUEST_IDENTITIES:
/* send empty lists */
- no_identities(e, type);
+ no_identities(e);
break;
default:
/* send a fail message for all other request types */
send_status(e, 0);
}
- return;
+ return 0;
}
- debug("type %d", type);
switch (type) {
case SSH_AGENTC_LOCK:
case SSH_AGENTC_UNLOCK:
process_lock_agent(e, type == SSH_AGENTC_LOCK);
break;
-#ifdef WITH_SSH1
- /* ssh1 */
- case SSH_AGENTC_RSA_CHALLENGE:
- process_authentication_challenge1(e);
- break;
- case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
- process_request_identities(e, 1);
- break;
- case SSH_AGENTC_ADD_RSA_IDENTITY:
- case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED:
- process_add_identity(e, 1);
- break;
- case SSH_AGENTC_REMOVE_RSA_IDENTITY:
- process_remove_identity(e, 1);
- break;
-#endif
case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
- process_remove_all_identities(e, 1); /* safe for !WITH_SSH1 */
+ process_remove_all_identities(e); /* safe for !WITH_SSH1 */
break;
/* ssh2 */
case SSH2_AGENTC_SIGN_REQUEST:
process_sign_request2(e);
break;
case SSH2_AGENTC_REQUEST_IDENTITIES:
- process_request_identities(e, 2);
+ process_request_identities(e);
break;
case SSH2_AGENTC_ADD_IDENTITY:
case SSH2_AGENTC_ADD_ID_CONSTRAINED:
- process_add_identity(e, 2);
+ process_add_identity(e);
break;
case SSH2_AGENTC_REMOVE_IDENTITY:
- process_remove_identity(e, 2);
+ process_remove_identity(e);
break;
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
- process_remove_all_identities(e, 2);
+ process_remove_all_identities(e);
break;
#ifdef ENABLE_PKCS11
case SSH_AGENTC_ADD_SMARTCARD_KEY:
@@ -903,6 +866,7 @@ process_message(SocketEntry *e)
send_status(e, 0);
break;
}
+ return 0;
}
static void
@@ -929,7 +893,7 @@ new_socket(sock_type type, int fd)
}
old_alloc = sockets_alloc;
new_alloc = sockets_alloc + 10;
- sockets = xrealloc(sockets, new_alloc, sizeof(sockets[0]));
+ sockets = xreallocarray(sockets, new_alloc, sizeof(sockets[0]));
for (i = old_alloc; i < new_alloc; i++)
sockets[i].type = AUTH_UNUSED;
sockets_alloc = new_alloc;
@@ -944,19 +908,153 @@ new_socket(sock_type type, int fd)
}
static int
-prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
- struct timeval **tvpp)
+handle_socket_read(u_int socknum)
{
- u_int i, sz;
- int n = 0;
- static struct timeval tv;
+ struct sockaddr_un sunaddr;
+ socklen_t slen;
+ uid_t euid;
+ gid_t egid;
+ int fd;
+
+ slen = sizeof(sunaddr);
+ fd = accept(sockets[socknum].fd, (struct sockaddr *)&sunaddr, &slen);
+ if (fd == -1) {
+ error("accept from AUTH_SOCKET: %s", strerror(errno));
+ return -1;
+ }
+ if (getpeereid(fd, &euid, &egid) == -1) {
+ error("getpeereid %d failed: %s", fd, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ if ((euid != 0) && (getuid() != euid)) {
+ error("uid mismatch: peer euid %u != uid %u",
+ (u_int) euid, (u_int) getuid());
+ close(fd);
+ return -1;
+ }
+ new_socket(AUTH_CONNECTION, fd);
+ return 0;
+}
+
+static int
+handle_conn_read(u_int socknum)
+{
+ char buf[AGENT_RBUF_LEN];
+ ssize_t len;
+ int r;
+
+ if ((len = read(sockets[socknum].fd, buf, sizeof(buf))) <= 0) {
+ if (len == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ return 0;
+ error("%s: read error on socket %u (fd %d): %s",
+ __func__, socknum, sockets[socknum].fd,
+ strerror(errno));
+ }
+ return -1;
+ }
+ if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ explicit_bzero(buf, sizeof(buf));
+ process_message(socknum);
+ return 0;
+}
+
+static int
+handle_conn_write(u_int socknum)
+{
+ ssize_t len;
+ int r;
+
+ if (sshbuf_len(sockets[socknum].output) == 0)
+ return 0; /* shouldn't happen */
+ if ((len = write(sockets[socknum].fd,
+ sshbuf_ptr(sockets[socknum].output),
+ sshbuf_len(sockets[socknum].output))) <= 0) {
+ if (len == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ return 0;
+ error("%s: read error on socket %u (fd %d): %s",
+ __func__, socknum, sockets[socknum].fd,
+ strerror(errno));
+ }
+ return -1;
+ }
+ if ((r = sshbuf_consume(sockets[socknum].output, len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ return 0;
+}
+
+static void
+after_poll(struct pollfd *pfd, size_t npfd, u_int maxfds)
+{
+ size_t i;
+ u_int socknum, activefds = npfd;
+
+ for (i = 0; i < npfd; i++) {
+ if (pfd[i].revents == 0)
+ continue;
+ /* Find sockets entry */
+ for (socknum = 0; socknum < sockets_alloc; socknum++) {
+ if (sockets[socknum].type != AUTH_SOCKET &&
+ sockets[socknum].type != AUTH_CONNECTION)
+ continue;
+ if (pfd[i].fd == sockets[socknum].fd)
+ break;
+ }
+ if (socknum >= sockets_alloc) {
+ error("%s: no socket for fd %d", __func__, pfd[i].fd);
+ continue;
+ }
+ /* Process events */
+ switch (sockets[socknum].type) {
+ case AUTH_SOCKET:
+ if ((pfd[i].revents & (POLLIN|POLLERR)) == 0)
+ break;
+ if (npfd > maxfds) {
+ debug3("out of fds (active %u >= limit %u); "
+ "skipping accept", activefds, maxfds);
+ break;
+ }
+ if (handle_socket_read(socknum) == 0)
+ activefds++;
+ break;
+ case AUTH_CONNECTION:
+ if ((pfd[i].revents & (POLLIN|POLLERR)) != 0 &&
+ handle_conn_read(socknum) != 0) {
+ goto close_sock;
+ }
+ if ((pfd[i].revents & (POLLOUT|POLLHUP)) != 0 &&
+ handle_conn_write(socknum) != 0) {
+ close_sock:
+ if (activefds == 0)
+ fatal("activefds == 0 at close_sock");
+ close_socket(&sockets[socknum]);
+ activefds--;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static int
+prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp, u_int maxfds)
+{
+ struct pollfd *pfd = *pfdp;
+ size_t i, j, npfd = 0;
time_t deadline;
+ int r;
+ /* Count active sockets */
for (i = 0; i < sockets_alloc; i++) {
switch (sockets[i].type) {
case AUTH_SOCKET:
case AUTH_CONNECTION:
- n = MAX(n, sockets[i].fd);
+ npfd++;
break;
case AUTH_UNUSED:
break;
@@ -965,28 +1063,44 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
break;
}
}
+ if (npfd != *npfdp &&
+ (pfd = recallocarray(pfd, *npfdp, npfd, sizeof(*pfd))) == NULL)
+ fatal("%s: recallocarray failed", __func__);
+ *pfdp = pfd;
+ *npfdp = npfd;
- sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
- if (*fdrp == NULL || sz > *nallocp) {
- free(*fdrp);
- free(*fdwp);
- *fdrp = xmalloc(sz);
- *fdwp = xmalloc(sz);
- *nallocp = sz;
- }
- if (n < *fdl)
- debug("XXX shrink: %d < %d", n, *fdl);
- *fdl = n;
- memset(*fdrp, 0, sz);
- memset(*fdwp, 0, sz);
-
- for (i = 0; i < sockets_alloc; i++) {
+ for (i = j = 0; i < sockets_alloc; i++) {
switch (sockets[i].type) {
case AUTH_SOCKET:
+ if (npfd > maxfds) {
+ debug3("out of fds (active %zu >= limit %u); "
+ "skipping arming listener", npfd, maxfds);
+ break;
+ }
+ pfd[j].fd = sockets[i].fd;
+ pfd[j].revents = 0;
+ pfd[j].events = POLLIN;
+ j++;
+ break;
case AUTH_CONNECTION:
- FD_SET(sockets[i].fd, *fdrp);
+ pfd[j].fd = sockets[i].fd;
+ pfd[j].revents = 0;
+ /*
+ * Only prepare to read if we can handle a full-size
+ * input read buffer and enqueue a max size reply..
+ */
+ if ((r = sshbuf_check_reserve(sockets[i].input,
+ AGENT_RBUF_LEN)) == 0 &&
+ (r = sshbuf_check_reserve(sockets[i].output,
+ AGENT_MAX_LEN)) == 0)
+ pfd[j].events = POLLIN;
+ else if (r != SSH_ERR_NO_BUFFER_SPACE) {
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
+ }
if (sshbuf_len(sockets[i].output) > 0)
- FD_SET(sockets[i].fd, *fdwp);
+ pfd[j].events |= POLLOUT;
+ j++;
break;
default:
break;
@@ -995,101 +1109,19 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
deadline = reaper();
if (parent_alive_interval != 0)
deadline = (deadline == 0) ? parent_alive_interval :
- MIN(deadline, parent_alive_interval);
+ MINIMUM(deadline, parent_alive_interval);
if (deadline == 0) {
- *tvpp = NULL;
+ *timeoutp = -1; /* INFTIM */
} else {
- tv.tv_sec = deadline;
- tv.tv_usec = 0;
- *tvpp = &tv;
+ if (deadline > INT_MAX / 1000)
+ *timeoutp = INT_MAX / 1000;
+ else
+ *timeoutp = deadline * 1000;
}
return (1);
}
static void
-after_select(fd_set *readset, fd_set *writeset)
-{
- struct sockaddr_un sunaddr;
- socklen_t slen;
- char buf[1024];
- int len, sock, r;
- u_int i, orig_alloc;
- uid_t euid;
- gid_t egid;
-
- for (i = 0, orig_alloc = sockets_alloc; i < orig_alloc; i++)
- switch (sockets[i].type) {
- case AUTH_UNUSED:
- break;
- case AUTH_SOCKET:
- if (FD_ISSET(sockets[i].fd, readset)) {
- slen = sizeof(sunaddr);
- sock = accept(sockets[i].fd,
- (struct sockaddr *)&sunaddr, &slen);
- if (sock < 0) {
- error("accept from AUTH_SOCKET: %s",
- strerror(errno));
- break;
- }
- if (getpeereid(sock, &euid, &egid) < 0) {
- error("getpeereid %d failed: %s",
- sock, strerror(errno));
- close(sock);
- break;
- }
- if ((euid != 0) && (getuid() != euid)) {
- error("uid mismatch: "
- "peer euid %u != uid %u",
- (u_int) euid, (u_int) getuid());
- close(sock);
- break;
- }
- new_socket(AUTH_CONNECTION, sock);
- }
- break;
- case AUTH_CONNECTION:
- if (sshbuf_len(sockets[i].output) > 0 &&
- FD_ISSET(sockets[i].fd, writeset)) {
- len = write(sockets[i].fd,
- sshbuf_ptr(sockets[i].output),
- sshbuf_len(sockets[i].output));
- if (len == -1 && (errno == EAGAIN ||
- errno == EWOULDBLOCK ||
- errno == EINTR))
- continue;
- if (len <= 0) {
- close_socket(&sockets[i]);
- break;
- }
- if ((r = sshbuf_consume(sockets[i].output,
- len)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
- }
- if (FD_ISSET(sockets[i].fd, readset)) {
- len = read(sockets[i].fd, buf, sizeof(buf));
- if (len == -1 && (errno == EAGAIN ||
- errno == EWOULDBLOCK ||
- errno == EINTR))
- continue;
- if (len <= 0) {
- close_socket(&sockets[i]);
- break;
- }
- if ((r = sshbuf_put(sockets[i].input,
- buf, len)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
- explicit_bzero(buf, sizeof(buf));
- process_message(&sockets[i]);
- }
- break;
- default:
- fatal("Unknown type %d", sockets[i].type);
- }
-}
-
-static void
cleanup_socket(void)
{
if (cleanup_pid != 0 && getpid() != cleanup_pid)
@@ -1137,8 +1169,8 @@ static void
usage(void)
{
fprintf(stderr,
- "usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-E fingerprint_hash]\n"
- " [-t life] [command [arg ...]]\n"
+ "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n"
+ " [-P provider_whitelist] [-t life] [command [arg ...]]\n"
" ssh-agent [-c | -s] -k\n");
exit(1);
}
@@ -1146,11 +1178,9 @@ usage(void)
int
main(int ac, char **av)
{
- int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0;
+ int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0;
int sock, fd, ch, result, saved_errno;
- u_int nalloc;
char *shell, *format, *pidstr, *agentsocket = NULL;
- fd_set *readsetp = NULL, *writesetp = NULL;
#ifdef HAVE_SETRLIMIT
struct rlimit rlim;
#endif
@@ -1158,9 +1188,12 @@ main(int ac, char **av)
extern char *optarg;
pid_t pid;
char pidstrbuf[1 + 3 * sizeof pid];
- struct timeval *tvp = NULL;
size_t len;
mode_t prev_mask;
+ int timeout = -1; /* INFTIM */
+ struct pollfd *pfd = NULL;
+ size_t npfd = 0;
+ u_int maxfds;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@@ -1169,19 +1202,17 @@ main(int ac, char **av)
setegid(getgid());
setgid(getgid());
-#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
- /* Disable ptrace on Linux without sgid bit */
- prctl(PR_SET_DUMPABLE, 0);
-#endif
+ platform_disable_tracing(0); /* strict=no */
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
+#ifdef RLIMIT_NOFILE
+ if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
+ fatal("%s: getrlimit: %s", __progname, strerror(errno));
#endif
__progname = ssh_get_progname(av[0]);
seed_rng();
- while ((ch = getopt(ac, av, "cdksE:a:t:")) != -1) {
+ while ((ch = getopt(ac, av, "cDdksE:a:P:t:")) != -1) {
switch (ch) {
case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg);
@@ -1196,16 +1227,26 @@ main(int ac, char **av)
case 'k':
k_flag++;
break;
+ case 'P':
+ if (provider_whitelist != NULL)
+ fatal("-P option already specified");
+ provider_whitelist = xstrdup(optarg);
+ break;
case 's':
if (c_flag)
usage();
s_flag++;
break;
case 'd':
- if (d_flag)
+ if (d_flag || D_flag)
usage();
d_flag++;
break;
+ case 'D':
+ if (d_flag || D_flag)
+ usage();
+ D_flag++;
+ break;
case 'a':
agentsocket = optarg;
break;
@@ -1222,9 +1263,12 @@ main(int ac, char **av)
ac -= optind;
av += optind;
- if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
+ 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 (ac == 0 && !c_flag && !s_flag) {
shell = getenv("SHELL");
if (shell != NULL && (len = strlen(shell)) > 2 &&
@@ -1257,6 +1301,18 @@ main(int ac, char **av)
printf("echo Agent pid %ld killed;\n", (long)pid);
exit(0);
}
+
+ /*
+ * Minimum file descriptors:
+ * stdio (3) + listener (1) + syslog (1 maybe) + connection (1) +
+ * a few spare for libc / stack protectors / sanitisers, etc.
+ */
+#define SSH_AGENT_MIN_FDS (3+1+1+1+4)
+ if (rlim.rlim_cur < SSH_AGENT_MIN_FDS)
+ fatal("%s: file descriptor rlimit %lld too low (minimum %u)",
+ __progname, (long long)rlim.rlim_cur, SSH_AGENT_MIN_FDS);
+ maxfds = rlim.rlim_cur - SSH_AGENT_MIN_FDS;
+
parent_pid = getpid();
if (agentsocket == NULL) {
@@ -1291,12 +1347,15 @@ main(int ac, char **av)
* Fork, and have the parent execute the command, if any, or present
* the socket data. The child continues as the authentication agent.
*/
- if (d_flag) {
- log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1);
+ if (D_flag || d_flag) {
+ log_init(__progname,
+ d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO,
+ SYSLOG_FACILITY_AUTH, 1);
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf("echo Agent pid %ld;\n", (long)parent_pid);
+ fflush(stdout);
goto skip;
}
pid = fork();
@@ -1346,7 +1405,7 @@ main(int ac, char **av)
#ifdef HAVE_SETRLIMIT
/* deny core dumps, since memory contains unencrypted private keys */
rlim.rlim_cur = rlim.rlim_max = 0;
- if (setrlimit(RLIMIT_CORE, &rlim) < 0) {
+ if (setrlimit(RLIMIT_CORE, &rlim) == -1) {
error("setrlimit RLIMIT_CORE: %s", strerror(errno));
cleanup_exit(1);
}
@@ -1363,25 +1422,28 @@ skip:
if (ac > 0)
parent_alive_interval = 10;
idtab_init();
- signal(SIGPIPE, SIG_IGN);
- signal(SIGINT, d_flag ? cleanup_handler : SIG_IGN);
- signal(SIGHUP, cleanup_handler);
- signal(SIGTERM, cleanup_handler);
- nalloc = 0;
+ ssh_signal(SIGPIPE, SIG_IGN);
+ ssh_signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN);
+ ssh_signal(SIGHUP, cleanup_handler);
+ ssh_signal(SIGTERM, cleanup_handler);
+
+ if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1)
+ fatal("%s: pledge: %s", __progname, strerror(errno));
+ platform_pledge_agent();
while (1) {
- prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp);
- result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
+ prepare_poll(&pfd, &npfd, &timeout, maxfds);
+ result = poll(pfd, npfd, timeout);
saved_errno = errno;
if (parent_alive_interval != 0)
check_parent_exists();
(void) reaper(); /* remove expired keys */
- if (result < 0) {
+ if (result == -1) {
if (saved_errno == EINTR)
continue;
- fatal("select: %s", strerror(saved_errno));
+ fatal("poll: %s", strerror(saved_errno));
} else if (result > 0)
- after_select(readsetp, writesetp);
+ after_poll(pfd, npfd, maxfds);
}
/* NOTREACHED */
}
diff --git a/ssh-dss.c b/ssh-dss.c
index 8ed19d84..fddc29cc 100644
--- a/ssh-dss.c
+++ b/ssh-dss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-dss.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */
+/* $OpenBSD: ssh-dss.c,v 1.39 2020/02/26 13:40:09 jsg Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -43,6 +43,8 @@
#define SSHKEY_INTERNAL
#include "sshkey.h"
+#include "openbsd-compat/openssl-compat.h"
+
#define INTBLOB_LEN 20
#define SIGBLOB_LEN (2*INTBLOB_LEN)
@@ -51,6 +53,7 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
{
DSA_SIG *sig = NULL;
+ const BIGNUM *sig_r, *sig_s;
u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN];
size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
struct sshbuf *b = NULL;
@@ -76,54 +79,40 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
goto out;
}
- rlen = BN_num_bytes(sig->r);
- slen = BN_num_bytes(sig->s);
+ DSA_SIG_get0(sig, &sig_r, &sig_s);
+ rlen = BN_num_bytes(sig_r);
+ slen = BN_num_bytes(sig_s);
if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
ret = SSH_ERR_INTERNAL_ERROR;
goto out;
}
explicit_bzero(sigblob, SIGBLOB_LEN);
- BN_bn2bin(sig->r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen);
- BN_bn2bin(sig->s, sigblob + SIGBLOB_LEN - slen);
-
- if (compat & SSH_BUG_SIGBLOB) {
- if (sigp != NULL) {
- if ((*sigp = malloc(SIGBLOB_LEN)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(*sigp, sigblob, SIGBLOB_LEN);
- }
- if (lenp != NULL)
- *lenp = SIGBLOB_LEN;
- ret = 0;
- } else {
- /* ietf-drafts */
- if ((b = sshbuf_new()) == NULL) {
+ BN_bn2bin(sig_r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen);
+ BN_bn2bin(sig_s, sigblob + SIGBLOB_LEN - slen);
+
+ if ((b = sshbuf_new()) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 ||
+ (ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 0)
+ goto out;
+
+ len = sshbuf_len(b);
+ if (sigp != NULL) {
+ if ((*sigp = malloc(len)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 ||
- (ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 0)
- goto out;
- len = sshbuf_len(b);
- if (sigp != NULL) {
- if ((*sigp = malloc(len)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(*sigp, sshbuf_ptr(b), len);
- }
- if (lenp != NULL)
- *lenp = len;
- ret = 0;
+ memcpy(*sigp, sshbuf_ptr(b), len);
}
+ if (lenp != NULL)
+ *lenp = len;
+ ret = 0;
out:
explicit_bzero(digest, sizeof(digest));
- if (sig != NULL)
- DSA_SIG_free(sig);
- if (b != NULL)
- sshbuf_free(b);
+ DSA_SIG_free(sig);
+ sshbuf_free(b);
return ret;
}
@@ -133,6 +122,7 @@ ssh_dss_verify(const struct sshkey *key,
const u_char *data, size_t datalen, u_int compat)
{
DSA_SIG *sig = NULL;
+ BIGNUM *sig_r = NULL, *sig_s = NULL;
u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL;
size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
int ret = SSH_ERR_INTERNAL_ERROR;
@@ -140,34 +130,27 @@ ssh_dss_verify(const struct sshkey *key,
char *ktype = NULL;
if (key == NULL || key->dsa == NULL ||
- sshkey_type_plain(key->type) != KEY_DSA)
+ sshkey_type_plain(key->type) != KEY_DSA ||
+ signature == NULL || signaturelen == 0)
return SSH_ERR_INVALID_ARGUMENT;
if (dlen == 0)
return SSH_ERR_INTERNAL_ERROR;
/* fetch signature */
- if (compat & SSH_BUG_SIGBLOB) {
- if ((sigblob = malloc(signaturelen)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- memcpy(sigblob, signature, signaturelen);
- len = signaturelen;
- } else {
- /* ietf-drafts */
- if ((b = sshbuf_from(signature, signaturelen)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
- sshbuf_get_string(b, &sigblob, &len) != 0) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- if (strcmp("ssh-dss", ktype) != 0) {
- ret = SSH_ERR_KEY_TYPE_MISMATCH;
- goto out;
- }
- if (sshbuf_len(b) != 0) {
- ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
- goto out;
- }
+ if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
+ sshbuf_get_string(b, &sigblob, &len) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (strcmp("ssh-dss", ktype) != 0) {
+ ret = SSH_ERR_KEY_TYPE_MISMATCH;
+ goto out;
+ }
+ if (sshbuf_len(b) != 0) {
+ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
+ goto out;
}
if (len != SIGBLOB_LEN) {
@@ -177,16 +160,21 @@ ssh_dss_verify(const struct sshkey *key,
/* parse signature */
if ((sig = DSA_SIG_new()) == NULL ||
- (sig->r = BN_new()) == NULL ||
- (sig->s = BN_new()) == NULL) {
+ (sig_r = BN_new()) == NULL ||
+ (sig_s = BN_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) ||
- (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) {
+ if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig_r) == NULL) ||
+ (BN_bin2bn(sigblob + INTBLOB_LEN, INTBLOB_LEN, sig_s) == NULL)) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
+ if (!DSA_SIG_set0(sig, sig_r, sig_s)) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ sig_r = sig_s = NULL; /* transferred */
/* sha1 the data */
if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
@@ -207,16 +195,13 @@ ssh_dss_verify(const struct sshkey *key,
out:
explicit_bzero(digest, sizeof(digest));
- if (sig != NULL)
- DSA_SIG_free(sig);
- if (b != NULL)
- sshbuf_free(b);
- if (ktype != NULL)
- free(ktype);
- if (sigblob != NULL) {
- explicit_bzero(sigblob, len);
- free(sigblob);
- }
+ DSA_SIG_free(sig);
+ BN_clear_free(sig_r);
+ BN_clear_free(sig_s);
+ sshbuf_free(b);
+ free(ktype);
+ if (sigblob != NULL)
+ freezero(sigblob, len);
return ret;
}
#endif /* WITH_OPENSSL */
diff --git a/ssh-ecdsa-sk.c b/ssh-ecdsa-sk.c
new file mode 100644
index 00000000..981d60d7
--- /dev/null
+++ b/ssh-ecdsa-sk.c
@@ -0,0 +1,209 @@
+/* $OpenBSD: ssh-ecdsa-sk.c,v 1.5 2019/11/26 03:04:27 djm Exp $ */
+/*
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ * Copyright (c) 2010 Damien Miller. All rights reserved.
+ * Copyright (c) 2019 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* #define DEBUG_SK 1 */
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#ifdef WITH_OPENSSL
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+#endif
+
+#include <string.h>
+#include <stdio.h> /* needed for DEBUG_SK only */
+
+#include "openbsd-compat/openssl-compat.h"
+
+#include "sshbuf.h"
+#include "ssherr.h"
+#include "digest.h"
+#define SSHKEY_INTERNAL
+#include "sshkey.h"
+
+/* 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)
+{
+#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;
+ struct sshbuf *b = NULL, *sigbuf = NULL, *original_signed = NULL;
+ char *ktype = NULL;
+ struct sshkey_sig_details *details = NULL;
+#ifdef DEBUG_SK
+ char *tmp = NULL;
+#endif
+
+ if (detailsp != NULL)
+ *detailsp = NULL;
+ if (key == NULL || key->ecdsa == NULL ||
+ sshkey_type_plain(key->type) != KEY_ECDSA_SK ||
+ signature == NULL || signaturelen == 0)
+ return SSH_ERR_INVALID_ARGUMENT;
+
+ if (key->ecdsa_nid != NID_X9_62_prime256v1)
+ return SSH_ERR_INTERNAL_ERROR;
+
+ /* fetch signature */
+ if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
+ 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 (sshbuf_len(b) != 0) {
+ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
+ goto out;
+ }
+
+ /* parse signature */
+ if (sshbuf_get_bignum2(sigbuf, &sig_r) != 0 ||
+ sshbuf_get_bignum2(sigbuf, &sig_s) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if ((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;
+ }
+#ifdef DEBUG_SK
+ fprintf(stderr, "%s: data: (len %zu)\n", __func__, datalen);
+ /* sshbuf_dump_data(data, datalen, stderr); */
+ fprintf(stderr, "%s: sig_r: %s\n", __func__, (tmp = BN_bn2hex(sig_r)));
+ free(tmp);
+ fprintf(stderr, "%s: sig_s: %s\n", __func__, (tmp = BN_bn2hex(sig_s)));
+ free(tmp);
+ fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n",
+ __func__, sig_flags, sig_counter);
+#endif
+ sig_r = sig_s = NULL; /* transferred */
+
+ if (sshbuf_len(sigbuf) != 0) {
+ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
+ goto out;
+ }
+
+ /* 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,
+ msghash, sizeof(msghash))) != 0)
+ goto out;
+ /* Application value is hashed before signature */
+ if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, key->sk_application,
+ strlen(key->sk_application), apphash, sizeof(apphash))) != 0)
+ goto out;
+#ifdef DEBUG_SK
+ fprintf(stderr, "%s: hashed application:\n", __func__);
+ sshbuf_dump_data(apphash, sizeof(apphash), stderr);
+ fprintf(stderr, "%s: hashed message:\n", __func__);
+ sshbuf_dump_data(msghash, sizeof(msghash), stderr);
+#endif
+ if ((ret = sshbuf_put(original_signed,
+ apphash, sizeof(apphash))) != 0 ||
+ (ret = sshbuf_put_u8(original_signed, sig_flags)) != 0 ||
+ (ret = sshbuf_put_u32(original_signed, sig_counter)) != 0 ||
+ (ret = sshbuf_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
+ fprintf(stderr, "%s: signed buf:\n", __func__);
+ sshbuf_dump(original_signed, stderr);
+ fprintf(stderr, "%s: signed hash:\n", __func__);
+ sshbuf_dump_data(sighash, sizeof(sighash), stderr);
+#endif
+
+ /* Verify it */
+ switch (ECDSA_do_verify(sighash, sizeof(sighash), sig, key->ecdsa)) {
+ case 1:
+ ret = 0;
+ break;
+ case 0:
+ ret = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ default:
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ /* success */
+ if (detailsp != NULL) {
+ *detailsp = details;
+ details = NULL;
+ }
+ out:
+ explicit_bzero(&sig_flags, sizeof(sig_flags));
+ explicit_bzero(&sig_counter, sizeof(sig_counter));
+ explicit_bzero(msghash, sizeof(msghash));
+ explicit_bzero(sighash, sizeof(msghash));
+ explicit_bzero(apphash, sizeof(apphash));
+ sshkey_sig_details_free(details);
+ sshbuf_free(original_signed);
+ sshbuf_free(sigbuf);
+ sshbuf_free(b);
+ ECDSA_SIG_free(sig);
+ BN_clear_free(sig_r);
+ BN_clear_free(sig_s);
+ free(ktype);
+ return ret;
+#else
+ return SSH_ERR_INTERNAL_ERROR;
+#endif
+}
diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c
index 2c76f8b4..599c7199 100644
--- a/ssh-ecdsa.c
+++ b/ssh-ecdsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa.c,v 1.11 2014/06/24 01:13:21 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa.c,v 1.16 2019/01/21 09:54:11 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -43,12 +43,15 @@
#define SSHKEY_INTERNAL
#include "sshkey.h"
+#include "openbsd-compat/openssl-compat.h"
+
/* ARGSUSED */
int
ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
{
ECDSA_SIG *sig = NULL;
+ const BIGNUM *sig_r, *sig_s;
int hash_alg;
u_char digest[SSH_DIGEST_MAX_LENGTH];
size_t len, dlen;
@@ -80,8 +83,9 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((ret = sshbuf_put_bignum2(bb, sig->r)) != 0 ||
- (ret = sshbuf_put_bignum2(bb, sig->s)) != 0)
+ ECDSA_SIG_get0(sig, &sig_r, &sig_s);
+ if ((ret = sshbuf_put_bignum2(bb, sig_r)) != 0 ||
+ (ret = sshbuf_put_bignum2(bb, sig_s)) != 0)
goto out;
if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 ||
(ret = sshbuf_put_stringb(b, bb)) != 0)
@@ -99,12 +103,9 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
ret = 0;
out:
explicit_bzero(digest, sizeof(digest));
- if (b != NULL)
- sshbuf_free(b);
- if (bb != NULL)
- sshbuf_free(bb);
- if (sig != NULL)
- ECDSA_SIG_free(sig);
+ sshbuf_free(b);
+ sshbuf_free(bb);
+ ECDSA_SIG_free(sig);
return ret;
}
@@ -115,6 +116,7 @@ ssh_ecdsa_verify(const struct sshkey *key,
const u_char *data, size_t datalen, u_int compat)
{
ECDSA_SIG *sig = NULL;
+ BIGNUM *sig_r = NULL, *sig_s = NULL;
int hash_alg;
u_char digest[SSH_DIGEST_MAX_LENGTH];
size_t dlen;
@@ -123,7 +125,8 @@ ssh_ecdsa_verify(const struct sshkey *key,
char *ktype = NULL;
if (key == NULL || key->ecdsa == NULL ||
- sshkey_type_plain(key->type) != KEY_ECDSA)
+ sshkey_type_plain(key->type) != KEY_ECDSA ||
+ signature == NULL || signaturelen == 0)
return SSH_ERR_INVALID_ARGUMENT;
if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
@@ -148,15 +151,21 @@ ssh_ecdsa_verify(const struct sshkey *key,
}
/* parse signature */
+ if (sshbuf_get_bignum2(sigbuf, &sig_r) != 0 ||
+ sshbuf_get_bignum2(sigbuf, &sig_s) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
if ((sig = ECDSA_SIG_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if (sshbuf_get_bignum2(sigbuf, sig->r) != 0 ||
- sshbuf_get_bignum2(sigbuf, sig->s) != 0) {
- ret = SSH_ERR_INVALID_FORMAT;
+ if (!ECDSA_SIG_set0(sig, sig_r, sig_s)) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
+ sig_r = sig_s = NULL; /* transferred */
+
if (sshbuf_len(sigbuf) != 0) {
ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
goto out;
@@ -179,12 +188,11 @@ ssh_ecdsa_verify(const struct sshkey *key,
out:
explicit_bzero(digest, sizeof(digest));
- if (sigbuf != NULL)
- sshbuf_free(sigbuf);
- if (b != NULL)
- sshbuf_free(b);
- if (sig != NULL)
- ECDSA_SIG_free(sig);
+ sshbuf_free(sigbuf);
+ sshbuf_free(b);
+ ECDSA_SIG_free(sig);
+ BN_clear_free(sig_r);
+ BN_clear_free(sig_s);
free(ktype);
return ret;
}
diff --git a/ssh-ed25519-sk.c b/ssh-ed25519-sk.c
new file mode 100644
index 00000000..f784776d
--- /dev/null
+++ b/ssh-ed25519-sk.c
@@ -0,0 +1,164 @@
+/* $OpenBSD: ssh-ed25519-sk.c,v 1.5 2020/02/26 13:40:09 jsg Exp $ */
+/*
+ * Copyright (c) 2019 Markus Friedl. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* #define DEBUG_SK 1 */
+
+#include "includes.h"
+
+#define SSHKEY_INTERNAL
+#include <sys/types.h>
+#include <limits.h>
+
+#include "crypto_api.h"
+
+#include <string.h>
+#include <stdarg.h>
+
+#include "log.h"
+#include "sshbuf.h"
+#include "sshkey.h"
+#include "ssherr.h"
+#include "ssh.h"
+#include "digest.h"
+
+int
+ssh_ed25519_sk_verify(const struct sshkey *key,
+ const u_char *signature, size_t signaturelen,
+ const u_char *data, size_t datalen, u_int compat,
+ struct sshkey_sig_details **detailsp)
+{
+ struct sshbuf *b = NULL;
+ struct sshbuf *encoded = NULL;
+ char *ktype = NULL;
+ const u_char *sigblob;
+ const u_char *sm;
+ u_char *m = NULL;
+ u_char apphash[32];
+ u_char msghash[32];
+ u_char sig_flags;
+ u_int sig_counter;
+ size_t len;
+ unsigned long long smlen = 0, mlen = 0;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ int ret;
+ struct sshkey_sig_details *details = NULL;
+
+ if (detailsp != NULL)
+ *detailsp = NULL;
+
+ if (key == NULL ||
+ sshkey_type_plain(key->type) != KEY_ED25519_SK ||
+ key->ed25519_pk == NULL ||
+ signature == NULL || signaturelen == 0)
+ return SSH_ERR_INVALID_ARGUMENT;
+
+ if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
+ sshbuf_get_string_direct(b, &sigblob, &len) != 0 ||
+ sshbuf_get_u8(b, &sig_flags) != 0 ||
+ sshbuf_get_u32(b, &sig_counter) != 0) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+#ifdef DEBUG_SK
+ fprintf(stderr, "%s: data:\n", __func__);
+ /* sshbuf_dump_data(data, datalen, stderr); */
+ fprintf(stderr, "%s: sigblob:\n", __func__);
+ sshbuf_dump_data(sigblob, len, stderr);
+ fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n",
+ __func__, sig_flags, sig_counter);
+#endif
+ if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) {
+ r = SSH_ERR_KEY_TYPE_MISMATCH;
+ goto out;
+ }
+ if (sshbuf_len(b) != 0) {
+ r = SSH_ERR_UNEXPECTED_TRAILING_DATA;
+ goto out;
+ }
+ if (len > crypto_sign_ed25519_BYTES) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (ssh_digest_memory(SSH_DIGEST_SHA256, key->sk_application,
+ strlen(key->sk_application), apphash, sizeof(apphash)) != 0 ||
+ ssh_digest_memory(SSH_DIGEST_SHA256, data, datalen,
+ msghash, sizeof(msghash)) != 0) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+#ifdef DEBUG_SK
+ fprintf(stderr, "%s: hashed application:\n", __func__);
+ sshbuf_dump_data(apphash, sizeof(apphash), stderr);
+ fprintf(stderr, "%s: hashed message:\n", __func__);
+ sshbuf_dump_data(msghash, sizeof(msghash), stderr);
+#endif
+ if ((details = calloc(1, sizeof(*details))) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ details->sk_counter = sig_counter;
+ details->sk_flags = sig_flags;
+ if ((encoded = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (sshbuf_put(encoded, sigblob, len) != 0 ||
+ sshbuf_put(encoded, apphash, sizeof(apphash)) != 0 ||
+ sshbuf_put_u8(encoded, sig_flags) != 0 ||
+ sshbuf_put_u32(encoded, sig_counter) != 0 ||
+ sshbuf_put(encoded, msghash, sizeof(msghash)) != 0) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+#ifdef DEBUG_SK
+ fprintf(stderr, "%s: signed buf:\n", __func__);
+ sshbuf_dump(encoded, stderr);
+#endif
+ sm = sshbuf_ptr(encoded);
+ smlen = sshbuf_len(encoded);
+ mlen = smlen;
+ if ((m = malloc(smlen)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen,
+ key->ed25519_pk)) != 0) {
+ debug2("%s: crypto_sign_ed25519_open failed: %d",
+ __func__, ret);
+ }
+ if (ret != 0 || mlen != smlen - len) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ /* XXX compare 'm' and 'sm + len' ? */
+ /* success */
+ r = 0;
+ if (detailsp != NULL) {
+ *detailsp = details;
+ details = NULL;
+ }
+ out:
+ if (m != NULL)
+ freezero(m, smlen); /* NB mlen may be invalid if r != 0 */
+ sshkey_sig_details_free(details);
+ sshbuf_free(b);
+ sshbuf_free(encoded);
+ free(ktype);
+ return r;
+}
diff --git a/ssh-ed25519.c b/ssh-ed25519.c
index b159ff5e..7dee8270 100644
--- a/ssh-ed25519.c
+++ b/ssh-ed25519.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519.c,v 1.6 2015/01/15 21:38:50 markus Exp $ */
+/* $OpenBSD: ssh-ed25519.c,v 1.8 2020/02/26 13:40:09 jsg Exp $ */
/*
* Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
*
@@ -83,10 +83,8 @@ ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
r = 0;
out:
sshbuf_free(b);
- if (sig != NULL) {
- explicit_bzero(sig, slen);
- free(sig);
- }
+ if (sig != NULL)
+ freezero(sig, slen);
return r;
}
@@ -107,7 +105,8 @@ ssh_ed25519_verify(const struct sshkey *key,
if (key == NULL ||
sshkey_type_plain(key->type) != KEY_ED25519 ||
key->ed25519_pk == NULL ||
- datalen >= INT_MAX - crypto_sign_ed25519_BYTES)
+ datalen >= INT_MAX - crypto_sign_ed25519_BYTES ||
+ signature == NULL || signaturelen == 0)
return SSH_ERR_INVALID_ARGUMENT;
if ((b = sshbuf_from(signature, signaturelen)) == NULL)
@@ -152,14 +151,10 @@ ssh_ed25519_verify(const struct sshkey *key,
/* success */
r = 0;
out:
- if (sm != NULL) {
- explicit_bzero(sm, smlen);
- free(sm);
- }
- if (m != NULL) {
- explicit_bzero(m, smlen); /* NB mlen may be invalid if r != 0 */
- free(m);
- }
+ if (sm != NULL)
+ freezero(sm, smlen);
+ if (m != NULL)
+ freezero(m, smlen); /* NB mlen may be invalid if r != 0 */
sshbuf_free(b);
free(ktype);
return r;
diff --git a/ssh-gss.h b/ssh-gss.h
index a99d7f08..36180d07 100644
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-gss.h,v 1.11 2014/02/26 20:28:44 djm Exp $ */
+/* $OpenBSD: ssh-gss.h,v 1.14 2018/07/10 09:13:30 djm Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
*
@@ -107,6 +107,9 @@ ssh_gssapi_mech *ssh_gssapi_get_ctype(Gssctxt *);
void ssh_gssapi_prepare_supported_oids(void);
OM_uint32 ssh_gssapi_test_oid_supported(OM_uint32 *, gss_OID, int *);
+struct sshbuf;
+int ssh_gssapi_get_buffer_desc(struct sshbuf *, gss_buffer_desc *);
+
OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *);
OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int,
gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
@@ -118,7 +121,8 @@ char *ssh_gssapi_last_error(Gssctxt *, OM_uint32 *, OM_uint32 *);
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(Buffer *, const char *, const char *, const char *);
+void ssh_gssapi_buildmic(struct sshbuf *, const char *,
+ const char *, const char *);
int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
/* In the server */
@@ -128,6 +132,7 @@ OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
void ssh_gssapi_do_child(char ***, u_int *);
void ssh_gssapi_cleanup_creds(void);
void ssh_gssapi_storecreds(void);
+const char *ssh_gssapi_displayname(void);
#endif /* GSSAPI */
diff --git a/ssh-keygen.0 b/ssh-keygen.0
deleted file mode 100644
index 784ad032..00000000
--- a/ssh-keygen.0
+++ /dev/null
@@ -1,566 +0,0 @@
-SSH-KEYGEN(1) General Commands Manual SSH-KEYGEN(1)
-
-NAME
- ssh-keygen M-bM-^@M-^S authentication key generation, management and conversion
-
-SYNOPSIS
- ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1]
- [-N new_passphrase] [-C comment] [-f output_keyfile]
- ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]
- ssh-keygen -i [-m key_format] [-f input_keyfile]
- ssh-keygen -e [-m key_format] [-f input_keyfile]
- ssh-keygen -y [-f input_keyfile]
- ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]
- ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]
- ssh-keygen -B [-f input_keyfile]
- ssh-keygen -D pkcs11
- ssh-keygen -F hostname [-f known_hosts_file] [-l]
- ssh-keygen -H [-f known_hosts_file]
- ssh-keygen -R hostname [-f known_hosts_file]
- ssh-keygen -r hostname [-f input_keyfile] [-g]
- ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]
- ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]
- [-j start_line] [-K checkpt] [-W generator]
- ssh-keygen -s ca_key -I certificate_identity [-h] [-n principals]
- [-O option] [-V validity_interval] [-z serial_number] file ...
- ssh-keygen -L [-f input_keyfile]
- ssh-keygen -A
- ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]
- file ...
- ssh-keygen -Q -f krl_file file ...
-
-DESCRIPTION
- ssh-keygen generates, manages and converts authentication keys for
- ssh(1). ssh-keygen can create RSA keys for use by SSH protocol version 1
- and DSA, ECDSA, Ed25519 or RSA keys for use by SSH protocol version 2.
- The type of key to be generated is specified with the -t option. If
- invoked without any arguments, ssh-keygen will generate an RSA key for
- use in SSH protocol 2 connections.
-
- ssh-keygen is also used to generate groups for use in Diffie-Hellman
- group exchange (DH-GEX). See the MODULI GENERATION section for details.
-
- Finally, ssh-keygen can be used to generate and update Key Revocation
- Lists, and to test whether given keys have been revoked by one. See the
- KEY REVOCATION LISTS section for details.
-
- Normally each user wishing to use SSH with public key authentication runs
- this once to create the authentication key in ~/.ssh/identity,
- ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 or ~/.ssh/id_rsa.
- Additionally, the system administrator may use this to generate host
- keys, as seen in /etc/rc.
-
- Normally this program generates the key and asks for a file in which to
- store the private key. The public key is stored in a file with the same
- name but M-bM-^@M-^\.pubM-bM-^@M-^] appended. The program also asks for a passphrase. The
- passphrase may be empty to indicate no passphrase (host keys must have an
- empty passphrase), or it may be a string of arbitrary length. A
- passphrase is similar to a password, except it can be a phrase with a
- series of words, punctuation, numbers, whitespace, or any string of
- characters you want. Good passphrases are 10-30 characters long, are not
- simple sentences or otherwise easily guessable (English prose has only
- 1-2 bits of entropy per character, and provides very bad passphrases),
- and contain a mix of upper and lowercase letters, numbers, and non-
- alphanumeric characters. The passphrase can be changed later by using
- the -p option.
-
- There is no way to recover a lost passphrase. If the passphrase is lost
- or forgotten, a new key must be generated and the corresponding public
- key copied to other machines.
-
- For RSA1 keys, there is also a comment field in the key file that is only
- for convenience to the user to help identify the key. The comment can
- tell what the key is for, or whatever is useful. The comment is
- initialized to M-bM-^@M-^\user@hostM-bM-^@M-^] when the key is created, but can be changed
- using the -c option.
-
- After a key is generated, instructions below detail where the keys should
- be placed to be activated.
-
- The options are as follows:
-
- -A For each of the key types (rsa1, rsa, dsa, ecdsa and ed25519) for
- which host keys do not exist, generate the host keys with the
- default key file path, an empty passphrase, default bits for the
- key type, and default comment. This is used by /etc/rc to
- generate new host keys.
-
- -a rounds
- When saving a new-format private key (i.e. an ed25519 key or any
- SSH protocol 2 key when the -o flag is set), this option
- specifies the number of KDF (key derivation function) rounds
- used. Higher numbers result in slower passphrase verification
- and increased resistance to brute-force password cracking (should
- the keys be stolen).
-
- When screening DH-GEX candidates ( using the -T command). This
- option specifies the number of primality tests to perform.
-
- -B Show the bubblebabble digest of specified private or public key
- file.
-
- -b bits
- Specifies the number of bits in the key to create. For RSA keys,
- the minimum size is 768 bits and the default is 2048 bits.
- Generally, 2048 bits is considered sufficient. DSA keys must be
- exactly 1024 bits as specified by FIPS 186-2. For ECDSA keys,
- the -b flag determines the key length by selecting from one of
- three elliptic curve sizes: 256, 384 or 521 bits. Attempting to
- use bit lengths other than these three values for ECDSA keys will
- fail. Ed25519 keys have a fixed length and the -b flag will be
- ignored.
-
- -C comment
- Provides a new comment.
-
- -c Requests changing the comment in the private and public key
- files. This operation is only supported for RSA1 keys. The
- program will prompt for the file containing the private keys, for
- the passphrase if the key has one, and for the new comment.
-
- -D pkcs11
- Download the RSA public keys provided by the PKCS#11 shared
- library pkcs11. When used in combination with -s, this option
- indicates that a CA key resides in a PKCS#11 token (see the
- CERTIFICATES section for details).
-
- -E fingerprint_hash
- Specifies the hash algorithm used when displaying key
- fingerprints. Valid options are: M-bM-^@M-^\md5M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The
- default is M-bM-^@M-^\sha256M-bM-^@M-^].
-
- -e This option will read a private or public OpenSSH key file and
- print to stdout the key in one of the formats specified by the -m
- option. The default export format is M-bM-^@M-^\RFC4716M-bM-^@M-^]. This option
- allows exporting OpenSSH keys for use by other programs,
- including several commercial SSH implementations.
-
- -F hostname
- Search for the specified hostname in a known_hosts file, listing
- any occurrences found. This option is useful to find hashed host
- names or addresses and may also be used in conjunction with the
- -H option to print found keys in a hashed format.
-
- -f filename
- Specifies the filename of the key file.
-
- -G output_file
- Generate candidate primes for DH-GEX. These primes must be
- screened for safety (using the -T option) before use.
-
- -g Use generic DNS format when printing fingerprint resource records
- using the -r command.
-
- -H Hash a known_hosts file. This replaces all hostnames and
- addresses with hashed representations within the specified file;
- the original content is moved to a file with a .old suffix.
- These hashes may be used normally by ssh and sshd, but they do
- not reveal identifying information should the file's contents be
- disclosed. This option will not modify existing hashed hostnames
- and is therefore safe to use on files that mix hashed and non-
- hashed names.
-
- -h When signing a key, create a host certificate instead of a user
- certificate. Please see the CERTIFICATES section for details.
-
- -I certificate_identity
- Specify the key identity when signing a public key. Please see
- the CERTIFICATES section for details.
-
- -i This option will read an unencrypted private (or public) key file
- in the format specified by the -m option and print an OpenSSH
- compatible private (or public) key to stdout. This option allows
- importing keys from other software, including several commercial
- SSH implementations. The default import format is M-bM-^@M-^\RFC4716M-bM-^@M-^].
-
- -J num_lines
- Exit after screening the specified number of lines while
- performing DH candidate screening using the -T option.
-
- -j start_line
- Start screening at the specified line number while performing DH
- candidate screening using the -T option.
-
- -K checkpt
- Write the last line processed to the file checkpt while
- performing DH candidate screening using the -T option. This will
- be used to skip lines in the input file that have already been
- processed if the job is restarted.
-
- -k Generate a KRL file. In this mode, ssh-keygen will generate a
- KRL file at the location specified via the -f flag that revokes
- every key or certificate presented on the command line.
- Keys/certificates to be revoked may be specified by public key
- file or using the format described in the KEY REVOCATION LISTS
- section.
-
- -L Prints the contents of a certificate.
-
- -l Show fingerprint of specified public key file. Private RSA1 keys
- are also supported. For RSA and DSA keys ssh-keygen tries to
- find the matching public key file and prints its fingerprint. If
- combined with -v, an ASCII art representation of the key is
- supplied with the fingerprint.
-
- -M memory
- Specify the amount of memory to use (in megabytes) when
- generating candidate moduli for DH-GEX.
-
- -m key_format
- Specify a key format for the -i (import) or -e (export)
- conversion options. The supported key formats are: M-bM-^@M-^\RFC4716M-bM-^@M-^]
- (RFC 4716/SSH2 public or private key), M-bM-^@M-^\PKCS8M-bM-^@M-^] (PEM PKCS8 public
- key) or M-bM-^@M-^\PEMM-bM-^@M-^] (PEM public key). The default conversion format is
- M-bM-^@M-^\RFC4716M-bM-^@M-^].
-
- -N new_passphrase
- Provides the new passphrase.
-
- -n principals
- Specify one or more principals (user or host names) to be
- included in a certificate when signing a key. Multiple
- principals may be specified, separated by commas. Please see the
- CERTIFICATES section for details.
-
- -O option
- Specify a certificate option when signing a key. This option may
- be specified multiple times. Please see the CERTIFICATES section
- for details. The options that are valid for user certificates
- are:
-
- clear Clear all enabled permissions. This is useful for
- clearing the default set of permissions so permissions
- may be added individually.
-
- force-command=command
- Forces the execution of command instead of any shell or
- command specified by the user when the certificate is
- used for authentication.
-
- no-agent-forwarding
- Disable ssh-agent(1) forwarding (permitted by default).
-
- no-port-forwarding
- Disable port forwarding (permitted by default).
-
- no-pty Disable PTY allocation (permitted by default).
-
- no-user-rc
- Disable execution of ~/.ssh/rc by sshd(8) (permitted by
- default).
-
- no-x11-forwarding
- Disable X11 forwarding (permitted by default).
-
- permit-agent-forwarding
- Allows ssh-agent(1) forwarding.
-
- permit-port-forwarding
- Allows port forwarding.
-
- permit-pty
- Allows PTY allocation.
-
- permit-user-rc
- Allows execution of ~/.ssh/rc by sshd(8).
-
- permit-x11-forwarding
- Allows X11 forwarding.
-
- source-address=address_list
- Restrict the source addresses from which the certificate
- is considered valid. The address_list is a comma-
- separated list of one or more address/netmask pairs in
- CIDR format.
-
- At present, no options are valid for host keys.
-
- -o Causes ssh-keygen to save SSH protocol 2 private keys using the
- new OpenSSH format rather than the more compatible PEM format.
- The new format has increased resistance to brute-force password
- cracking but is not supported by versions of OpenSSH prior to
- 6.5. Ed25519 keys always use the new private key format.
-
- -P passphrase
- Provides the (old) passphrase.
-
- -p Requests changing the passphrase of a private key file instead of
- creating a new private key. The program will prompt for the file
- containing the private key, for the old passphrase, and twice for
- the new passphrase.
-
- -Q Test whether keys have been revoked in a KRL.
-
- -q Silence ssh-keygen.
-
- -R hostname
- Removes all keys belonging to hostname from a known_hosts file.
- This option is useful to delete hashed hosts (see the -H option
- above).
-
- -r hostname
- Print the SSHFP fingerprint resource record named hostname for
- the specified public key file.
-
- -S start
- Specify start point (in hex) when generating candidate moduli for
- DH-GEX.
-
- -s ca_key
- Certify (sign) a public key using the specified CA key. Please
- see the CERTIFICATES section for details.
-
- When generating a KRL, -s specifies a path to a CA public key
- file used to revoke certificates directly by key ID or serial
- number. See the KEY REVOCATION LISTS section for details.
-
- -T output_file
- Test DH group exchange candidate primes (generated using the -G
- option) for safety.
-
- -t dsa | ecdsa | ed25519 | rsa | rsa1
- Specifies the type of key to create. The possible values are
- M-bM-^@M-^\rsa1M-bM-^@M-^] for protocol version 1 and M-bM-^@M-^\dsaM-bM-^@M-^], M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^], or
- M-bM-^@M-^\rsaM-bM-^@M-^] for protocol version 2.
-
- -u Update a KRL. When specified with -k, keys listed via the
- command line are added to the existing KRL rather than a new KRL
- being created.
-
- -V validity_interval
- Specify a validity interval when signing a certificate. A
- validity interval may consist of a single time, indicating that
- the certificate is valid beginning now and expiring at that time,
- or may consist of two times separated by a colon to indicate an
- explicit time interval. The start time may be specified as a
- date in YYYYMMDD format, a time in YYYYMMDDHHMMSS format or a
- relative time (to the current time) consisting of a minus sign
- followed by a relative time in the format described in the TIME
- FORMATS section of sshd_config(5). The end time may be specified
- as a YYYYMMDD date, a YYYYMMDDHHMMSS time or a relative time
- starting with a plus character.
-
- For example: M-bM-^@M-^\+52w1dM-bM-^@M-^] (valid from now to 52 weeks and one day
- from now), M-bM-^@M-^\-4w:+4wM-bM-^@M-^] (valid from four weeks ago to four weeks
- from now), M-bM-^@M-^\20100101123000:20110101123000M-bM-^@M-^] (valid from 12:30 PM,
- January 1st, 2010 to 12:30 PM, January 1st, 2011), M-bM-^@M-^\-1d:20110101M-bM-^@M-^]
- (valid from yesterday to midnight, January 1st, 2011).
-
- -v Verbose mode. Causes ssh-keygen to print debugging messages
- about its progress. This is helpful for debugging moduli
- generation. Multiple -v options increase the verbosity. The
- maximum is 3.
-
- -W generator
- Specify desired generator when testing candidate moduli for DH-
- GEX.
-
- -y This option will read a private OpenSSH format file and print an
- OpenSSH public key to stdout.
-
- -z serial_number
- Specifies a serial number to be embedded in the certificate to
- distinguish this certificate from others from the same CA. The
- default serial number is zero.
-
- When generating a KRL, the -z flag is used to specify a KRL
- version number.
-
-MODULI GENERATION
- ssh-keygen may be used to generate groups for the Diffie-Hellman Group
- Exchange (DH-GEX) protocol. Generating these groups is a two-step
- process: first, candidate primes are generated using a fast, but memory
- intensive process. These candidate primes are then tested for
- suitability (a CPU-intensive process).
-
- Generation of primes is performed using the -G option. The desired
- length of the primes may be specified by the -b option. For example:
-
- # ssh-keygen -G moduli-2048.candidates -b 2048
-
- By default, the search for primes begins at a random point in the desired
- length range. This may be overridden using the -S option, which
- specifies a different start point (in hex).
-
- Once a set of candidates have been generated, they must be screened for
- suitability. This may be performed using the -T option. In this mode
- ssh-keygen will read candidates from standard input (or a file specified
- using the -f option). For example:
-
- # ssh-keygen -T moduli-2048 -f moduli-2048.candidates
-
- By default, each candidate will be subjected to 100 primality tests.
- This may be overridden using the -a option. The DH generator value will
- be chosen automatically for the prime under consideration. If a specific
- generator is desired, it may be requested using the -W option. Valid
- generator values are 2, 3, and 5.
-
- Screened DH groups may be installed in /etc/moduli. It is important that
- this file contains moduli of a range of bit lengths and that both ends of
- a connection share common moduli.
-
-CERTIFICATES
- ssh-keygen supports signing of keys to produce certificates that may be
- used for user or host authentication. Certificates consist of a public
- key, some identity information, zero or more principal (user or host)
- names and a set of options that are signed by a Certification Authority
- (CA) key. Clients or servers may then trust only the CA key and verify
- its signature on a certificate rather than trusting many user/host keys.
- Note that OpenSSH certificates are a different, and much simpler, format
- to the X.509 certificates used in ssl(8).
-
- ssh-keygen supports two types of certificates: user and host. User
- certificates authenticate users to servers, whereas host certificates
- authenticate server hosts to users. To generate a user certificate:
-
- $ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub
-
- The resultant certificate will be placed in /path/to/user_key-cert.pub.
- A host certificate requires the -h option:
-
- $ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub
-
- The host certificate will be output to /path/to/host_key-cert.pub.
-
- It is possible to sign using a CA key stored in a PKCS#11 token by
- providing the token library using -D and identifying the CA key by
- providing its public half as an argument to -s:
-
- $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id host_key.pub
-
- In all cases, key_id is a "key identifier" that is logged by the server
- when the certificate is used for authentication.
-
- Certificates may be limited to be valid for a set of principal
- (user/host) names. By default, generated certificates are valid for all
- users or hosts. To generate a certificate for a specified set of
- principals:
-
- $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub
- $ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub
-
- Additional limitations on the validity and use of user certificates may
- be specified through certificate options. A certificate option may
- disable features of the SSH session, may be valid only when presented
- from particular source addresses or may force the use of a specific
- command. For a list of valid certificate options, see the documentation
- for the -O option above.
-
- Finally, certificates may be defined with a validity lifetime. The -V
- option allows specification of certificate start and end times. A
- certificate that is presented at a time outside this range will not be
- considered valid. By default, certificates are valid from UNIX Epoch to
- the distant future.
-
- For certificates to be used for user or host authentication, the CA
- public key must be trusted by sshd(8) or ssh(1). Please refer to those
- manual pages for details.
-
-KEY REVOCATION LISTS
- ssh-keygen is able to manage OpenSSH format Key Revocation Lists (KRLs).
- These binary files specify keys or certificates to be revoked using a
- compact format, taking as little as one bit per certificate if they are
- being revoked by serial number.
-
- KRLs may be generated using the -k flag. This option reads one or more
- files from the command line and generates a new KRL. The files may
- either contain a KRL specification (see below) or public keys, listed one
- per line. Plain public keys are revoked by listing their hash or
- contents in the KRL and certificates revoked by serial number or key ID
- (if the serial is zero or not available).
-
- Revoking keys using a KRL specification offers explicit control over the
- types of record used to revoke keys and may be used to directly revoke
- certificates by serial number or key ID without having the complete
- original certificate on hand. A KRL specification consists of lines
- containing one of the following directives followed by a colon and some
- directive-specific information.
-
- serial: serial_number[-serial_number]
- Revokes a certificate with the specified serial number. Serial
- numbers are 64-bit values, not including zero and may be
- expressed in decimal, hex or octal. If two serial numbers are
- specified separated by a hyphen, then the range of serial numbers
- including and between each is revoked. The CA key must have been
- specified on the ssh-keygen command line using the -s option.
-
- id: key_id
- Revokes a certificate with the specified key ID string. The CA
- key must have been specified on the ssh-keygen command line using
- the -s option.
-
- key: public_key
- Revokes the specified key. If a certificate is listed, then it
- is revoked as a plain public key.
-
- sha1: public_key
- Revokes the specified key by its SHA1 hash.
-
- KRLs may be updated using the -u flag in addition to -k. When this
- option is specified, keys listed via the command line are merged into the
- KRL, adding to those already there.
-
- It is also possible, given a KRL, to test whether it revokes a particular
- key (or keys). The -Q flag will query an existing KRL, testing each key
- specified on the commandline. If any key listed on the command line has
- been revoked (or an error encountered) then ssh-keygen will exit with a
- non-zero exit status. A zero exit status will only be returned if no key
- was revoked.
-
-FILES
- ~/.ssh/identity
- Contains the protocol version 1 RSA authentication identity of
- the user. This file should not be readable by anyone but the
- user. It is possible to specify a passphrase when generating the
- key; that passphrase will be used to encrypt the private part of
- this file using 3DES. This file is not automatically accessed by
- ssh-keygen but it is offered as the default file for the private
- key. ssh(1) will read this file when a login attempt is made.
-
- ~/.ssh/identity.pub
- Contains the protocol version 1 RSA public key for
- authentication. The contents of this file should be added to
- ~/.ssh/authorized_keys on all machines where the user wishes to
- log in using RSA authentication. There is no need to keep the
- contents of this file secret.
-
- ~/.ssh/id_dsa
- ~/.ssh/id_ecdsa
- ~/.ssh/id_ed25519
- ~/.ssh/id_rsa
- Contains the protocol version 2 DSA, ECDSA, Ed25519 or RSA
- authentication identity of the user. This file should not be
- readable by anyone but the user. It is possible to specify a
- passphrase when generating the key; that passphrase will be used
- to encrypt the private part of this file using 128-bit AES. This
- file is not automatically accessed by ssh-keygen but it is
- offered as the default file for the private key. ssh(1) will
- read this file when a login attempt is made.
-
- ~/.ssh/id_dsa.pub
- ~/.ssh/id_ecdsa.pub
- ~/.ssh/id_ed25519.pub
- ~/.ssh/id_rsa.pub
- Contains the protocol version 2 DSA, ECDSA, Ed25519 or RSA public
- key for authentication. The contents of this file should be
- added to ~/.ssh/authorized_keys on all machines where the user
- wishes to log in using public key authentication. There is no
- need to keep the contents of this file secret.
-
- /etc/moduli
- Contains Diffie-Hellman groups used for DH-GEX. The file format
- is described in moduli(5).
-
-SEE ALSO
- ssh(1), ssh-add(1), ssh-agent(1), moduli(5), sshd(8)
-
- The Secure Shell (SSH) Public Key File Format, RFC 4716, 2006.
-
-AUTHORS
- OpenSSH is a derivative of the original and free ssh 1.2.12 release by
- Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
- de Raadt and Dug Song removed many bugs, re-added newer features and
- created OpenSSH. Markus Friedl contributed the support for SSH protocol
- versions 1.5 and 2.0.
-
-OpenBSD 5.7 February 24, 2015 OpenBSD 5.7
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index 9b93666c..059c1b03 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-keygen.1,v 1.125 2015/02/24 15:24:05 naddy Exp $
+.\" $OpenBSD: ssh-keygen.1,v 1.203 2020/04/03 02:26:56 djm Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,42 +35,45 @@
.\" (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 24 2015 $
+.Dd $Mdocdate: April 3 2020 $
.Dt SSH-KEYGEN 1
.Os
.Sh NAME
.Nm ssh-keygen
-.Nd authentication key generation, management and conversion
+.Nd OpenSSH authentication key utility
.Sh SYNOPSIS
-.Bk -words
.Nm ssh-keygen
.Op Fl q
.Op Fl b Ar bits
-.Op Fl t Cm dsa | ecdsa | ed25519 | rsa | rsa1
-.Op Fl N Ar new_passphrase
.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 w Ar provider
.Nm ssh-keygen
.Fl p
-.Op Fl P Ar old_passphrase
-.Op Fl N Ar new_passphrase
.Op Fl f Ar keyfile
+.Op Fl m Ar format
+.Op Fl N Ar new_passphrase
+.Op Fl P Ar old_passphrase
.Nm ssh-keygen
.Fl i
-.Op Fl m Ar key_format
.Op Fl f Ar input_keyfile
+.Op Fl m Ar key_format
.Nm ssh-keygen
.Fl e
-.Op Fl m Ar key_format
.Op Fl f Ar input_keyfile
+.Op Fl m Ar key_format
.Nm ssh-keygen
.Fl y
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl c
-.Op Fl P Ar passphrase
.Op Fl C Ar comment
.Op Fl f Ar keyfile
+.Op Fl P Ar passphrase
.Nm ssh-keygen
.Fl l
.Op Fl v
@@ -83,37 +86,35 @@
.Fl D Ar pkcs11
.Nm ssh-keygen
.Fl F Ar hostname
+.Op Fl lv
.Op Fl f Ar known_hosts_file
-.Op Fl l
.Nm ssh-keygen
.Fl H
.Op Fl f Ar known_hosts_file
.Nm ssh-keygen
+.Fl K
+.Op Fl w Ar provider
+.Nm ssh-keygen
.Fl R Ar hostname
.Op Fl f Ar known_hosts_file
.Nm ssh-keygen
.Fl r Ar hostname
-.Op Fl f Ar input_keyfile
.Op Fl g
+.Op Fl f Ar input_keyfile
.Nm ssh-keygen
-.Fl G Ar output_file
-.Op Fl v
-.Op Fl b Ar bits
-.Op Fl M Ar memory
-.Op Fl S Ar start_point
+.Fl M Cm generate
+.Op Fl O Ar option
+.Ar output_file
.Nm ssh-keygen
-.Fl T Ar output_file
-.Fl f Ar input_file
-.Op Fl v
-.Op Fl a Ar rounds
-.Op Fl J Ar num_lines
-.Op Fl j Ar start_line
-.Op Fl K Ar checkpt
-.Op Fl W Ar generator
+.Fl M Cm screen
+.Op Fl f Ar input_file
+.Op Fl O Ar option
+.Ar output_file
.Nm ssh-keygen
-.Fl s Ar ca_key
.Fl I Ar certificate_identity
-.Op Fl h
+.Fl s Ar ca_key
+.Op Fl hU
+.Op Fl D Ar pkcs11_provider
.Op Fl n Ar principals
.Op Fl O Ar option
.Op Fl V Ar validity_interval
@@ -124,6 +125,7 @@
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl A
+.Op Fl f Ar prefix_path
.Nm ssh-keygen
.Fl k
.Fl f Ar krl_file
@@ -133,22 +135,42 @@
.Ar
.Nm ssh-keygen
.Fl Q
+.Op Fl l
.Fl f Ar krl_file
.Ar
-.Ek
+.Nm ssh-keygen
+.Fl Y Cm find-principals
+.Fl s Ar signature_file
+.Fl f Ar allowed_signers_file
+.Nm ssh-keygen
+.Fl Y Cm check-novalidate
+.Fl n Ar namespace
+.Fl s Ar signature_file
+.Nm ssh-keygen
+.Fl Y Cm sign
+.Fl f Ar key_file
+.Fl n Ar namespace
+.Ar
+.Nm ssh-keygen
+.Fl Y Cm verify
+.Fl f Ar allowed_signers_file
+.Fl I Ar signer_identity
+.Fl n Ar namespace
+.Fl s Ar signature_file
+.Op Fl r Ar revocation_file
.Sh DESCRIPTION
.Nm
generates, manages and converts authentication keys for
.Xr ssh 1 .
.Nm
-can create RSA keys for use by SSH protocol version 1 and
-DSA, ECDSA, Ed25519 or RSA keys for use by SSH protocol version 2.
+can create keys for use by SSH protocol version 2.
+.Pp
The type of key to be generated is specified with the
.Fl t
option.
If invoked without any arguments,
.Nm
-will generate an RSA key for use in SSH protocol 2 connections.
+will generate an RSA key.
.Pp
.Nm
is also used to generate groups for use in Diffie-Hellman group
@@ -168,10 +190,11 @@ section for details.
Normally each user wishing to use SSH
with public key authentication runs this once to create the authentication
key in
-.Pa ~/.ssh/identity ,
.Pa ~/.ssh/id_dsa ,
.Pa ~/.ssh/id_ecdsa ,
-.Pa ~/.ssh/id_ed25519
+.Pa ~/.ssh/id_ecdsa_sk ,
+.Pa ~/.ssh/id_ed25519 ,
+.Pa ~/.ssh/id_ed25519_sk
or
.Pa ~/.ssh/id_rsa .
Additionally, the system administrator may use this to generate host keys,
@@ -203,49 +226,56 @@ There is no way to recover a lost passphrase.
If the passphrase is lost or forgotten, a new key must be generated
and the corresponding public key copied to other machines.
.Pp
-For RSA1 keys,
-there is also a comment field in the key file that is only for
-convenience to the user to help identify the key.
-The comment can tell what the key is for, or whatever is useful.
+.Nm
+will by default write keys in an OpenSSH-specific format.
+This format is preferred as it offers better protection for
+keys at rest as well as allowing storage of key comments within
+the private key file itself.
+The key comment may be useful to help identify the key.
The comment is initialized to
.Dq user@host
when the key is created, but can be changed using the
.Fl c
option.
.Pp
+It is still possible for
+.Nm
+to write the previously-used PEM format private keys using the
+.Fl m
+flag.
+This may be used when generating new keys, and existing new-format
+keys may be converted using this option in conjunction with the
+.Fl p
+(change passphrase) flag.
+.Pp
After a key is generated, instructions below detail where the keys
should be placed to be activated.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl A
-For each of the key types (rsa1, rsa, dsa, ecdsa and ed25519)
+For each of the key types (rsa, dsa, ecdsa and ed25519)
for which host keys
do not exist, generate the host keys with the default key file path,
an empty passphrase, default bits for the key type, and default comment.
+If
+.Fl f
+has also been specified, its argument is used as a prefix to the
+default path for the resulting host key files.
This is used by
.Pa /etc/rc
to generate new host keys.
.It Fl a Ar rounds
-When saving a new-format private key (i.e. an ed25519 key or any SSH protocol
-2 key when the
-.Fl o
-flag is set), this option specifies the number of KDF (key derivation function)
-rounds used.
+When saving a private key, this option specifies the number of KDF
+(key derivation function) rounds used.
Higher numbers result in slower passphrase verification and increased
resistance to brute-force password cracking (should the keys be stolen).
-.Pp
-When screening DH-GEX candidates (
-using the
-.Fl T
-command).
-This option specifies the number of primality tests to perform.
.It Fl B
Show the bubblebabble digest of specified private or public key file.
.It Fl b Ar bits
Specifies the number of bits in the key to create.
-For RSA keys, the minimum size is 768 bits and the default is 2048 bits.
-Generally, 2048 bits is considered sufficient.
+For RSA keys, the minimum size is 1024 bits and the default is 3072 bits.
+Generally, 3072 bits is considered sufficient.
DSA keys must be exactly 1024 bits as specified by FIPS 186-2.
For ECDSA keys, the
.Fl b
@@ -253,18 +283,17 @@ flag determines the key length by selecting from one of three elliptic
curve sizes: 256, 384 or 521 bits.
Attempting to use bit lengths other than these three values for ECDSA keys
will fail.
-Ed25519 keys have a fixed length and the
+ECDSA-SK, Ed25519 and Ed25519-SK keys have a fixed length and the
.Fl b
flag will be ignored.
.It Fl C Ar comment
Provides a new comment.
.It Fl c
Requests changing the comment in the private and public key files.
-This operation is only supported for RSA1 keys.
The program will prompt for the file containing the private keys, for
the passphrase if the key has one, and for the new comment.
.It Fl D Ar pkcs11
-Download the RSA public keys provided by the PKCS#11 shared library
+Download the public keys provided by the PKCS#11 shared library
.Ar pkcs11 .
When used in combination with
.Fl s ,
@@ -281,16 +310,17 @@ The default is
.Dq sha256 .
.It Fl e
This option will read a private or public OpenSSH key file and
-print to stdout the key in one of the formats specified by the
+print to stdout a public key in one of the formats specified by the
.Fl m
option.
The default export format is
.Dq RFC4716 .
This option allows exporting OpenSSH keys for use by other programs, including
several commercial SSH implementations.
-.It Fl F Ar hostname
+.It Fl F Ar hostname | [hostname]:port
Search for the specified
.Ar hostname
+(with optional port number)
in a
.Pa known_hosts
file, listing any occurrences found.
@@ -300,12 +330,6 @@ used in conjunction with the
option to print found keys in a hashed format.
.It Fl f Ar filename
Specifies the filename of the key file.
-.It Fl G Ar output_file
-Generate candidate primes for DH-GEX.
-These primes must be screened for
-safety (using the
-.Fl T
-option) before use.
.It Fl g
Use generic DNS format when printing fingerprint resource records using the
.Fl r
@@ -346,24 +370,10 @@ This option allows importing keys from other software, including several
commercial SSH implementations.
The default import format is
.Dq RFC4716 .
-.It Fl J Ar num_lines
-Exit after screening the specified number of lines
-while performing DH candidate screening using the
-.Fl T
-option.
-.It Fl j Ar start_line
-Start screening at the specified line number
-while performing DH candidate screening using the
-.Fl T
-option.
-.It Fl K Ar checkpt
-Write the last line processed to the file
-.Ar checkpt
-while performing DH candidate screening using the
-.Fl T
-option.
-This will be used to skip lines in the input file that have already been
-processed if the job is restarted.
+.It Fl K
+Download resident keys from a FIDO authenticator.
+Public and private key files will be written to the current directory for
+each downloaded key.
.It Fl k
Generate a KRL file.
In this mode,
@@ -376,35 +386,61 @@ using the format described in the
.Sx KEY REVOCATION LISTS
section.
.It Fl L
-Prints the contents of a certificate.
+Prints the contents of one or more certificates.
.It Fl l
Show fingerprint of specified public key file.
-Private RSA1 keys are also supported.
For RSA and DSA keys
.Nm
tries to find the matching public key file and prints its fingerprint.
If combined with
.Fl v ,
-an ASCII art representation of the key is supplied with the fingerprint.
-.It Fl M Ar memory
-Specify the amount of memory to use (in megabytes) when generating
-candidate moduli for DH-GEX.
+a visual ASCII art representation of the key is supplied with the
+fingerprint.
+.It Fl M Cm generate
+Generate candidate Diffie-Hellman Group Exchange (DH-GEX) parameters for
+eventual use by the
+.Sq diffie-hellman-group-exchange-*
+key exchange methods.
+The numbers generated by this operation must be further screened before
+use.
+See the
+.Sx MODULI GENERATION
+section for more information.
+.It Fl M Cm screen
+Screen candidate parameters for Diffie-Hellman Group Exchange.
+This will accept a list of candidate numbers and test that they are
+safe (Sophie Germain) primes with acceptable group generators.
+The results of this operation may be added to the
+.Pa /etc/moduli
+file.
+See the
+.Sx MODULI GENERATION
+section for more information.
.It Fl m Ar key_format
-Specify a key format for the
+Specify a key format for key generation, the
.Fl i
-(import) or
+(import),
.Fl e
-(export) conversion options.
+(export) conversion options, and the
+.Fl p
+change passphrase operation.
+The latter may be used to convert between OpenSSH private key and PEM
+private key formats.
The supported key formats are:
.Dq RFC4716
(RFC 4716/SSH2 public or private key),
.Dq PKCS8
-(PEM PKCS8 public key)
+(PKCS8 public or private key)
or
.Dq PEM
(PEM public key).
-The default conversion format is
+By default OpenSSH will write newly-generated private keys in its own
+format, but when converting public keys for export the default format is
.Dq RFC4716 .
+Setting a format of
+.Dq PEM
+when generating or updating a supported private key type will cause the
+key to be stored in the legacy PEM private key format.
.It Fl N Ar new_passphrase
Provides the new passphrase.
.It Fl n Ar principals
@@ -415,70 +451,67 @@ Please see the
.Sx CERTIFICATES
section for details.
.It Fl O Ar option
-Specify a certificate option when signing a key.
-This option may be specified multiple times.
-Please see the
+Specify a key/value option.
+These are specific to the operation that
+.Nm
+has been requested to perform.
+.Pp
+When signing certificates, one of the options listed in the
.Sx CERTIFICATES
-section for details.
-The options that are valid for user certificates are:
+section may be specified here.
+.Pp
+When performing moduli generation or screening, one of the options
+listed in the
+.Sx MODULI GENERATION
+section may be specified.
+.Pp
+When generating a key that will be hosted on a FIDO authenticator,
+this flag may be used to specify key-specific options.
+Those supported at present are:
.Bl -tag -width Ds
-.It Ic clear
-Clear all enabled permissions.
-This is useful for clearing the default set of permissions so permissions may
-be added individually.
-.It Ic force-command Ns = Ns Ar command
-Forces the execution of
-.Ar command
-instead of any shell or command specified by the user when
-the certificate is used for authentication.
-.It Ic no-agent-forwarding
-Disable
-.Xr ssh-agent 1
-forwarding (permitted by default).
-.It Ic no-port-forwarding
-Disable port forwarding (permitted by default).
-.It Ic no-pty
-Disable PTY allocation (permitted by default).
-.It Ic no-user-rc
-Disable execution of
-.Pa ~/.ssh/rc
-by
+.It Cm application
+Override the default FIDO application/origin string of
+.Dq ssh: .
+This may be useful when generating host or domain-specific resident keys.
+The specified application string must begin with
+.Dq ssh: .
+.It Cm challenge Ns = Ns Ar path
+Specifies a path to a challenge string that will be passed to the
+FIDO token during key generation.
+The challenge string may be used as part of an out-of-band
+protocol for key enrollment
+(a random challenge is used by default).
+.It Cm device
+Explicitly specify a
+.Xr fido 4
+device to use, rather than letting the token middleware select one.
+.It Cm no-touch-required
+Indicate that the generated private key should not require touch
+events (user presence) when making signatures.
+Note that
.Xr sshd 8
-(permitted by default).
-.It Ic no-x11-forwarding
-Disable X11 forwarding (permitted by default).
-.It Ic permit-agent-forwarding
-Allows
-.Xr ssh-agent 1
-forwarding.
-.It Ic permit-port-forwarding
-Allows port forwarding.
-.It Ic permit-pty
-Allows PTY allocation.
-.It Ic permit-user-rc
-Allows execution of
-.Pa ~/.ssh/rc
-by
-.Xr sshd 8 .
-.It Ic permit-x11-forwarding
-Allows X11 forwarding.
-.It Ic source-address Ns = Ns Ar address_list
-Restrict the source addresses from which the certificate is considered valid.
-The
-.Ar address_list
-is a comma-separated list of one or more address/netmask pairs in CIDR
-format.
+will refuse such signatures by default, unless overridden via
+an authorized_keys option.
+.It Cm resident
+Indicate that the key should be stored on the FIDO authenticator itself.
+Resident keys may be supported on FIDO2 tokens and typically require that
+a PIN be set on the token prior to generation.
+Resident keys may be loaded off the token using
+.Xr ssh-add 1 .
+.It Cm user
+A username to be associated with a resident key,
+overriding the empty default username.
+Specifying a username may be useful when generating multiple resident keys
+for the same application name.
+.It Cm write-attestation Ns = Ns Ar path
+May be used at key generation time to record the attestation certificate
+returned from FIDO tokens during key generation.
+By default this information is discarded.
.El
.Pp
-At present, no options are valid for host keys.
-.It Fl o
-Causes
-.Nm
-to save SSH protocol 2 private keys using the new OpenSSH format rather than
-the more compatible PEM format.
-The new format has increased resistance to brute-force password cracking
-but is not supported by versions of OpenSSH prior to 6.5.
-Ed25519 keys always use the new private key format.
+The
+.Fl O
+option may be specified multiple times.
.It Fl P Ar passphrase
Provides the (old) passphrase.
.It Fl p
@@ -489,12 +522,16 @@ containing the private key, for the old passphrase, and twice for the
new passphrase.
.It Fl Q
Test whether keys have been revoked in a KRL.
+If the
+.Fl l
+option is also specified then the contents of the KRL will be printed.
.It Fl q
Silence
.Nm ssh-keygen .
-.It Fl R Ar hostname
-Removes all keys belonging to
+.It Fl R Ar hostname | [hostname]:port
+Removes all keys belonging to the specified
.Ar hostname
+(with optional port number)
from a
.Pa known_hosts
file.
@@ -505,8 +542,6 @@ option above).
Print the SSHFP fingerprint resource record named
.Ar hostname
for the specified public key file.
-.It Fl S Ar start
-Specify start point (in hex) when generating candidate moduli for DH-GEX.
.It Fl s Ar ca_key
Certify (sign) a public key using the specified CA key.
Please see the
@@ -520,21 +555,34 @@ by key ID or serial number.
See the
.Sx KEY REVOCATION LISTS
section for details.
-.It Fl T Ar output_file
-Test DH group exchange candidate primes (generated using the
-.Fl G
-option) for safety.
-.It Fl t Cm dsa | ecdsa | ed25519 | rsa | rsa1
+.It Fl t Cm dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa
Specifies the type of key to create.
The possible values are
-.Dq rsa1
-for protocol version 1 and
.Dq dsa ,
.Dq ecdsa ,
+.Dq ecdsa-sk ,
.Dq ed25519 ,
+.Dq ed25519-sk ,
or
-.Dq rsa
-for protocol version 2.
+.Dq rsa .
+.Pp
+This flag may also be used to specify the desired signature type when
+signing certificates using an RSA CA key.
+The available RSA signature variants are
+.Dq ssh-rsa
+(SHA1 signatures, not recommended),
+.Dq rsa-sha2-256 ,
+and
+.Dq rsa-sha2-512
+(the default).
+.It Fl U
+When used in combination with
+.Fl s ,
+this option indicates that a CA key resides in a
+.Xr ssh-agent 1 .
+See the
+.Sx CERTIFICATES
+section for more information.
.It Fl u
Update a KRL.
When specified with
@@ -546,13 +594,20 @@ Specify a validity interval when signing a certificate.
A validity interval may consist of a single time, indicating that the
certificate is valid beginning now and expiring at that time, or may consist
of two times separated by a colon to indicate an explicit time interval.
-The start time may be specified as a date in YYYYMMDD format, a time
-in YYYYMMDDHHMMSS format or a relative time (to the current time) consisting
-of a minus sign followed by a relative time in the format described in the
+.Pp
+The start time may be specified as the string
+.Dq always
+to indicate the certificate has no specified start time,
+a date in YYYYMMDD format, a time in YYYYMMDDHHMM[SS] format,
+a relative time (to the current time) consisting of a minus sign followed by
+an interval in the format described in the
TIME FORMATS section of
.Xr sshd_config 5 .
-The end time may be specified as a YYYYMMDD date, a YYYYMMDDHHMMSS time or
-a relative time starting with a plus character.
+.Pp
+The end time may be specified as a YYYYMMDD date, a YYYYMMDDHHMM[SS] time,
+a relative time starting with a plus character or the string
+.Dq forever
+to indicate that the certificate has no expiry date.
.Pp
For example:
.Dq +52w1d
@@ -563,6 +618,8 @@ For example:
(valid from 12:30 PM, January 1st, 2010 to 12:30 PM, January 1st, 2011),
.Dq -1d:20110101
(valid from yesterday to midnight, January 1st, 2011).
+.Dq -1m:forever
+(valid from one minute ago and never expiring).
.It Fl v
Verbose mode.
Causes
@@ -573,14 +630,106 @@ Multiple
.Fl v
options increase the verbosity.
The maximum is 3.
-.It Fl W Ar generator
-Specify desired generator when testing candidate moduli for DH-GEX.
+.It Fl w Ar provider
+Specifies a path to a library that will be used when creating
+FIDO authenticator-hosted keys, overriding the default of using
+the internal USB HID support.
+.It Fl Y Cm find-principals
+Find the principal(s) associated with the public key of a signature,
+provided using the
+.Fl s
+flag in an authorized signers file provided using the
+.Fl f
+flag.
+The format of the allowed signers file is documented in the
+.Sx ALLOWED SIGNERS
+section below.
+If one or more matching principals are found, they are returned on
+standard output.
+.It Fl Y Cm check-novalidate
+Checks that a signature generated using
+.Nm
+.Fl Y Cm sign
+has a valid structure.
+This does not validate if a signature comes from an authorized signer.
+When testing a signature,
+.Nm
+accepts a message on standard input and a signature namespace using
+.Fl n .
+A file containing the corresponding signature must also be supplied using the
+.Fl s
+flag.
+Successful testing of the signature is signalled by
+.Nm
+returning a zero exit status.
+.It Fl Y Cm sign
+Cryptographically sign a file or some data using a SSH key.
+When signing,
+.Nm
+accepts zero or more files to sign on the command-line - if no files
+are specified then
+.Nm
+will sign data presented on standard input.
+Signatures are written to the path of the input file with
+.Dq .sig
+appended, or to standard output if the message to be signed was read from
+standard input.
+.Pp
+The key used for signing is specified using the
+.Fl f
+option and may refer to either a private key, or a public key with the private
+half available via
+.Xr ssh-agent 1 .
+An additional signature namespace, used to prevent signature confusion across
+different domains of use (e.g. file signing vs email signing) must be provided
+via the
+.Fl n
+flag.
+Namespaces are arbitrary strings, and may include:
+.Dq file
+for file signing,
+.Dq email
+for email signing.
+For custom uses, it is recommended to use names following a
+NAMESPACE@YOUR.DOMAIN pattern to generate unambiguous namespaces.
+.It Fl Y Cm verify
+Request to verify a signature generated using
+.Nm
+.Fl Y Cm sign
+as described above.
+When verifying a signature,
+.Nm
+accepts a message on standard input and a signature namespace using
+.Fl n .
+A file containing the corresponding signature must also be supplied using the
+.Fl s
+flag, along with the identity of the signer using
+.Fl I
+and a list of allowed signers via the
+.Fl f
+flag.
+The format of the allowed signers file is documented in the
+.Sx ALLOWED SIGNERS
+section below.
+A file containing revoked keys can be passed using the
+.Fl r
+flag.
+The revocation file may be a KRL or a one-per-line list of public keys.
+Successful verification by an authorized signer is signalled by
+.Nm
+returning a zero exit status.
.It Fl y
This option will read a private
OpenSSH format file and print an OpenSSH public key to stdout.
.It Fl z Ar serial_number
Specifies a serial number to be embedded in the certificate to distinguish
this certificate from others from the same CA.
+If the
+.Ar serial_number
+is prefixed with a
+.Sq +
+character, then the serial number will be incremented for each certificate
+signed on a single command-line.
The default serial number is zero.
.Pp
When generating a KRL, the
@@ -597,25 +746,25 @@ These candidate primes are then tested for suitability (a CPU-intensive
process).
.Pp
Generation of primes is performed using the
-.Fl G
+.Fl M Cm generate
option.
The desired length of the primes may be specified by the
-.Fl b
+.Fl O Cm bits
option.
For example:
.Pp
-.Dl # ssh-keygen -G moduli-2048.candidates -b 2048
+.Dl # ssh-keygen -M generate -O bits=2048 moduli-2048.candidates
.Pp
By default, the search for primes begins at a random point in the
desired length range.
This may be overridden using the
-.Fl S
+.Fl O Cm start
option, which specifies a different start point (in hex).
.Pp
Once a set of candidates have been generated, they must be screened for
suitability.
This may be performed using the
-.Fl T
+.Fl M Cm screen
option.
In this mode
.Nm
@@ -624,16 +773,16 @@ will read candidates from standard input (or a file specified using the
option).
For example:
.Pp
-.Dl # ssh-keygen -T moduli-2048 -f moduli-2048.candidates
+.Dl # ssh-keygen -M screen -f moduli-2048.candidates moduli-2048
.Pp
By default, each candidate will be subjected to 100 primality tests.
This may be overridden using the
-.Fl a
+.Fl O Cm prime-tests
option.
The DH generator value will be chosen automatically for the
prime under consideration.
If a specific generator is desired, it may be requested using the
-.Fl W
+.Fl O Cm generator
option.
Valid generator values are 2, 3, and 5.
.Pp
@@ -641,6 +790,30 @@ Screened DH groups may be installed in
.Pa /etc/moduli .
It is important that this file contains moduli of a range of bit lengths and
that both ends of a connection share common moduli.
+.Pp
+A number of options are available for moduli generation and screening via the
+.Fl O
+flag:
+.Bl -tag -width Ds
+.It Ic lines Ns = Ns Ar number
+Exit after screening the specified number of lines while performing DH
+candidate screening.
+.It Ic start-line Ns = Ns Ar line-number
+Start screening at the specified line number while performing DH candidate
+screening.
+.It Ic checkpoint Ns = Ns Ar filename
+Write the last line processed to the specified file while performing DH
+candidate screening.
+This will be used to skip lines in the input file that have already been
+processed if the job is restarted.
+.It Ic memory Ns = Ns Ar mbytes
+Specify the amount of memory to use (in megabytes) when generating
+candidate moduli for DH-GEX.
+.It Ic start Ns = Ns Ar hex-value
+Specify start point (in hex) when generating candidate moduli for DH-GEX.
+.It Ic generator Ns = Ns Ar value
+Specify desired generator (in decimal) when testing candidate moduli for DH-GEX.
+.El
.Sh CERTIFICATES
.Nm
supports signing of keys to produce certificates that may be used for
@@ -680,7 +853,15 @@ and identifying the CA key by providing its public half as an argument
to
.Fl s :
.Pp
-.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id host_key.pub
+.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub
+.Pp
+Similarly, it is possible for the CA key to be hosted in a
+.Xr ssh-agent 1 .
+This is indicated by the
+.Fl U
+flag and, again, the CA key must be identified by its public half.
+.Pp
+.Dl $ ssh-keygen -Us ca_key.pub -I key_id user_key.pub
.Pp
In all cases,
.Ar key_id
@@ -693,16 +874,101 @@ By default, generated certificates are valid for all users or hosts.
To generate a certificate for a specified set of principals:
.Pp
.Dl $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub
-.Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub"
+.Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain host_key.pub"
.Pp
Additional limitations on the validity and use of user certificates may
be specified through certificate options.
A certificate option may disable features of the SSH session, may be
valid only when presented from particular source addresses or may
force the use of a specific command.
-For a list of valid certificate options, see the documentation for the
-.Fl O
-option above.
+.Pp
+The options that are valid for user certificates are:
+.Pp
+.Bl -tag -width Ds -compact
+.It Ic clear
+Clear all enabled permissions.
+This is useful for clearing the default set of permissions so permissions may
+be added individually.
+.Pp
+.It Ic critical : Ns Ar name Ns Op Ns = Ns Ar contents
+.It Ic extension : Ns Ar name Ns Op Ns = Ns Ar contents
+Includes an arbitrary certificate critical option or extension.
+The specified
+.Ar name
+should include a domain suffix, e.g.\&
+.Dq name@example.com .
+If
+.Ar contents
+is specified then it is included as the contents of the extension/option
+encoded as a string, otherwise the extension/option is created with no
+contents (usually indicating a flag).
+Extensions may be ignored by a client or server that does not recognise them,
+whereas unknown critical options will cause the certificate to be refused.
+.Pp
+.It Ic force-command Ns = Ns Ar command
+Forces the execution of
+.Ar command
+instead of any shell or command specified by the user when
+the certificate is used for authentication.
+.Pp
+.It Ic no-agent-forwarding
+Disable
+.Xr ssh-agent 1
+forwarding (permitted by default).
+.Pp
+.It Ic no-port-forwarding
+Disable port forwarding (permitted by default).
+.Pp
+.It Ic no-pty
+Disable PTY allocation (permitted by default).
+.Pp
+.It Ic no-user-rc
+Disable execution of
+.Pa ~/.ssh/rc
+by
+.Xr sshd 8
+(permitted by default).
+.Pp
+.It Ic no-x11-forwarding
+Disable X11 forwarding (permitted by default).
+.Pp
+.It Ic permit-agent-forwarding
+Allows
+.Xr ssh-agent 1
+forwarding.
+.Pp
+.It Ic permit-port-forwarding
+Allows port forwarding.
+.Pp
+.It Ic permit-pty
+Allows PTY allocation.
+.Pp
+.It Ic permit-user-rc
+Allows execution of
+.Pa ~/.ssh/rc
+by
+.Xr sshd 8 .
+.Pp
+.It Ic permit-X11-forwarding
+Allows X11 forwarding.
+.Pp
+.It Ic no-touch-required
+Do not require signatures made using this key require demonstration
+of user presence (e.g. by having the user touch the authenticator).
+This option only makes sense for the FIDO authenticator algorithms
+.Cm ecdsa-sk
+and
+.Cm ed25519-sk .
+.Pp
+.It Ic source-address Ns = Ns Ar address_list
+Restrict the source addresses from which the certificate is considered valid.
+The
+.Ar address_list
+is a comma-separated list of one or more address/netmask pairs in CIDR
+format.
+.El
+.Pp
+At present, no standard options are valid for host keys.
.Pp
Finally, certificates may be defined with a validity lifetime.
The
@@ -767,7 +1033,20 @@ option.
Revokes the specified key.
If a certificate is listed, then it is revoked as a plain public key.
.It Cm sha1 : Ar public_key
-Revokes the specified key by its SHA1 hash.
+Revokes the specified key by including its SHA1 hash in the KRL.
+.It Cm sha256 : Ar public_key
+Revokes the specified key by including its SHA256 hash in the KRL.
+KRLs that revoke keys by SHA256 hash are not supported by OpenSSH versions
+prior to 7.9.
+.It Cm hash : Ar fingerprint
+Revokes a key using a fingerprint hash, as obtained from a
+.Xr sshd 8
+authentication log message or the
+.Nm
+.Fl l
+flag.
+Only SHA256 fingerprints are supported here and resultant KRLs are
+not supported by OpenSSH versions prior to 7.9.
.El
.Pp
KRLs may be updated using the
@@ -781,40 +1060,80 @@ It is also possible, given a KRL, to test whether it revokes a particular key
(or keys).
The
.Fl Q
-flag will query an existing KRL, testing each key specified on the commandline.
+flag will query an existing KRL, testing each key specified on the command line.
If any key listed on the command line has been revoked (or an error encountered)
then
.Nm
will exit with a non-zero exit status.
A zero exit status will only be returned if no key was revoked.
-.Sh FILES
-.Bl -tag -width Ds -compact
-.It Pa ~/.ssh/identity
-Contains the protocol version 1 RSA authentication identity of the user.
-This file should not be readable by anyone but the user.
-It is possible to
-specify a passphrase when generating the key; that passphrase will be
-used to encrypt the private part of this file using 3DES.
-This file is not automatically accessed by
+.Sh ALLOWED SIGNERS
+When verifying signatures,
.Nm
-but it is offered as the default file for the private key.
-.Xr ssh 1
-will read this file when a login attempt is made.
+uses a simple list of identities and keys to determine whether a signature
+comes from an authorized source.
+This "allowed signers" file uses a format patterned after the
+AUTHORIZED_KEYS FILE FORMAT described in
+.Xr sshd 8 .
+Each line of the file contains the following space-separated fields:
+principals, options, keytype, base64-encoded key.
+Empty lines and lines starting with a
+.Ql #
+are ignored as comments.
.Pp
-.It Pa ~/.ssh/identity.pub
-Contains the protocol version 1 RSA public key for authentication.
-The contents of this file should be added to
-.Pa ~/.ssh/authorized_keys
-on all machines
-where the user wishes to log in using RSA authentication.
-There is no need to keep the contents of this file secret.
+The principals field is a pattern-list (See PATTERNS in
+.Xr ssh_config 5 )
+consisting of one or more comma-separated USER@DOMAIN identity patterns
+that are accepted for signing.
+When verifying, the identity presented via the
+.Fl I
+option must match a principals pattern in order for the corresponding key to be
+considered acceptable for verification.
.Pp
+The options (if present) consist of comma-separated option specifications.
+No spaces are permitted, except within double quotes.
+The following option specifications are supported (note that option keywords
+are case-insensitive):
+.Bl -tag -width Ds
+.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"
+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.
+.El
+.Pp
+When verifying signatures made by certificates, the expected principal
+name must match both the principals pattern in the allowed signers file and
+the principals embedded in the certificate itself.
+.Pp
+An example allowed signers file:
+.Bd -literal -offset 3n
+# Comments allowed at start of line
+user1@example.com,user2@example.com ssh-rsa AAAAX1...
+# A certificate authority, trusted for all principals in a domain.
+*@example.com cert-authority ssh-ed25519 AAAB4...
+# A key that is accepted only for file signing.
+user2@example.com namespaces="file" ssh-ed25519 AAA41...
+.Ed
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev SSH_SK_PROVIDER
+Specifies a path to a library that will be used when loading any
+FIDO authenticator-hosted keys, overriding the default of using
+the built-in USB HID support.
+.El
+.Sh FILES
+.Bl -tag -width Ds -compact
.It Pa ~/.ssh/id_dsa
.It Pa ~/.ssh/id_ecdsa
+.It Pa ~/.ssh/id_ecdsa_sk
.It Pa ~/.ssh/id_ed25519
+.It Pa ~/.ssh/id_ed25519_sk
.It Pa ~/.ssh/id_rsa
-Contains the protocol version 2 DSA, ECDSA, Ed25519 or RSA
-authentication identity of the user.
+Contains the DSA, ECDSA, authenticator-hosted ECDSA, Ed25519,
+authenticator-hosted Ed25519 or RSA authentication identity of the user.
This file should not be readable by anyone but the user.
It is possible to
specify a passphrase when generating the key; that passphrase will be
@@ -827,10 +1146,12 @@ will read this file when a login attempt is made.
.Pp
.It Pa ~/.ssh/id_dsa.pub
.It Pa ~/.ssh/id_ecdsa.pub
+.It Pa ~/.ssh/id_ecdsa_sk.pub
.It Pa ~/.ssh/id_ed25519.pub
+.It Pa ~/.ssh/id_ed25519_sk.pub
.It Pa ~/.ssh/id_rsa.pub
-Contains the protocol version 2 DSA, ECDSA, Ed25519 or RSA
-public key for authentication.
+Contains the DSA, ECDSA, authenticator-hosted ECDSA, Ed25519,
+authenticator-hosted Ed25519 or RSA public key for authentication.
The contents of this file should be added to
.Pa ~/.ssh/authorized_keys
on all machines
diff --git a/ssh-keygen.c b/ssh-keygen.c
index a3c2362a..2c5c75db 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.266 2015/02/26 20:45:47 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.409.2.1 2020/05/18 19:02:13 benno Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -24,6 +24,9 @@
#include "openbsd-compat/openssl-compat.h"
#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
@@ -37,12 +40,12 @@
#include <string.h>
#include <unistd.h>
#include <limits.h>
+#include <locale.h>
+#include <time.h>
#include "xmalloc.h"
#include "sshkey.h"
-#include "rsa.h"
#include "authfile.h"
-#include "uuencode.h"
#include "sshbuf.h"
#include "pathnames.h"
#include "log.h"
@@ -57,171 +60,199 @@
#include "atomicio.h"
#include "krl.h"
#include "digest.h"
+#include "utf8.h"
+#include "authfd.h"
+#include "sshsig.h"
+#include "ssh-sk.h"
+#include "sk-api.h" /* XXX for SSH_SK_USER_PRESENCE_REQD; remove */
-/* Number of bits in the RSA/DSA key. This value can be set on the command line. */
-#define DEFAULT_BITS 2048
-#define DEFAULT_BITS_DSA 1024
-#define DEFAULT_BITS_ECDSA 256
-u_int32_t bits = 0;
-
-/*
- * Flag indicating that we just want to change the passphrase. This can be
- * set on the command line.
- */
-int change_passphrase = 0;
+#ifdef WITH_OPENSSL
+# define DEFAULT_KEY_TYPE_NAME "rsa"
+#else
+# define DEFAULT_KEY_TYPE_NAME "ed25519"
+#endif
/*
- * Flag indicating that we just want to change the comment. This can be set
- * on the command line.
+ * Default number of bits in the RSA, DSA and ECDSA keys. These value can be
+ * overridden on the command line.
+ *
+ * These values, with the exception of DSA, provide security equivalent to at
+ * least 128 bits of security according to NIST Special Publication 800-57:
+ * Recommendation for Key Management Part 1 rev 4 section 5.6.1.
+ * For DSA it (and FIPS-186-4 section 4.2) specifies that the only size for
+ * which a 160bit hash is acceptable is 1kbit, and since ssh-dss specifies only
+ * SHA1 we limit the DSA key size 1k bits.
*/
-int change_comment = 0;
-
-int quiet = 0;
-
-int log_level = SYSLOG_LEVEL_INFO;
-
-/* Flag indicating that we want to hash a known_hosts file */
-int hash_hosts = 0;
-/* Flag indicating that we want lookup a host in known_hosts file */
-int find_host = 0;
-/* Flag indicating that we want to delete a host from a known_hosts file */
-int delete_host = 0;
+#define DEFAULT_BITS 3072
+#define DEFAULT_BITS_DSA 1024
+#define DEFAULT_BITS_ECDSA 256
-/* Flag indicating that we want to show the contents of a certificate */
-int show_cert = 0;
+static int quiet = 0;
/* Flag indicating that we just want to see the key fingerprint */
-int print_fingerprint = 0;
-int print_bubblebabble = 0;
+static int print_fingerprint = 0;
+static int print_bubblebabble = 0;
/* Hash algorithm to use for fingerprints. */
-int fingerprint_hash = SSH_FP_HASH_DEFAULT;
+static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
/* The identity file name, given on the command line or entered by the user. */
-char identity_file[1024];
-int have_identity = 0;
+static char identity_file[PATH_MAX];
+static int have_identity = 0;
/* This is set to the passphrase if given on the command line. */
-char *identity_passphrase = NULL;
+static char *identity_passphrase = NULL;
/* This is set to the new passphrase if given on the command line. */
-char *identity_new_passphrase = NULL;
-
-/* This is set to the new comment if given on the command line. */
-char *identity_comment = NULL;
-
-/* Path to CA key when certifying keys. */
-char *ca_key_path = NULL;
-
-/* Certificate serial number */
-unsigned long long cert_serial = 0;
+static char *identity_new_passphrase = NULL;
/* Key type when certifying */
-u_int cert_key_type = SSH2_CERT_TYPE_USER;
+static u_int cert_key_type = SSH2_CERT_TYPE_USER;
/* "key ID" of signed key */
-char *cert_key_id = NULL;
+static char *cert_key_id = NULL;
/* Comma-separated list of principal names for certifying keys */
-char *cert_principals = NULL;
+static char *cert_principals = NULL;
/* Validity period for certificates */
-u_int64_t cert_valid_from = 0;
-u_int64_t cert_valid_to = ~0ULL;
+static u_int64_t cert_valid_from = 0;
+static u_int64_t cert_valid_to = ~0ULL;
/* Certificate options */
-#define CERTOPT_X_FWD (1)
-#define CERTOPT_AGENT_FWD (1<<1)
-#define CERTOPT_PORT_FWD (1<<2)
-#define CERTOPT_PTY (1<<3)
-#define CERTOPT_USER_RC (1<<4)
+#define CERTOPT_X_FWD (1)
+#define CERTOPT_AGENT_FWD (1<<1)
+#define CERTOPT_PORT_FWD (1<<2)
+#define CERTOPT_PTY (1<<3)
+#define CERTOPT_USER_RC (1<<4)
+#define CERTOPT_NO_REQUIRE_USER_PRESENCE (1<<5)
#define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \
CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC)
-u_int32_t certflags_flags = CERTOPT_DEFAULT;
-char *certflags_command = NULL;
-char *certflags_src_addr = NULL;
+static u_int32_t certflags_flags = CERTOPT_DEFAULT;
+static char *certflags_command = NULL;
+static char *certflags_src_addr = NULL;
+
+/* Arbitrary extensions specified by user */
+struct cert_userext {
+ char *key;
+ char *val;
+ int crit;
+};
+static struct cert_userext *cert_userext;
+static size_t ncert_userext;
/* Conversion to/from various formats */
-int convert_to = 0;
-int convert_from = 0;
enum {
FMT_RFC4716,
FMT_PKCS8,
FMT_PEM
} convert_format = FMT_RFC4716;
-int print_public = 0;
-int print_generic = 0;
-char *key_type_name = NULL;
+static char *key_type_name = NULL;
/* Load key from this PKCS#11 provider */
-char *pkcs11provider = NULL;
+static char *pkcs11provider = NULL;
-/* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */
-int use_new_format = 0;
+/* FIDO/U2F provider to use */
+static char *sk_provider = NULL;
+
+/* Format for writing private keys */
+static int private_key_format = SSHKEY_PRIVATE_OPENSSH;
/* Cipher for new-format private keys */
-char *new_format_cipher = NULL;
+static char *openssh_format_cipher = NULL;
-/*
- * Number of KDF rounds to derive new format keys /
- * number of primality trials when screening moduli.
- */
-int rounds = 0;
+/* Number of KDF rounds to derive new format keys. */
+static int rounds = 0;
/* argv0 */
extern char *__progname;
-char hostname[NI_MAXHOST];
+static char hostname[NI_MAXHOST];
+#ifdef WITH_OPENSSL
/* moduli.c */
int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long,
unsigned long);
+#endif
static void
type_bits_valid(int type, const char *name, u_int32_t *bitsp)
{
-#ifdef WITH_OPENSSL
- u_int maxbits;
- int nid;
-#endif
-
- if (type == KEY_UNSPEC) {
- fprintf(stderr, "unknown key type %s\n", key_type_name);
- exit(1);
- }
+ if (type == KEY_UNSPEC)
+ fatal("unknown key type %s", key_type_name);
if (*bitsp == 0) {
#ifdef WITH_OPENSSL
- if (type == KEY_DSA)
+ u_int nid;
+
+ switch(type) {
+ case KEY_DSA:
*bitsp = DEFAULT_BITS_DSA;
- else if (type == KEY_ECDSA) {
+ break;
+ case KEY_ECDSA:
if (name != NULL &&
(nid = sshkey_ecdsa_nid_from_name(name)) > 0)
*bitsp = sshkey_curve_nid_to_bits(nid);
if (*bitsp == 0)
*bitsp = DEFAULT_BITS_ECDSA;
- } else
-#endif
+ break;
+ case KEY_RSA:
*bitsp = DEFAULT_BITS;
+ break;
+ }
+#endif
}
#ifdef WITH_OPENSSL
- maxbits = (type == KEY_DSA) ?
- OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS;
- if (*bitsp > maxbits) {
- fprintf(stderr, "key bits exceeds maximum %d\n", maxbits);
- exit(1);
+ switch (type) {
+ case KEY_DSA:
+ if (*bitsp != 1024)
+ fatal("Invalid DSA key length: must be 1024 bits");
+ break;
+ case KEY_RSA:
+ if (*bitsp < SSH_RSA_MINIMUM_MODULUS_SIZE)
+ fatal("Invalid RSA key length: minimum is %d bits",
+ SSH_RSA_MINIMUM_MODULUS_SIZE);
+ else if (*bitsp > OPENSSL_RSA_MAX_MODULUS_BITS)
+ fatal("Invalid RSA key length: maximum is %d bits",
+ OPENSSL_RSA_MAX_MODULUS_BITS);
+ break;
+ case KEY_ECDSA:
+ if (sshkey_ecdsa_bits_to_nid(*bitsp) == -1)
+ fatal("Invalid ECDSA key length: valid lengths are "
+#ifdef OPENSSL_HAS_NISTP521
+ "256, 384 or 521 bits");
+#else
+ "256 or 384 bits");
+#endif
}
- if (type == KEY_DSA && *bitsp != 1024)
- fatal("DSA keys must be 1024 bits");
- else if (type != KEY_ECDSA && type != KEY_ED25519 && *bitsp < 768)
- fatal("Key must at least be 768 bits");
- else if (type == KEY_ECDSA && sshkey_ecdsa_bits_to_nid(*bitsp) == -1)
- fatal("Invalid ECDSA key length - valid lengths are "
- "256, 384 or 521 bits");
#endif
}
+/*
+ * Checks whether a file exists and, if so, asks the user whether they wish
+ * to overwrite it.
+ * Returns nonzero if the file does not already exist or if the user agrees to
+ * overwrite, or zero otherwise.
+ */
+static int
+confirm_overwrite(const char *filename)
+{
+ char yesno[3];
+ struct stat st;
+
+ if (stat(filename, &st) != 0)
+ return 1;
+ printf("%s already exists.\n", filename);
+ printf("Overwrite (y/n)? ");
+ fflush(stdout);
+ if (fgets(yesno, sizeof(yesno), stdin) == NULL)
+ return 0;
+ if (yesno[0] != 'y' && yesno[0] != 'Y')
+ return 0;
+ return 1;
+}
+
static void
ask_filename(struct passwd *pw, const char *prompt)
{
@@ -232,11 +263,7 @@ ask_filename(struct passwd *pw, const char *prompt)
name = _PATH_SSH_CLIENT_ID_RSA;
else {
switch (sshkey_type_from_name(key_type_name)) {
- case KEY_RSA1:
- name = _PATH_SSH_CLIENT_IDENTITY;
- break;
case KEY_DSA_CERT:
- case KEY_DSA_CERT_V00:
case KEY_DSA:
name = _PATH_SSH_CLIENT_ID_DSA;
break;
@@ -245,9 +272,12 @@ ask_filename(struct passwd *pw, const char *prompt)
case KEY_ECDSA:
name = _PATH_SSH_CLIENT_ID_ECDSA;
break;
+ case KEY_ECDSA_SK_CERT:
+ case KEY_ECDSA_SK:
+ name = _PATH_SSH_CLIENT_ID_ECDSA_SK;
+ break;
#endif
case KEY_RSA_CERT:
- case KEY_RSA_CERT_V00:
case KEY_RSA:
name = _PATH_SSH_CLIENT_ID_RSA;
break;
@@ -255,14 +285,22 @@ ask_filename(struct passwd *pw, const char *prompt)
case KEY_ED25519_CERT:
name = _PATH_SSH_CLIENT_ID_ED25519;
break;
- default:
- fprintf(stderr, "bad key type\n");
- exit(1);
+ case KEY_ED25519_SK:
+ case KEY_ED25519_SK_CERT:
+ name = _PATH_SSH_CLIENT_ID_ED25519_SK;
+ break;
+ case KEY_XMSS:
+ case KEY_XMSS_CERT:
+ name = _PATH_SSH_CLIENT_ID_XMSS;
break;
+ default:
+ fatal("bad key type");
}
}
- snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name);
- fprintf(stderr, "%s (%s): ", prompt, identity_file);
+ snprintf(identity_file, sizeof(identity_file),
+ "%s/%s", pw->pw_dir, name);
+ printf("%s (%s): ", prompt, identity_file);
+ fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL)
exit(1);
buf[strcspn(buf, "\n")] = '\0';
@@ -272,13 +310,15 @@ ask_filename(struct passwd *pw, const char *prompt)
}
static struct sshkey *
-load_identity(char *filename)
+load_identity(const char *filename, char **commentp)
{
char *pass;
struct sshkey *prv;
int r;
- if ((r = sshkey_load_private(filename, "", &prv, NULL)) == 0)
+ if (commentp != NULL)
+ *commentp = NULL;
+ 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));
@@ -286,9 +326,8 @@ load_identity(char *filename)
pass = xstrdup(identity_passphrase);
else
pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN);
- r = sshkey_load_private(filename, pass, &prv, NULL);
- explicit_bzero(pass, strlen(pass));
- free(pass);
+ r = sshkey_load_private(filename, pass, &prv, commentp);
+ freezero(pass, strlen(pass));
if (r != 0)
fatal("Load key \"%s\": %s", filename, ssh_err(r));
return prv;
@@ -303,31 +342,30 @@ load_identity(char *filename)
static void
do_convert_to_ssh2(struct passwd *pw, struct sshkey *k)
{
- size_t len;
- u_char *blob;
- char comment[61];
+ struct sshbuf *b;
+ char comment[61], *b64;
int r;
- if (k->type == KEY_RSA1) {
- fprintf(stderr, "version 1 keys are not supported\n");
- exit(1);
- }
- if ((r = sshkey_to_blob(k, &blob, &len)) != 0) {
- fprintf(stderr, "key_to_blob failed: %s\n", ssh_err(r));
- exit(1);
- }
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshkey_putb(k, b)) != 0)
+ fatal("key_to_blob failed: %s", ssh_err(r));
+ if ((b64 = sshbuf_dtob64_string(b, 1)) == NULL)
+ fatal("%s: sshbuf_dtob64_string failed", __func__);
+
/* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */
snprintf(comment, sizeof(comment),
"%u-bit %s, converted by %s@%s from OpenSSH",
sshkey_size(k), sshkey_type(k),
pw->pw_name, hostname);
+ sshkey_free(k);
+ sshbuf_free(b);
+
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
- fprintf(stdout, "Comment: \"%s\"\n", comment);
- dump_base64(stdout, blob, len);
+ fprintf(stdout, "Comment: \"%s\"\n%s", comment, b64);
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
- sshkey_free(k);
- free(blob);
+ free(b64);
exit(0);
}
@@ -335,7 +373,6 @@ static void
do_convert_to_pkcs8(struct sshkey *k)
{
switch (sshkey_type_plain(k->type)) {
- case KEY_RSA1:
case KEY_RSA:
if (!PEM_write_RSA_PUBKEY(stdout, k->rsa))
fatal("PEM_write_RSA_PUBKEY failed");
@@ -360,18 +397,20 @@ static void
do_convert_to_pem(struct sshkey *k)
{
switch (sshkey_type_plain(k->type)) {
- case KEY_RSA1:
case KEY_RSA:
if (!PEM_write_RSAPublicKey(stdout, k->rsa))
fatal("PEM_write_RSAPublicKey failed");
break;
-#if notyet /* OpenSSH 0.9.8 lacks this function */
case KEY_DSA:
- if (!PEM_write_DSAPublicKey(stdout, k->dsa))
- fatal("PEM_write_DSAPublicKey failed");
+ if (!PEM_write_DSA_PUBKEY(stdout, k->dsa))
+ fatal("PEM_write_DSA_PUBKEY failed");
+ break;
+#ifdef OPENSSL_HAS_ECC
+ case KEY_ECDSA:
+ if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa))
+ fatal("PEM_write_EC_PUBKEY failed");
break;
#endif
- /* XXX ECDSA? */
default:
fatal("%s: unsupported key type %s", __func__, sshkey_type(k));
}
@@ -387,10 +426,10 @@ do_convert_to(struct passwd *pw)
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
- if (stat(identity_file, &st) < 0)
+ if (stat(identity_file, &st) == -1)
fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
if ((r = sshkey_load_public(identity_file, &k, NULL)) != 0)
- k = load_identity(identity_file);
+ k = load_identity(identity_file, NULL);
switch (convert_format) {
case FMT_RFC4716:
do_convert_to_ssh2(pw, k);
@@ -430,9 +469,8 @@ buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value)
}
static struct sshkey *
-do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
+do_convert_private_ssh2(struct sshbuf *b)
{
- struct sshbuf *b;
struct sshkey *key = NULL;
char *type, *cipher;
u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345";
@@ -440,16 +478,17 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
u_int magic, i1, i2, i3, i4;
size_t slen;
u_long e;
+ BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
+ BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL;
+ BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
+ BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL;
- if ((b = sshbuf_from(blob, blen)) == NULL)
- fatal("%s: sshbuf_from failed", __func__);
if ((r = sshbuf_get_u32(b, &magic)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
error("bad magic 0x%x != 0x%x", magic,
SSH_COM_PRIVATE_KEY_MAGIC);
- sshbuf_free(b);
return NULL;
}
if ((r = sshbuf_get_u32(b, &i1)) != 0 ||
@@ -463,7 +502,6 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
if (strcmp(cipher, "none") != 0) {
error("unsupported cipher %s", cipher);
free(cipher);
- sshbuf_free(b);
free(type);
return NULL;
}
@@ -474,21 +512,32 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
} else if (strstr(type, "rsa")) {
ktype = KEY_RSA;
} else {
- sshbuf_free(b);
free(type);
return NULL;
}
- if ((key = sshkey_new_private(ktype)) == NULL)
- fatal("key_new_private failed");
+ if ((key = sshkey_new(ktype)) == NULL)
+ fatal("sshkey_new failed");
free(type);
switch (key->type) {
case KEY_DSA:
- buffer_get_bignum_bits(b, key->dsa->p);
- buffer_get_bignum_bits(b, key->dsa->g);
- buffer_get_bignum_bits(b, key->dsa->q);
- buffer_get_bignum_bits(b, key->dsa->pub_key);
- buffer_get_bignum_bits(b, key->dsa->priv_key);
+ if ((dsa_p = BN_new()) == NULL ||
+ (dsa_q = BN_new()) == NULL ||
+ (dsa_g = BN_new()) == NULL ||
+ (dsa_pub_key = BN_new()) == NULL ||
+ (dsa_priv_key = BN_new()) == NULL)
+ fatal("%s: BN_new", __func__);
+ buffer_get_bignum_bits(b, dsa_p);
+ buffer_get_bignum_bits(b, dsa_g);
+ buffer_get_bignum_bits(b, dsa_q);
+ buffer_get_bignum_bits(b, dsa_pub_key);
+ buffer_get_bignum_bits(b, dsa_priv_key);
+ if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g))
+ fatal("%s: DSA_set0_pqg failed", __func__);
+ dsa_p = dsa_q = dsa_g = NULL; /* transferred */
+ if (!DSA_set0_key(key->dsa, dsa_pub_key, dsa_priv_key))
+ fatal("%s: DSA_set0_key failed", __func__);
+ dsa_pub_key = dsa_priv_key = NULL; /* transferred */
break;
case KEY_RSA:
if ((r = sshbuf_get_u8(b, &e1)) != 0 ||
@@ -505,29 +554,44 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
e += e3;
debug("e %lx", e);
}
- if (!BN_set_word(key->rsa->e, e)) {
- sshbuf_free(b);
+ if ((rsa_e = BN_new()) == NULL)
+ fatal("%s: BN_new", __func__);
+ if (!BN_set_word(rsa_e, e)) {
+ BN_clear_free(rsa_e);
sshkey_free(key);
return NULL;
}
- buffer_get_bignum_bits(b, key->rsa->d);
- buffer_get_bignum_bits(b, key->rsa->n);
- buffer_get_bignum_bits(b, key->rsa->iqmp);
- buffer_get_bignum_bits(b, key->rsa->q);
- buffer_get_bignum_bits(b, key->rsa->p);
- if ((r = rsa_generate_additional_parameters(key->rsa)) != 0)
+ if ((rsa_n = BN_new()) == NULL ||
+ (rsa_d = BN_new()) == NULL ||
+ (rsa_p = BN_new()) == NULL ||
+ (rsa_q = BN_new()) == NULL ||
+ (rsa_iqmp = BN_new()) == NULL)
+ fatal("%s: BN_new", __func__);
+ buffer_get_bignum_bits(b, rsa_d);
+ buffer_get_bignum_bits(b, rsa_n);
+ buffer_get_bignum_bits(b, rsa_iqmp);
+ buffer_get_bignum_bits(b, rsa_q);
+ buffer_get_bignum_bits(b, rsa_p);
+ if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, rsa_d))
+ fatal("%s: RSA_set0_key failed", __func__);
+ rsa_n = rsa_e = rsa_d = NULL; /* transferred */
+ if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q))
+ fatal("%s: RSA_set0_factors failed", __func__);
+ rsa_p = rsa_q = NULL; /* transferred */
+ if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0)
fatal("generate RSA parameters failed: %s", ssh_err(r));
+ BN_clear_free(rsa_iqmp);
break;
}
rlen = sshbuf_len(b);
if (rlen != 0)
- error("do_convert_private_ssh2_from_blob: "
- "remaining bytes in key blob %d", rlen);
- sshbuf_free(b);
+ error("%s: remaining bytes in key blob %d", __func__, rlen);
/* try the key */
- if (sshkey_sign(key, &sig, &slen, data, sizeof(data), 0) != 0 ||
- sshkey_verify(key, sig, slen, data, sizeof(data), 0) != 0) {
+ if (sshkey_sign(key, &sig, &slen, data, sizeof(data),
+ NULL, NULL, 0) != 0 ||
+ sshkey_verify(key, sig, slen, data, sizeof(data),
+ NULL, 0, NULL) != 0) {
sshkey_free(key);
free(sig);
return NULL;
@@ -544,17 +608,13 @@ get_line(FILE *fp, char *line, size_t len)
line[0] = '\0';
while ((c = fgetc(fp)) != EOF) {
- if (pos >= len - 1) {
- fprintf(stderr, "input line too long.\n");
- exit(1);
- }
+ if (pos >= len - 1)
+ fatal("input line too long.");
switch (c) {
case '\r':
c = fgetc(fp);
- if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) {
- fprintf(stderr, "unget: %s\n", strerror(errno));
- exit(1);
- }
+ if (c != EOF && c != '\n' && ungetc(c, fp) == EOF)
+ fatal("unget: %s", strerror(errno));
return pos;
case '\n':
return pos;
@@ -572,10 +632,12 @@ do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private)
int r, blen, escaped = 0;
u_int len;
char line[1024];
- u_char blob[8096];
+ struct sshbuf *buf;
char encoded[8096];
FILE *fp;
+ if ((buf = sshbuf_new()) == NULL)
+ fatal("sshbuf_new failed");
if ((fp = fopen(identity_file, "r")) == NULL)
fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
encoded[0] = '\0';
@@ -605,17 +667,14 @@ do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private)
(encoded[len-2] == '=') &&
(encoded[len-3] == '='))
encoded[len-3] = '\0';
- blen = uudecode(encoded, blob, sizeof(blob));
- if (blen < 0) {
- fprintf(stderr, "uudecode failed.\n");
- exit(1);
- }
- if (*private)
- *k = do_convert_private_ssh2_from_blob(blob, blen);
- else if ((r = sshkey_from_blob(blob, blen, k)) != 0) {
- fprintf(stderr, "decode blob failed: %s\n", ssh_err(r));
- exit(1);
- }
+ if ((r = sshbuf_b64tod(buf, encoded)) != 0)
+ fatal("%s: base64 decoding failed: %s", __func__, ssh_err(r));
+ if (*private) {
+ if ((*k = do_convert_private_ssh2(buf)) == NULL)
+ fatal("%s: private key conversion failed", __func__);
+ } else if ((r = sshkey_fromb(buf, k)) != 0)
+ fatal("decode blob failed: %s", ssh_err(r));
+ sshbuf_free(buf);
fclose(fp);
}
@@ -632,7 +691,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private)
identity_file);
}
fclose(fp);
- switch (EVP_PKEY_type(pubkey->type)) {
+ switch (EVP_PKEY_base_id(pubkey)) {
case EVP_PKEY_RSA:
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
fatal("sshkey_new failed");
@@ -656,7 +715,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private)
#endif
default:
fatal("%s: unsupported pubkey type %d", __func__,
- EVP_PKEY_type(pubkey->type));
+ EVP_PKEY_base_id(pubkey));
}
EVP_PKEY_free(pubkey);
return;
@@ -667,9 +726,6 @@ do_convert_from_pem(struct sshkey **k, int *private)
{
FILE *fp;
RSA *rsa;
-#ifdef notyet
- DSA *dsa;
-#endif
if ((fp = fopen(identity_file, "r")) == NULL)
fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
@@ -681,18 +737,6 @@ do_convert_from_pem(struct sshkey **k, int *private)
fclose(fp);
return;
}
-#if notyet /* OpenSSH 0.9.8 lacks this function */
- rewind(fp);
- if ((dsa = PEM_read_DSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
- if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
- fatal("sshkey_new failed");
- (*k)->type = KEY_DSA;
- (*k)->dsa = dsa;
- fclose(fp);
- return;
- }
- /* XXX ECDSA */
-#endif
fatal("%s: unrecognised raw private key format", __func__);
}
@@ -705,7 +749,7 @@ do_convert_from(struct passwd *pw)
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
- if (stat(identity_file, &st) < 0)
+ if (stat(identity_file, &st) == -1)
fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
switch (convert_format) {
@@ -749,10 +793,8 @@ do_convert_from(struct passwd *pw)
}
}
- if (!ok) {
- fprintf(stderr, "key write failed\n");
- exit(1);
- }
+ if (!ok)
+ fatal("key write failed");
sshkey_free(k);
exit(0);
}
@@ -764,18 +806,20 @@ do_print_public(struct passwd *pw)
struct sshkey *prv;
struct stat st;
int r;
+ char *comment = NULL;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
- if (stat(identity_file, &st) < 0) {
- perror(identity_file);
- exit(1);
- }
- prv = load_identity(identity_file);
+ if (stat(identity_file, &st) == -1)
+ fatal("%s: %s", identity_file, strerror(errno));
+ prv = load_identity(identity_file, &comment);
if ((r = sshkey_write(prv, stdout)) != 0)
- fprintf(stderr, "key_write failed: %s", ssh_err(r));
+ error("sshkey_write failed: %s", ssh_err(r));
sshkey_free(prv);
+ if (comment != NULL && *comment != '\0')
+ fprintf(stdout, " %s", comment);
fprintf(stdout, "\n");
+ free(comment);
exit(0);
}
@@ -787,13 +831,13 @@ do_download(struct passwd *pw)
int i, nkeys;
enum sshkey_fp_rep rep;
int fptype;
- char *fp, *ra;
+ char *fp, *ra, **comments = NULL;
fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
- pkcs11_init(0);
- nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
+ pkcs11_init(1);
+ nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys, &comments);
if (nkeys <= 0)
fatal("cannot read public key from pkcs11");
for (i = 0; i < nkeys; i++) {
@@ -805,16 +849,19 @@ do_download(struct passwd *pw)
fatal("%s: sshkey_fingerprint fail", __func__);
printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]),
fp, sshkey_type(keys[i]));
- if (log_level >= SYSLOG_LEVEL_VERBOSE)
+ if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
printf("%s\n", ra);
free(ra);
free(fp);
} else {
(void) sshkey_write(keys[i], stdout); /* XXX check */
- fprintf(stdout, "\n");
+ fprintf(stdout, "%s%s\n",
+ *(comments[i]) == '\0' ? "" : " ", comments[i]);
}
+ free(comments[i]);
sshkey_free(keys[i]);
}
+ free(comments);
free(keys);
pkcs11_terminate();
exit(0);
@@ -823,120 +870,162 @@ do_download(struct passwd *pw)
#endif /* ENABLE_PKCS11 */
}
+static struct sshkey *
+try_read_key(char **cpp)
+{
+ struct sshkey *ret;
+ int r;
+
+ if ((ret = sshkey_new(KEY_UNSPEC)) == NULL)
+ fatal("sshkey_new failed");
+ if ((r = sshkey_read(ret, cpp)) == 0)
+ return ret;
+ /* Not a key */
+ sshkey_free(ret);
+ return NULL;
+}
+
static void
-do_fingerprint(struct passwd *pw)
+fingerprint_one_key(const struct sshkey *public, const char *comment)
{
- FILE *f;
- struct sshkey *public;
- char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra;
- int r, i, skip = 0, num = 0, invalid = 1;
+ char *fp = NULL, *ra = NULL;
enum sshkey_fp_rep rep;
int fptype;
- struct stat st;
fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
- if (!have_identity)
- ask_filename(pw, "Enter file in which the key is");
- if (stat(identity_file, &st) < 0) {
- perror(identity_file);
- exit(1);
- }
- if ((r = sshkey_load_public(identity_file, &public, &comment)) != 0)
- debug2("Error loading public key \"%s\": %s",
- identity_file, ssh_err(r));
- else {
- fp = sshkey_fingerprint(public, fptype, rep);
- ra = sshkey_fingerprint(public, fingerprint_hash,
- SSH_FP_RANDOMART);
- if (fp == NULL || ra == NULL)
- fatal("%s: sshkey_fingerprint fail", __func__);
- printf("%u %s %s (%s)\n", sshkey_size(public), fp, comment,
- sshkey_type(public));
- if (log_level >= SYSLOG_LEVEL_VERBOSE)
- printf("%s\n", ra);
- sshkey_free(public);
- free(comment);
- free(ra);
- free(fp);
- exit(0);
- }
- if (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__);
+ mprintf("%u %s %s (%s)\n", sshkey_size(public), fp,
+ comment ? comment : "no comment", sshkey_type(public));
+ if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
+ printf("%s\n", ra);
+ free(ra);
+ free(fp);
+}
+
+static void
+fingerprint_private(const char *path)
+{
+ struct stat st;
+ char *comment = NULL;
+ struct sshkey *privkey = NULL, *pubkey = NULL;
+ int r;
+
+ 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));
+ if (pubkey == NULL || comment == NULL || *comment == '\0') {
free(comment);
- comment = NULL;
+ if ((r = sshkey_load_private(path, NULL,
+ &privkey, &comment)) != 0)
+ debug("load private \"%s\": %s", path, ssh_err(r));
}
+ if (pubkey == NULL && privkey == NULL)
+ fatal("%s is not a key file.", path);
- if ((f = fopen(identity_file, "r")) == NULL)
- fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
+ fingerprint_one_key(pubkey == NULL ? privkey : pubkey, comment);
+ sshkey_free(pubkey);
+ sshkey_free(privkey);
+ free(comment);
+}
+
+static void
+do_fingerprint(struct passwd *pw)
+{
+ FILE *f;
+ struct sshkey *public = NULL;
+ char *comment = NULL, *cp, *ep, *line = NULL;
+ size_t linesize = 0;
+ int i, invalid = 1;
+ const char *path;
+ u_long lnum = 0;
- while (fgets(line, sizeof(line), f)) {
- if ((cp = strchr(line, '\n')) == NULL) {
- error("line %d too long: %.40s...",
- num + 1, line);
- skip = 1;
+ if (!have_identity)
+ ask_filename(pw, "Enter file in which the key is");
+ path = identity_file;
+
+ if (strcmp(identity_file, "-") == 0) {
+ f = stdin;
+ path = "(stdin)";
+ } else if ((f = fopen(path, "r")) == NULL)
+ fatal("%s: %s: %s", __progname, path, strerror(errno));
+
+ while (getline(&line, &linesize, f) != -1) {
+ lnum++;
+ cp = line;
+ cp[strcspn(cp, "\n")] = '\0';
+ /* Trim leading space and comments */
+ cp = line + strspn(line, " \t");
+ if (*cp == '#' || *cp == '\0')
continue;
+
+ /*
+ * Input may be plain keys, private keys, authorized_keys
+ * or known_hosts.
+ */
+
+ /*
+ * Try private keys first. Assume a key is private if
+ * "SSH PRIVATE KEY" appears on the first line and we're
+ * not reading from stdin (XXX support private keys on stdin).
+ */
+ if (lnum == 1 && strcmp(identity_file, "-") != 0 &&
+ strstr(cp, "PRIVATE KEY") != NULL) {
+ free(line);
+ fclose(f);
+ fingerprint_private(path);
+ exit(0);
+ }
+
+ /*
+ * If it's not a private key, then this must be prepared to
+ * accept a public key prefixed with a hostname or options.
+ * Try a bare key first, otherwise skip the leading stuff.
+ */
+ if ((public = try_read_key(&cp)) == NULL) {
+ i = strtol(cp, &ep, 10);
+ if (i == 0 || ep == NULL ||
+ (*ep != ' ' && *ep != '\t')) {
+ int quoted = 0;
+
+ comment = cp;
+ for (; *cp && (quoted || (*cp != ' ' &&
+ *cp != '\t')); cp++) {
+ if (*cp == '\\' && cp[1] == '"')
+ cp++; /* Skip both */
+ else if (*cp == '"')
+ quoted = !quoted;
+ }
+ if (!*cp)
+ continue;
+ *cp++ = '\0';
+ }
}
- num++;
- if (skip) {
- skip = 0;
+ /* Retry after parsing leading hostname/key options */
+ if (public == NULL && (public = try_read_key(&cp)) == NULL) {
+ debug("%s:%lu: not a public key", path, lnum);
continue;
}
- *cp = '\0';
- /* Skip leading whitespace, empty and comment lines. */
- for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+ /* Find trailing comment, if any */
+ for (; *cp == ' ' || *cp == '\t'; cp++)
;
- if (!*cp || *cp == '\n' || *cp == '#')
- continue;
- i = strtol(cp, &ep, 10);
- if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
- int quoted = 0;
+ if (*cp != '\0' && *cp != '#')
comment = cp;
- for (; *cp && (quoted || (*cp != ' ' &&
- *cp != '\t')); cp++) {
- if (*cp == '\\' && cp[1] == '"')
- cp++; /* Skip both */
- else if (*cp == '"')
- quoted = !quoted;
- }
- if (!*cp)
- continue;
- *cp++ = '\0';
- }
- ep = cp;
- if ((public = sshkey_new(KEY_RSA1)) == NULL)
- fatal("sshkey_new failed");
- if ((r = sshkey_read(public, &cp)) != 0) {
- cp = ep;
- sshkey_free(public);
- if ((public = sshkey_new(KEY_UNSPEC)) == NULL)
- fatal("sshkey_new failed");
- if ((r = sshkey_read(public, &cp)) != 0) {
- sshkey_free(public);
- continue;
- }
- }
- comment = *cp ? cp : 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 fail", __func__);
- printf("%u %s %s (%s)\n", sshkey_size(public), fp,
- comment ? comment : "no comment", sshkey_type(public));
- if (log_level >= SYSLOG_LEVEL_VERBOSE)
- printf("%s\n", ra);
- free(ra);
- free(fp);
+
+ fingerprint_one_key(public, comment);
sshkey_free(public);
- invalid = 0;
+ invalid = 0; /* One good key in the file is sufficient */
}
fclose(f);
+ free(line);
- if (invalid) {
- printf("%s is not a public key file.\n", identity_file);
- exit(1);
- }
+ if (invalid)
+ fatal("%s is not a public key file.", path);
exit(0);
}
@@ -948,33 +1037,55 @@ do_gen_all_hostkeys(struct passwd *pw)
char *key_type_display;
char *path;
} key_types[] = {
- { "rsa1", "RSA1", _PATH_HOST_KEY_FILE },
+#ifdef WITH_OPENSSL
{ "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE },
{ "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE },
#ifdef OPENSSL_HAS_ECC
{ "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE },
-#endif
+#endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
{ "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE },
+#ifdef WITH_XMSS
+ { "xmss", "XMSS",_PATH_HOST_XMSS_KEY_FILE },
+#endif /* WITH_XMSS */
{ NULL, NULL, NULL }
};
+ u_int32_t bits = 0;
int first = 0;
struct stat st;
struct sshkey *private, *public;
- char comment[1024];
+ char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file;
int i, type, fd, r;
- FILE *f;
for (i = 0; key_types[i].key_type; i++) {
- if (stat(key_types[i].path, &st) == 0)
- continue;
- if (errno != ENOENT) {
- printf("Could not stat %s: %s", key_types[i].path,
+ public = private = NULL;
+ prv_tmp = pub_tmp = prv_file = pub_file = NULL;
+
+ xasprintf(&prv_file, "%s%s",
+ identity_file, key_types[i].path);
+
+ /* Check whether private key exists and is not zero-length */
+ if (stat(prv_file, &st) == 0) {
+ if (st.st_size != 0)
+ goto next;
+ } else if (errno != ENOENT) {
+ error("Could not stat %s: %s", key_types[i].path,
strerror(errno));
- first = 0;
- continue;
+ goto failnext;
}
+ /*
+ * Private key doesn't exist or is invalid; proceed with
+ * key generation.
+ */
+ xasprintf(&prv_tmp, "%s%s.XXXXXXXXXX",
+ identity_file, key_types[i].path);
+ xasprintf(&pub_tmp, "%s%s.pub.XXXXXXXXXX",
+ identity_file, key_types[i].path);
+ xasprintf(&pub_file, "%s%s.pub",
+ identity_file, key_types[i].path);
+
if (first == 0) {
first = 1;
printf("%s: generating new host keys: ", __progname);
@@ -982,57 +1093,62 @@ do_gen_all_hostkeys(struct passwd *pw)
printf("%s ", key_types[i].key_type_display);
fflush(stdout);
type = sshkey_type_from_name(key_types[i].key_type);
- strlcpy(identity_file, key_types[i].path, sizeof(identity_file));
+ if ((fd = mkstemp(prv_tmp)) == -1) {
+ error("Could not save your private key in %s: %s",
+ prv_tmp, strerror(errno));
+ goto failnext;
+ }
+ (void)close(fd); /* just using mkstemp() to reserve a name */
bits = 0;
type_bits_valid(type, NULL, &bits);
if ((r = sshkey_generate(type, bits, &private)) != 0) {
- fprintf(stderr, "key_generate failed: %s\n",
- ssh_err(r));
- first = 0;
- continue;
+ error("sshkey_generate failed: %s", ssh_err(r));
+ goto failnext;
}
if ((r = sshkey_from_private(private, &public)) != 0)
fatal("sshkey_from_private failed: %s", ssh_err(r));
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
hostname);
- if ((r = sshkey_save_private(private, identity_file, "",
- comment, use_new_format, new_format_cipher, rounds)) != 0) {
- printf("Saving key \"%s\" failed: %s\n", identity_file,
- ssh_err(r));
- sshkey_free(private);
- sshkey_free(public);
- first = 0;
- continue;
+ 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));
+ goto failnext;
}
- sshkey_free(private);
- strlcat(identity_file, ".pub", sizeof(identity_file));
- fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (fd == -1) {
- printf("Could not save your public key in %s\n",
- identity_file);
- sshkey_free(public);
- first = 0;
- continue;
+ if ((fd = mkstemp(pub_tmp)) == -1) {
+ error("Could not save your public key in %s: %s",
+ pub_tmp, strerror(errno));
+ goto failnext;
}
- f = fdopen(fd, "w");
- if (f == NULL) {
- printf("fdopen %s failed\n", identity_file);
- close(fd);
- sshkey_free(public);
- first = 0;
- continue;
+ (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));
+ goto failnext;
}
- if ((r = sshkey_write(public, f)) != 0) {
- fprintf(stderr, "write key failed: %s\n", ssh_err(r));
- fclose(f);
- sshkey_free(public);
+
+ /* Rename temporary files to their permanent locations. */
+ if (rename(pub_tmp, pub_file) != 0) {
+ error("Unable to move %s into position: %s",
+ pub_file, strerror(errno));
+ goto failnext;
+ }
+ if (rename(prv_tmp, prv_file) != 0) {
+ error("Unable to move %s into position: %s",
+ key_types[i].path, strerror(errno));
+ failnext:
first = 0;
- continue;
+ goto next;
}
- fprintf(f, " %s\n", comment);
- fclose(f);
+ next:
+ sshkey_free(private);
sshkey_free(public);
-
+ free(prv_tmp);
+ free(pub_tmp);
+ free(prv_file);
+ free(pub_file);
}
if (first != 0)
printf("\n");
@@ -1044,6 +1160,9 @@ struct known_hosts_ctx {
int has_unhashed; /* When hashing, original had unhashed hosts */
int found_key; /* For find/delete, host was found */
int invalid; /* File contained invalid items; don't delete */
+ int hash_hosts; /* Hash hostnames as we go */
+ int find_host; /* Search for specific hostname */
+ int delete_host; /* Delete host from known_hosts */
};
static int
@@ -1052,6 +1171,7 @@ known_hosts_hash(struct hostkey_foreach_line *l, void *_ctx)
struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
char *hashed, *cp, *hosts, *ohosts;
int has_wild = l->hosts && strcspn(l->hosts, "*?!") != strlen(l->hosts);
+ int was_hashed = l->hosts && l->hosts[0] == HASH_DELIM;
switch (l->status) {
case HKF_STATUS_OK:
@@ -1060,12 +1180,11 @@ known_hosts_hash(struct hostkey_foreach_line *l, void *_ctx)
* Don't hash hosts already already hashed, with wildcard
* characters or a CA/revocation marker.
*/
- if ((l->match & HKF_MATCH_HOST_HASHED) != 0 ||
- has_wild || l->marker != MRK_NONE) {
+ if (was_hashed || has_wild || l->marker != MRK_NONE) {
fprintf(ctx->out, "%s\n", l->line);
- if (has_wild && !find_host) {
- fprintf(stderr, "%s:%ld: ignoring host name "
- "with wildcard: %.64s\n", l->path,
+ if (has_wild && !ctx->find_host) {
+ logit("%s:%lu: ignoring host name "
+ "with wildcard: %.64s", l->path,
l->linenum, l->hosts);
}
return 0;
@@ -1076,6 +1195,7 @@ known_hosts_hash(struct hostkey_foreach_line *l, void *_ctx)
*/
ohosts = hosts = xstrdup(l->hosts);
while ((cp = strsep(&hosts, ",")) != NULL && *cp != '\0') {
+ lowercase(cp);
if ((hashed = host_hash(cp, NULL, 0)) == NULL)
fatal("hash_host failed");
fprintf(ctx->out, "%s %s\n", hashed, l->rawkey);
@@ -1086,7 +1206,7 @@ known_hosts_hash(struct hostkey_foreach_line *l, void *_ctx)
case HKF_STATUS_INVALID:
/* Retain invalid lines, but mark file as invalid. */
ctx->invalid = 1;
- fprintf(stderr, "%s:%ld: invalid line\n", l->path, l->linenum);
+ logit("%s:%lu: invalid line", l->path, l->linenum);
/* FALLTHROUGH */
default:
fprintf(ctx->out, "%s\n", l->line);
@@ -1100,9 +1220,15 @@ static int
known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx)
{
struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
+ enum sshkey_fp_rep rep;
+ int fptype;
+ char *fp = NULL, *ra = NULL;
+
+ fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
+ rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
if (l->status == HKF_STATUS_MATCHED) {
- if (delete_host) {
+ if (ctx->delete_host) {
if (l->marker != MRK_NONE) {
/* Don't remove CA and revocation lines */
fprintf(ctx->out, "%s\n", l->line);
@@ -1114,30 +1240,44 @@ known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx)
*/
ctx->found_key = 1;
if (!quiet)
- printf("# Host %s found: line %ld\n",
+ printf("# Host %s found: line %lu\n",
ctx->host, l->linenum);
}
return 0;
- } else if (find_host) {
+ } else if (ctx->find_host) {
ctx->found_key = 1;
if (!quiet) {
- printf("# Host %s found: line %ld %s\n",
+ printf("# Host %s found: line %lu %s\n",
ctx->host,
l->linenum, l->marker == MRK_CA ? "CA" :
(l->marker == MRK_REVOKE ? "REVOKED" : ""));
}
- if (hash_hosts)
+ if (ctx->hash_hosts)
known_hosts_hash(l, ctx);
- else
+ else if (print_fingerprint) {
+ fp = sshkey_fingerprint(l->key, fptype, rep);
+ ra = sshkey_fingerprint(l->key,
+ fingerprint_hash, SSH_FP_RANDOMART);
+ if (fp == NULL || ra == NULL)
+ fatal("%s: sshkey_fingerprint failed",
+ __func__);
+ mprintf("%s %s %s%s%s\n", ctx->host,
+ sshkey_type(l->key), fp,
+ l->comment[0] ? " " : "",
+ l->comment);
+ if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
+ printf("%s\n", ra);
+ free(ra);
+ free(fp);
+ } else
fprintf(ctx->out, "%s\n", l->line);
return 0;
}
- } else if (delete_host) {
+ } else if (ctx->delete_host) {
/* Retain non-matching hosts when deleting */
if (l->status == HKF_STATUS_INVALID) {
ctx->invalid = 1;
- fprintf(stderr, "%s:%ld: invalid line\n",
- l->path, l->linenum);
+ logit("%s:%lu: invalid line", l->path, l->linenum);
}
fprintf(ctx->out, "%s\n", l->line);
}
@@ -1145,11 +1285,13 @@ known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx)
}
static void
-do_known_hosts(struct passwd *pw, const char *name)
+do_known_hosts(struct passwd *pw, const char *name, int find_host,
+ int delete_host, int hash_hosts)
{
char *cp, tmp[PATH_MAX], old[PATH_MAX];
int r, fd, oerrno, inplace = 0;
struct known_hosts_ctx ctx;
+ u_int foreach_options;
if (!have_identity) {
cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
@@ -1163,6 +1305,9 @@ do_known_hosts(struct passwd *pw, const char *name)
memset(&ctx, 0, sizeof(ctx));
ctx.out = stdout;
ctx.host = name;
+ ctx.hash_hosts = hash_hosts;
+ ctx.find_host = find_host;
+ ctx.delete_host = delete_host;
/*
* Find hosts goes to stdout, hash and deletions happen in-place
@@ -1184,29 +1329,32 @@ do_known_hosts(struct passwd *pw, const char *name)
}
inplace = 1;
}
-
/* XXX support identity_file == "-" for stdin */
- if ((r = hostkeys_foreach(identity_file,
- hash_hosts ? known_hosts_hash : known_hosts_find_delete, &ctx,
- name, NULL, find_host ? HKF_WANT_MATCH : 0)) != 0)
+ foreach_options = find_host ? HKF_WANT_MATCH : 0;
+ foreach_options |= print_fingerprint ? HKF_WANT_PARSE_KEY : 0;
+ if ((r = hostkeys_foreach(identity_file, (find_host || !hash_hosts) ?
+ known_hosts_find_delete : known_hosts_hash, &ctx, name, NULL,
+ foreach_options)) != 0) {
+ if (inplace)
+ unlink(tmp);
fatal("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
+ }
if (inplace)
fclose(ctx.out);
if (ctx.invalid) {
- fprintf(stderr, "%s is not a valid known_hosts file.\n",
- identity_file);
+ error("%s is not a valid known_hosts file.", identity_file);
if (inplace) {
- fprintf(stderr, "Not replacing existing known_hosts "
- "file because of errors\n");
+ error("Not replacing existing known_hosts "
+ "file because of errors");
unlink(tmp);
}
exit(1);
} else if (delete_host && !ctx.found_key) {
- fprintf(stderr, "Host %s not found in %s\n",
- name, identity_file);
- unlink(tmp);
+ logit("Host %s not found in %s", name, identity_file);
+ if (inplace)
+ unlink(tmp);
} else if (inplace) {
/* Backup existing file */
if (unlink(old) == -1 && errno != ENOENT)
@@ -1223,13 +1371,12 @@ do_known_hosts(struct passwd *pw, const char *name)
exit(1);
}
- fprintf(stderr, "%s updated.\n", identity_file);
- fprintf(stderr, "Original contents retained as %s\n", old);
+ printf("%s updated.\n", identity_file);
+ printf("Original contents retained as %s\n", old);
if (ctx.has_unhashed) {
- fprintf(stderr, "WARNING: %s contains unhashed "
- "entries\n", old);
- fprintf(stderr, "Delete this file to ensure privacy "
- "of hostnames\n");
+ logit("WARNING: %s contains unhashed entries", old);
+ logit("Delete this file to ensure privacy "
+ "of hostnames");
}
}
@@ -1251,10 +1398,8 @@ do_change_passphrase(struct passwd *pw)
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
- if (stat(identity_file, &st) < 0) {
- perror(identity_file);
- exit(1);
- }
+ if (stat(identity_file, &st) == -1)
+ fatal("%s: %s", identity_file, strerror(errno));
/* Try to load the file with empty passphrase. */
r = sshkey_load_private(identity_file, "", &private, &comment);
if (r == SSH_ERR_KEY_WRONG_PASSPHRASE) {
@@ -1266,18 +1411,15 @@ do_change_passphrase(struct passwd *pw)
RP_ALLOW_STDIN);
r = sshkey_load_private(identity_file, old_passphrase,
&private, &comment);
- explicit_bzero(old_passphrase, strlen(old_passphrase));
- free(old_passphrase);
+ freezero(old_passphrase, strlen(old_passphrase));
if (r != 0)
goto badkey;
} else if (r != 0) {
badkey:
- fprintf(stderr, "Failed to load key \"%s\": %s\n",
- identity_file, ssh_err(r));
- exit(1);
+ fatal("Failed to load key %s: %s", identity_file, ssh_err(r));
}
if (comment)
- printf("Key has comment '%s'\n", comment);
+ mprintf("Key has comment '%s'\n", comment);
/* Ask the new passphrase (twice). */
if (identity_new_passphrase) {
@@ -1300,24 +1442,21 @@ do_change_passphrase(struct passwd *pw)
exit(1);
}
/* Destroy the other copy. */
- explicit_bzero(passphrase2, strlen(passphrase2));
- free(passphrase2);
+ freezero(passphrase2, strlen(passphrase2));
}
/* Save the file using the new passphrase. */
if ((r = sshkey_save_private(private, identity_file, passphrase1,
- comment, use_new_format, new_format_cipher, rounds)) != 0) {
- printf("Saving key \"%s\" failed: %s.\n",
+ comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
+ error("Saving key \"%s\" failed: %s.",
identity_file, ssh_err(r));
- explicit_bzero(passphrase1, strlen(passphrase1));
- free(passphrase1);
+ freezero(passphrase1, strlen(passphrase1));
sshkey_free(private);
free(comment);
exit(1);
}
/* Destroy the passphrase and the copy of the key in memory. */
- explicit_bzero(passphrase1, strlen(passphrase1));
- free(passphrase1);
+ freezero(passphrase1, strlen(passphrase1));
sshkey_free(private); /* Destroys contents */
free(comment);
@@ -1329,7 +1468,8 @@ do_change_passphrase(struct passwd *pw)
* Print the SSHFP RR.
*/
static int
-do_print_resource_record(struct passwd *pw, char *fname, char *hname)
+do_print_resource_record(struct passwd *pw, char *fname, char *hname,
+ int print_generic)
{
struct sshkey *public;
char *comment = NULL;
@@ -1338,17 +1478,14 @@ do_print_resource_record(struct passwd *pw, char *fname, char *hname)
if (fname == NULL)
fatal("%s: no filename", __func__);
- if (stat(fname, &st) < 0) {
+ if (stat(fname, &st) == -1) {
if (errno == ENOENT)
return 0;
- perror(fname);
- exit(1);
+ fatal("%s: %s", fname, strerror(errno));
}
- if ((r = sshkey_load_public(fname, &public, &comment)) != 0) {
- printf("Failed to read v2 public key from \"%s\": %s.\n",
+ if ((r = sshkey_load_public(fname, &public, &comment)) != 0)
+ fatal("Failed to read v2 public key from \"%s\": %s.",
fname, ssh_err(r));
- exit(1);
- }
export_dns_rr(hname, public, stdout, print_generic);
sshkey_free(public);
free(comment);
@@ -1359,29 +1496,25 @@ do_print_resource_record(struct passwd *pw, char *fname, char *hname)
* Change the comment of a private key file.
*/
static void
-do_change_comment(struct passwd *pw)
+do_change_comment(struct passwd *pw, const char *identity_comment)
{
char new_comment[1024], *comment, *passphrase;
struct sshkey *private;
struct sshkey *public;
struct stat st;
- FILE *f;
- int r, fd;
+ int r;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
- if (stat(identity_file, &st) < 0) {
- perror(identity_file);
- exit(1);
- }
+ if (stat(identity_file, &st) == -1)
+ fatal("%s: %s", identity_file, strerror(errno));
if ((r = sshkey_load_private(identity_file, "",
&private, &comment)) == 0)
passphrase = xstrdup("");
- else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
- printf("Cannot load private key \"%s\": %s.\n",
+ else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
+ fatal("Cannot load private key \"%s\": %s.",
identity_file, ssh_err(r));
- exit(1);
- } else {
+ else {
if (identity_passphrase)
passphrase = xstrdup(identity_passphrase);
else if (identity_new_passphrase)
@@ -1392,24 +1525,29 @@ do_change_comment(struct passwd *pw)
/* Try to load using the passphrase. */
if ((r = sshkey_load_private(identity_file, passphrase,
&private, &comment)) != 0) {
- explicit_bzero(passphrase, strlen(passphrase));
- free(passphrase);
- printf("Cannot load private key \"%s\": %s.\n",
+ freezero(passphrase, strlen(passphrase));
+ fatal("Cannot load private key \"%s\": %s.",
identity_file, ssh_err(r));
- exit(1);
}
}
- if (private->type != KEY_RSA1) {
- fprintf(stderr, "Comments are only supported for RSA1 keys.\n");
+
+ if (private->type != KEY_ED25519 && private->type != KEY_XMSS &&
+ private_key_format != SSHKEY_PRIVATE_OPENSSH) {
+ error("Comments are only supported for keys stored in "
+ "the new format (-o).");
+ explicit_bzero(passphrase, strlen(passphrase));
sshkey_free(private);
exit(1);
}
- printf("Key now has comment '%s'\n", comment);
+ if (comment)
+ printf("Old comment: %s\n", comment);
+ else
+ printf("No existing comment\n");
if (identity_comment) {
strlcpy(new_comment, identity_comment, sizeof(new_comment));
} else {
- printf("Enter new comment: ");
+ printf("New comment: ");
fflush(stdout);
if (!fgets(new_comment, sizeof(new_comment), stdin)) {
explicit_bzero(passphrase, strlen(passphrase));
@@ -1418,83 +1556,44 @@ do_change_comment(struct passwd *pw)
}
new_comment[strcspn(new_comment, "\n")] = '\0';
}
+ if (comment != NULL && strcmp(comment, new_comment) == 0) {
+ printf("No change to comment\n");
+ free(passphrase);
+ sshkey_free(private);
+ free(comment);
+ exit(0);
+ }
/* Save the file using the new passphrase. */
if ((r = sshkey_save_private(private, identity_file, passphrase,
- new_comment, use_new_format, new_format_cipher, rounds)) != 0) {
- printf("Saving key \"%s\" failed: %s\n",
+ new_comment, private_key_format, openssh_format_cipher,
+ rounds)) != 0) {
+ error("Saving key \"%s\" failed: %s",
identity_file, ssh_err(r));
- explicit_bzero(passphrase, strlen(passphrase));
- free(passphrase);
+ freezero(passphrase, strlen(passphrase));
sshkey_free(private);
free(comment);
exit(1);
}
- explicit_bzero(passphrase, strlen(passphrase));
- free(passphrase);
+ freezero(passphrase, strlen(passphrase));
if ((r = sshkey_from_private(private, &public)) != 0)
- fatal("key_from_private failed: %s", ssh_err(r));
+ fatal("sshkey_from_private failed: %s", ssh_err(r));
sshkey_free(private);
strlcat(identity_file, ".pub", sizeof(identity_file));
- fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (fd == -1) {
- printf("Could not save your public key in %s\n", identity_file);
- exit(1);
- }
- f = fdopen(fd, "w");
- if (f == NULL) {
- printf("fdopen %s failed\n", identity_file);
- exit(1);
+ 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_write(public, f)) != 0)
- fprintf(stderr, "write key failed: %s\n", ssh_err(r));
sshkey_free(public);
- fprintf(f, " %s\n", new_comment);
- fclose(f);
-
free(comment);
- printf("The comment in your key file has been changed.\n");
- exit(0);
-}
-
-static const char *
-fmt_validity(u_int64_t valid_from, u_int64_t valid_to)
-{
- char from[32], to[32];
- static char ret[64];
- time_t tt;
- struct tm *tm;
-
- *from = *to = '\0';
- if (valid_from == 0 && valid_to == 0xffffffffffffffffULL)
- return "forever";
-
- if (valid_from != 0) {
- /* XXX revisit INT_MAX in 2038 :) */
- tt = valid_from > INT_MAX ? INT_MAX : valid_from;
- tm = localtime(&tt);
- strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
- }
- if (valid_to != 0xffffffffffffffffULL) {
- /* XXX revisit INT_MAX in 2038 :) */
- tt = valid_to > INT_MAX ? INT_MAX : valid_to;
- tm = localtime(&tt);
- strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
- }
-
- if (valid_from == 0) {
- snprintf(ret, sizeof(ret), "before %s", to);
- return ret;
- }
- if (valid_to == 0xffffffffffffffffULL) {
- snprintf(ret, sizeof(ret), "after %s", from);
- return ret;
- }
+ if (strlen(new_comment) > 0)
+ printf("Comment '%s' applied\n", new_comment);
+ else
+ printf("Comment removed\n");
- snprintf(ret, sizeof(ret), "from %s to %s", from, to);
- return ret;
+ exit(0);
}
static void
@@ -1530,6 +1629,8 @@ add_string_option(struct sshbuf *c, const char *name, const char *value)
static void
prepare_options_buf(struct sshbuf *c, int which)
{
+ size_t i;
+
sshbuf_reset(c);
if ((which & OPTIONS_CRITICAL) != 0 &&
certflags_command != NULL)
@@ -1549,9 +1650,23 @@ prepare_options_buf(struct sshbuf *c, int which)
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)))
+ continue;
+ if (cert_userext[i].val == NULL)
+ add_flag_option(c, cert_userext[i].key);
+ else {
+ add_string_option(c, cert_userext[i].key,
+ cert_userext[i].val);
+ }
+ }
}
static struct sshkey *
@@ -1565,7 +1680,8 @@ load_pkcs11_key(char *path)
fatal("Couldn't load CA public key \"%s\": %s",
path, ssh_err(r));
- nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, &keys);
+ nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase,
+ &keys, NULL);
debug3("%s: %d keys", __func__, nkeys);
if (nkeys <= 0)
fatal("cannot read public key from pkcs11");
@@ -1584,46 +1700,82 @@ load_pkcs11_key(char *path)
#endif /* ENABLE_PKCS11 */
}
+/* Signer for sshkey_certify_custom that uses the agent */
+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)
+{
+ int *agent_fdp = (int *)ctx;
+
+ return ssh_agent_sign(*agent_fdp, key, sigp, lenp,
+ data, datalen, alg, compat);
+}
+
static void
-do_ca_sign(struct passwd *pw, int argc, char **argv)
+do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
+ unsigned long long cert_serial, int cert_serial_autoinc,
+ int argc, char **argv)
{
- int r, i, fd;
+ int r, i, found, agent_fd = -1;
u_int n;
struct sshkey *ca, *public;
- char *otmp, *tmp, *cp, *out, *comment, **plist = NULL;
- FILE *f;
- int v00 = 0; /* legacy keys */
-
- if (key_type_name != NULL) {
- switch (sshkey_type_from_name(key_type_name)) {
- case KEY_RSA_CERT_V00:
- case KEY_DSA_CERT_V00:
- v00 = 1;
- break;
- case KEY_UNSPEC:
- if (strcasecmp(key_type_name, "v00") == 0) {
- v00 = 1;
- break;
- } else if (strcasecmp(key_type_name, "v01") == 0)
- break;
- /* FALLTHROUGH */
- default:
- fprintf(stderr, "unknown key type %s\n", key_type_name);
- exit(1);
- }
- }
+ char valid[64], *otmp, *tmp, *cp, *out, *comment;
+ char *ca_fp = NULL, **plist = NULL;
+ struct ssh_identitylist *agent_ids;
+ size_t j;
+ struct notifier_ctx *notifier = NULL;
#ifdef ENABLE_PKCS11
pkcs11_init(1);
#endif
tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
if (pkcs11provider != NULL) {
+ /* If a PKCS#11 token was specified then try to use it */
if ((ca = load_pkcs11_key(tmp)) == NULL)
fatal("No PKCS#11 key matching %s found", ca_key_path);
- } else
- ca = load_identity(tmp);
+ } else if (prefer_agent) {
+ /*
+ * Agent signature requested. Try to use agent after making
+ * sure the public key specified is actually present in the
+ * agent.
+ */
+ if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
+ fatal("Cannot load CA public key %s: %s",
+ tmp, ssh_err(r));
+ if ((r = ssh_get_authentication_socket(&agent_fd)) != 0)
+ fatal("Cannot use public key for CA signature: %s",
+ ssh_err(r));
+ if ((r = ssh_fetch_identitylist(agent_fd, &agent_ids)) != 0)
+ fatal("Retrieve agent key list: %s", ssh_err(r));
+ found = 0;
+ for (j = 0; j < agent_ids->nkeys; j++) {
+ if (sshkey_equal(ca, agent_ids->keys[j])) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ fatal("CA key %s not found in agent", tmp);
+ ssh_free_identitylist(agent_ids);
+ ca->flags |= SSHKEY_FLAG_EXT;
+ } else {
+ /* CA key is assumed to be a private key on the filesystem */
+ ca = load_identity(tmp, NULL);
+ }
free(tmp);
+ if (key_type_name != NULL) {
+ if (sshkey_type_from_name(key_type_name) != ca->type) {
+ fatal("CA key type %s doesn't match specified %s",
+ sshkey_ssh_name(ca), key_type_name);
+ }
+ } else if (ca->type == KEY_RSA) {
+ /* Default to a good signature algorithm */
+ key_type_name = "rsa-sha2-512";
+ }
+ ca_fp = sshkey_fingerprint(ca, fingerprint_hash, SSH_FP_DEFAULT);
+
for (i = 0; i < argc; i++) {
/* Split list of principals */
n = 0;
@@ -1631,24 +1783,25 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
otmp = tmp = xstrdup(cert_principals);
plist = NULL;
for (; (cp = strsep(&tmp, ",")) != NULL; n++) {
- plist = xrealloc(plist, n + 1, sizeof(*plist));
+ plist = xreallocarray(plist, n + 1, sizeof(*plist));
if (*(plist[n] = xstrdup(cp)) == '\0')
fatal("Empty principal name");
}
free(otmp);
}
-
+ if (n > SSHKEY_CERT_MAX_PRINCIPALS)
+ fatal("Too many certificate principals specified");
+
tmp = tilde_expand_filename(argv[i], pw->pw_uid);
if ((r = sshkey_load_public(tmp, &public, &comment)) != 0)
fatal("%s: unable to open \"%s\": %s",
__func__, tmp, ssh_err(r));
- if (public->type != KEY_RSA && public->type != KEY_DSA &&
- public->type != KEY_ECDSA && public->type != KEY_ED25519)
+ if (sshkey_is_cert(public))
fatal("%s: key \"%s\" type %s cannot be certified",
__func__, tmp, sshkey_type(public));
/* Prepare certificate to sign */
- if ((r = sshkey_to_certified(public, v00)) != 0)
+ if ((r = sshkey_to_certified(public)) != 0)
fatal("Could not upgrade key %s to certificate: %s",
tmp, ssh_err(r));
public->cert->type = cert_key_type;
@@ -1658,51 +1811,62 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
public->cert->principals = plist;
public->cert->valid_after = cert_valid_from;
public->cert->valid_before = cert_valid_to;
- if (v00) {
- prepare_options_buf(public->cert->critical,
- OPTIONS_CRITICAL|OPTIONS_EXTENSIONS);
- } else {
- prepare_options_buf(public->cert->critical,
- OPTIONS_CRITICAL);
- prepare_options_buf(public->cert->extensions,
- OPTIONS_EXTENSIONS);
- }
+ prepare_options_buf(public->cert->critical, OPTIONS_CRITICAL);
+ prepare_options_buf(public->cert->extensions,
+ OPTIONS_EXTENSIONS);
if ((r = sshkey_from_private(ca,
&public->cert->signature_key)) != 0)
- fatal("key_from_private (ca key): %s", ssh_err(r));
+ fatal("sshkey_from_private (ca key): %s", ssh_err(r));
- if (sshkey_certify(public, ca) != 0)
- fatal("Couldn't not certify key %s", tmp);
+ if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) {
+ if ((r = sshkey_certify_custom(public, ca,
+ key_type_name, sk_provider, agent_signer,
+ &agent_fd)) != 0)
+ fatal("Couldn't certify key %s via agent: %s",
+ tmp, ssh_err(r));
+ } else {
+ if (sshkey_is_sk(ca) &&
+ (ca->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
+ notifier = notify_start(0,
+ "Confirm user presence for key %s %s",
+ sshkey_type(ca), ca_fp);
+ }
+ r = sshkey_certify(public, ca, key_type_name,
+ sk_provider);
+ notify_complete(notifier);
+ if (r != 0)
+ fatal("Couldn't certify key %s: %s",
+ tmp, ssh_err(r));
+ }
if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0)
*cp = '\0';
xasprintf(&out, "%s-cert.pub", tmp);
free(tmp);
- if ((fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
- fatal("Could not open \"%s\" for writing: %s", out,
- strerror(errno));
- if ((f = fdopen(fd, "w")) == NULL)
- fatal("%s: fdopen: %s", __func__, strerror(errno));
- if ((r = sshkey_write(public, f)) != 0)
- fatal("Could not write certified key to %s: %s",
- out, ssh_err(r));
- fprintf(f, " %s\n", comment);
- fclose(f);
+ if ((r = sshkey_save_public(public, out, comment)) != 0) {
+ fatal("Unable to save public key to %s: %s",
+ identity_file, ssh_err(r));
+ }
if (!quiet) {
+ sshkey_format_cert_validity(public->cert,
+ valid, sizeof(valid));
logit("Signed %s key %s: id \"%s\" serial %llu%s%s "
- "valid %s", sshkey_cert_type(public),
+ "valid %s", sshkey_cert_type(public),
out, public->cert->key_id,
(unsigned long long)public->cert->serial,
cert_principals != NULL ? " for " : "",
cert_principals != NULL ? cert_principals : "",
- fmt_validity(cert_valid_from, cert_valid_to));
+ valid);
}
sshkey_free(public);
free(out);
+ if (cert_serial_autoinc)
+ cert_serial++;
}
+ free(ca_fp);
#ifdef ENABLE_PKCS11
pkcs11_terminate();
#endif
@@ -1723,40 +1887,6 @@ parse_relative_time(const char *s, time_t now)
return now + (u_int64_t)(secs * mul);
}
-static u_int64_t
-parse_absolute_time(const char *s)
-{
- struct tm tm;
- time_t tt;
- char buf[32], *fmt;
-
- /*
- * POSIX strptime says "The application shall ensure that there
- * is white-space or other non-alphanumeric characters between
- * any two conversion specifications" so arrange things this way.
- */
- switch (strlen(s)) {
- case 8:
- fmt = "%Y-%m-%d";
- snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6);
- break;
- case 14:
- fmt = "%Y-%m-%dT%H:%M:%S";
- snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s",
- s, s + 4, s + 6, s + 8, s + 10, s + 12);
- break;
- default:
- fatal("Invalid certificate time format %s", s);
- }
-
- memset(&tm, 0, sizeof(tm));
- if (strptime(buf, fmt, &tm) == NULL)
- fatal("Invalid certificate time %s", s);
- if ((tt = mktime(&tm)) < 0)
- fatal("Certificate time %s cannot be represented", s);
- return (u_int64_t)tt;
-}
-
static void
parse_cert_times(char *timespec)
{
@@ -1779,8 +1909,8 @@ parse_cert_times(char *timespec)
/*
* from:to, where
- * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS
- * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS
+ * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "always"
+ * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "forever"
*/
from = xstrdup(timespec);
to = strchr(from, ':');
@@ -1790,13 +1920,17 @@ parse_cert_times(char *timespec)
if (*from == '-' || *from == '+')
cert_valid_from = parse_relative_time(from, now);
- else
- cert_valid_from = parse_absolute_time(from);
+ else if (strcmp(from, "always") == 0)
+ cert_valid_from = 0;
+ else if (parse_absolute_time(from, &cert_valid_from) != 0)
+ fatal("Invalid from time \"%s\"", from);
if (*to == '-' || *to == '+')
cert_valid_to = parse_relative_time(to, now);
- else
- cert_valid_to = parse_absolute_time(to);
+ else if (strcmp(to, "forever") == 0)
+ cert_valid_to = ~(u_int64_t)0;
+ else if (parse_absolute_time(to, &cert_valid_to) != 0)
+ fatal("Invalid to time \"%s\"", to);
if (cert_valid_to <= cert_valid_from)
fatal("Empty certificate validity interval");
@@ -1806,7 +1940,8 @@ parse_cert_times(char *timespec)
static void
add_cert_option(char *opt)
{
- char *val;
+ char *val, *cp;
+ int iscrit = 0;
if (strcasecmp(opt, "clear") == 0)
certflags_flags = 0;
@@ -1830,6 +1965,10 @@ add_cert_option(char *opt)
certflags_flags &= ~CERTOPT_USER_RC;
else if (strcasecmp(opt, "permit-user-rc") == 0)
certflags_flags |= CERTOPT_USER_RC;
+ else if (strcasecmp(opt, "touch-required") == 0)
+ certflags_flags &= ~CERTOPT_NO_REQUIRE_USER_PRESENCE;
+ else if (strcasecmp(opt, "no-touch-required") == 0)
+ certflags_flags |= CERTOPT_NO_REQUIRE_USER_PRESENCE;
else if (strncasecmp(opt, "force-command=", 14) == 0) {
val = opt + 14;
if (*val == '\0')
@@ -1846,12 +1985,24 @@ add_cert_option(char *opt)
if (addr_match_cidr_list(NULL, val) != 0)
fatal("Invalid source-address list");
certflags_src_addr = xstrdup(val);
+ } else if (strncasecmp(opt, "extension:", 10) == 0 ||
+ (iscrit = (strncasecmp(opt, "critical:", 9) == 0))) {
+ val = xstrdup(strchr(opt, ':') + 1);
+ if ((cp = strchr(val, '=')) != NULL)
+ *cp++ = '\0';
+ cert_userext = xreallocarray(cert_userext, ncert_userext + 1,
+ sizeof(*cert_userext));
+ cert_userext[ncert_userext].key = val;
+ cert_userext[ncert_userext].val = cp == NULL ?
+ NULL : xstrdup(cp);
+ cert_userext[ncert_userext].crit = iscrit;
+ ncert_userext++;
} else
fatal("Unsupported certificate option \"%s\"", opt);
}
static void
-show_options(struct sshbuf *optbuf, int v00, int in_critical)
+show_options(struct sshbuf *optbuf, int in_critical)
{
char *name, *arg;
struct sshbuf *options, *option = NULL;
@@ -1866,14 +2017,15 @@ show_options(struct sshbuf *optbuf, int v00, int in_critical)
(r = sshbuf_froms(options, &option)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
printf(" %s", name);
- if ((v00 || !in_critical) &&
+ if (!in_critical &&
(strcmp(name, "permit-X11-forwarding") == 0 ||
strcmp(name, "permit-agent-forwarding") == 0 ||
strcmp(name, "permit-port-forwarding") == 0 ||
strcmp(name, "permit-pty") == 0 ||
- strcmp(name, "permit-user-rc") == 0))
+ strcmp(name, "permit-user-rc") == 0 ||
+ strcmp(name, "no-touch-required") == 0)) {
printf("\n");
- else if ((v00 || in_critical) &&
+ } else if (in_critical &&
(strcmp(name, "force-command") == 0 ||
strcmp(name, "source-address") == 0)) {
if ((r = sshbuf_get_cstring(option, &arg, NULL)) != 0)
@@ -1895,44 +2047,27 @@ show_options(struct sshbuf *optbuf, int v00, int in_critical)
}
static void
-do_show_cert(struct passwd *pw)
+print_cert(struct sshkey *key)
{
- struct sshkey *key;
- struct stat st;
- char *key_fp, *ca_fp;
- u_int i, v00;
- int r;
-
- if (!have_identity)
- ask_filename(pw, "Enter file in which the key is");
- if (stat(identity_file, &st) < 0)
- fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
- if ((r = sshkey_load_public(identity_file, &key, NULL)) != 0)
- fatal("Cannot load public key \"%s\": %s",
- identity_file, ssh_err(r));
- if (!sshkey_is_cert(key))
- fatal("%s is not a certificate", identity_file);
- v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00;
+ char valid[64], *key_fp, *ca_fp;
+ u_int i;
key_fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT);
ca_fp = sshkey_fingerprint(key->cert->signature_key,
fingerprint_hash, SSH_FP_DEFAULT);
if (key_fp == NULL || ca_fp == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
+ sshkey_format_cert_validity(key->cert, valid, sizeof(valid));
- printf("%s:\n", identity_file);
printf(" Type: %s %s certificate\n", sshkey_ssh_name(key),
sshkey_cert_type(key));
printf(" Public key: %s %s\n", sshkey_type(key), key_fp);
- printf(" Signing CA: %s %s\n",
- sshkey_type(key->cert->signature_key), ca_fp);
+ printf(" Signing CA: %s %s (using %s)\n",
+ sshkey_type(key->cert->signature_key), ca_fp,
+ key->cert->signature_type);
printf(" Key ID: \"%s\"\n", key->cert->key_id);
- if (!v00) {
- printf(" Serial: %llu\n",
- (unsigned long long)key->cert->serial);
- }
- printf(" Valid: %s\n",
- fmt_validity(key->cert->valid_after, key->cert->valid_before));
+ printf(" Serial: %llu\n", (unsigned long long)key->cert->serial);
+ printf(" Valid: %s\n", valid);
printf(" Principals: ");
if (key->cert->nprincipals == 0)
printf("(none)\n");
@@ -1947,33 +2082,82 @@ do_show_cert(struct passwd *pw)
printf("(none)\n");
else {
printf("\n");
- show_options(key->cert->critical, v00, 1);
+ show_options(key->cert->critical, 1);
}
- if (!v00) {
- printf(" Extensions: ");
- if (sshbuf_len(key->cert->extensions) == 0)
- printf("(none)\n");
- else {
- printf("\n");
- show_options(key->cert->extensions, v00, 0);
+ printf(" Extensions: ");
+ if (sshbuf_len(key->cert->extensions) == 0)
+ printf("(none)\n");
+ else {
+ printf("\n");
+ show_options(key->cert->extensions, 0);
+ }
+}
+
+static void
+do_show_cert(struct passwd *pw)
+{
+ struct sshkey *key = NULL;
+ struct stat st;
+ int r, is_stdin = 0, ok = 0;
+ FILE *f;
+ char *cp, *line = NULL;
+ const char *path;
+ size_t linesize = 0;
+ u_long lnum = 0;
+
+ if (!have_identity)
+ ask_filename(pw, "Enter file in which the key is");
+ if (strcmp(identity_file, "-") != 0 && stat(identity_file, &st) == -1)
+ fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
+
+ path = identity_file;
+ if (strcmp(path, "-") == 0) {
+ f = stdin;
+ path = "(stdin)";
+ is_stdin = 1;
+ } else if ((f = fopen(identity_file, "r")) == NULL)
+ fatal("fopen %s: %s", identity_file, strerror(errno));
+
+ while (getline(&line, &linesize, f) != -1) {
+ lnum++;
+ sshkey_free(key);
+ key = NULL;
+ /* Trim leading space and comments */
+ cp = line + strspn(line, " \t");
+ if (*cp == '#' || *cp == '\0')
+ continue;
+ if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
+ fatal("sshkey_new");
+ if ((r = sshkey_read(key, &cp)) != 0) {
+ error("%s:%lu: invalid key: %s", path,
+ lnum, ssh_err(r));
+ continue;
}
+ if (!sshkey_is_cert(key)) {
+ error("%s:%lu is not a certificate", path, lnum);
+ continue;
+ }
+ ok = 1;
+ if (!is_stdin && lnum == 1)
+ printf("%s:\n", path);
+ else
+ printf("%s:%lu:\n", path, lnum);
+ print_cert(key);
}
- exit(0);
+ free(line);
+ sshkey_free(key);
+ fclose(f);
+ exit(ok ? 0 : 1);
}
static void
load_krl(const char *path, struct ssh_krl **krlp)
{
struct sshbuf *krlbuf;
- int r, fd;
+ int r;
- if ((krlbuf = sshbuf_new()) == NULL)
- fatal("sshbuf_new failed");
- if ((fd = open(path, O_RDONLY)) == -1)
- fatal("open %s: %s", path, strerror(errno));
- if ((r = sshkey_load_file(fd, krlbuf)) != 0)
+ if ((r = sshbuf_load_file(path, &krlbuf)) != 0)
fatal("Unable to load KRL: %s", ssh_err(r));
- close(fd);
/* XXX check sigs */
if ((r = ssh_krl_from_blob(krlbuf, krlp, NULL, 0)) != 0 ||
*krlp == NULL)
@@ -1982,14 +2166,51 @@ load_krl(const char *path, struct ssh_krl **krlp)
}
static void
+hash_to_blob(const char *cp, u_char **blobp, size_t *lenp,
+ const char *file, u_long lnum)
+{
+ char *tmp;
+ size_t tlen;
+ struct sshbuf *b;
+ int r;
+
+ if (strncmp(cp, "SHA256:", 7) != 0)
+ fatal("%s:%lu: unsupported hash algorithm", file, lnum);
+ cp += 7;
+
+ /*
+ * OpenSSH base64 hashes omit trailing '='
+ * characters; put them back for decode.
+ */
+ tlen = strlen(cp);
+ tmp = xmalloc(tlen + 4 + 1);
+ strlcpy(tmp, cp, tlen + 1);
+ while ((tlen % 4) != 0) {
+ tmp[tlen++] = '=';
+ tmp[tlen] = '\0';
+ }
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_b64tod(b, tmp)) != 0)
+ fatal("%s:%lu: decode hash failed: %s", file, lnum, ssh_err(r));
+ free(tmp);
+ *lenp = sshbuf_len(b);
+ *blobp = xmalloc(*lenp);
+ memcpy(*blobp, sshbuf_ptr(b), *lenp);
+ sshbuf_free(b);
+}
+
+static void
update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
const struct sshkey *ca, struct ssh_krl *krl)
{
struct sshkey *key = NULL;
u_long lnum = 0;
- char *path, *cp, *ep, line[SSH_MAX_PUBKEY_BYTES];
+ char *path, *cp, *ep, *line = NULL;
+ u_char *blob = NULL;
+ size_t blen = 0, linesize = 0;
unsigned long long serial, serial2;
- int i, was_explicit_key, was_sha1, r;
+ int i, was_explicit_key, was_sha1, was_sha256, was_hash, r;
FILE *krl_spec;
path = tilde_expand_filename(file, pw->pw_uid);
@@ -2002,9 +2223,9 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
if (!quiet)
printf("Revoking from %s\n", path);
- while (read_keyfile_line(krl_spec, path, line, sizeof(line),
- &lnum) == 0) {
- was_explicit_key = was_sha1 = 0;
+ while (getline(&line, &linesize, krl_spec) != -1) {
+ lnum++;
+ was_explicit_key = was_sha1 = was_sha256 = was_hash = 0;
cp = line + strspn(line, " \t");
/* Trim trailing space, comments and strip \n */
for (i = 0, r = -1; cp[i] != '\0'; i++) {
@@ -2069,6 +2290,14 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
cp = cp + strspn(cp, " \t");
if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0)
fatal("%s: revoke key ID failed", __func__);
+ } else if (strncasecmp(cp, "hash:", 5) == 0) {
+ cp += 5;
+ cp = cp + strspn(cp, " \t");
+ hash_to_blob(cp, &blob, &blen, file, lnum);
+ r = ssh_krl_revoke_key_sha256(krl, blob, blen);
+ if (r != 0)
+ fatal("%s: revoke key failed: %s",
+ __func__, ssh_err(r));
} else {
if (strncasecmp(cp, "key:", 4) == 0) {
cp += 4;
@@ -2078,41 +2307,62 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
cp += 5;
cp = cp + strspn(cp, " \t");
was_sha1 = 1;
- } else {
+ } else if (strncasecmp(cp, "sha256:", 7) == 0) {
+ cp += 7;
+ cp = cp + strspn(cp, " \t");
+ was_sha256 = 1;
/*
* Just try to process the line as a key.
* Parsing will fail if it isn't.
*/
}
if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
- fatal("key_new");
+ fatal("sshkey_new");
if ((r = sshkey_read(key, &cp)) != 0)
fatal("%s:%lu: invalid key: %s",
path, lnum, ssh_err(r));
if (was_explicit_key)
r = ssh_krl_revoke_key_explicit(krl, key);
- else if (was_sha1)
- r = ssh_krl_revoke_key_sha1(krl, key);
- else
+ else if (was_sha1) {
+ if (sshkey_fingerprint_raw(key,
+ SSH_DIGEST_SHA1, &blob, &blen) != 0) {
+ fatal("%s:%lu: fingerprint failed",
+ file, lnum);
+ }
+ r = ssh_krl_revoke_key_sha1(krl, blob, blen);
+ } else if (was_sha256) {
+ if (sshkey_fingerprint_raw(key,
+ SSH_DIGEST_SHA256, &blob, &blen) != 0) {
+ fatal("%s:%lu: fingerprint failed",
+ file, lnum);
+ }
+ r = ssh_krl_revoke_key_sha256(krl, blob, blen);
+ } else
r = ssh_krl_revoke_key(krl, key);
if (r != 0)
fatal("%s: revoke key failed: %s",
__func__, ssh_err(r));
+ freezero(blob, blen);
+ blob = NULL;
+ blen = 0;
sshkey_free(key);
}
}
if (strcmp(path, "-") != 0)
fclose(krl_spec);
+ free(line);
free(path);
}
static void
-do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
+do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path,
+ unsigned long long krl_version, const char *krl_comment,
+ int argc, char **argv)
{
struct ssh_krl *krl;
struct stat sb;
struct sshkey *ca = NULL;
- int fd, i, r, wild_ca = 0;
+ int i, r, wild_ca = 0;
char *tmp;
struct sshbuf *kbuf;
@@ -2142,10 +2392,10 @@ do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
else if ((krl = ssh_krl_init()) == NULL)
fatal("couldn't create KRL");
- if (cert_serial != 0)
- ssh_krl_set_version(krl, cert_serial);
- if (identity_comment != NULL)
- ssh_krl_set_comment(krl, identity_comment);
+ if (krl_version != 0)
+ ssh_krl_set_version(krl, krl_version);
+ if (krl_comment != NULL)
+ ssh_krl_set_comment(krl, krl_comment);
for (i = 0; i < argc; i++)
update_krl_from_file(pw, argv[i], wild_ca, ca, krl);
@@ -2154,20 +2404,15 @@ do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
fatal("sshbuf_new failed");
if (ssh_krl_to_blob(krl, kbuf, NULL, 0) != 0)
fatal("Couldn't generate KRL");
- if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
- fatal("open %s: %s", identity_file, strerror(errno));
- if (atomicio(vwrite, fd, (void *)sshbuf_ptr(kbuf), sshbuf_len(kbuf)) !=
- sshbuf_len(kbuf))
+ if ((r = sshbuf_write_file(identity_file, kbuf)) != 0)
fatal("write %s: %s", identity_file, strerror(errno));
- close(fd);
sshbuf_free(kbuf);
ssh_krl_free(krl);
- if (ca != NULL)
- sshkey_free(ca);
+ sshkey_free(ca);
}
static void
-do_check_krl(struct passwd *pw, int argc, char **argv)
+do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv)
{
int i, r, ret = 0;
char *comment;
@@ -2177,6 +2422,8 @@ do_check_krl(struct passwd *pw, int argc, char **argv)
if (*identity_file == '\0')
fatal("KRL checking requires an input file");
load_krl(identity_file, &krl);
+ if (print_krl)
+ krl_dump(krl, stdout);
for (i = 0; i < argc; i++) {
if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0)
fatal("Cannot load public key %s: %s",
@@ -2194,17 +2441,605 @@ do_check_krl(struct passwd *pw, int argc, char **argv)
exit(ret);
}
+static struct sshkey *
+load_sign_key(const char *keypath, const struct sshkey *pubkey)
+{
+ size_t i, slen, plen = strlen(keypath);
+ char *privpath = xstrdup(keypath);
+ const char *suffixes[] = { "-cert.pub", ".pub", NULL };
+ struct sshkey *ret = NULL, *privkey = NULL;
+ int r;
+
+ /*
+ * If passed a public key filename, then try to locate the corresponding
+ * private key. This lets us specify certificates on the command-line
+ * and have ssh-keygen find the appropriate private key.
+ */
+ for (i = 0; suffixes[i]; i++) {
+ slen = strlen(suffixes[i]);
+ if (plen <= slen ||
+ 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);
+ }
+ if ((privkey = load_identity(privpath, NULL)) == NULL) {
+ error("Couldn't load identity %s", keypath);
+ goto done;
+ }
+ if (!sshkey_equal_public(pubkey, privkey)) {
+ error("Public key %s doesn't match private %s",
+ keypath, privpath);
+ goto done;
+ }
+ if (sshkey_is_cert(pubkey) && !sshkey_is_cert(privkey)) {
+ /*
+ * Graft the certificate onto the private key to make
+ * it capable of signing.
+ */
+ if ((r = sshkey_to_certified(privkey)) != 0) {
+ error("%s: sshkey_to_certified: %s", __func__,
+ ssh_err(r));
+ goto done;
+ }
+ if ((r = sshkey_cert_copy(pubkey, privkey)) != 0) {
+ error("%s: sshkey_cert_copy: %s", __func__, ssh_err(r));
+ goto done;
+ }
+ }
+ /* success */
+ ret = privkey;
+ privkey = NULL;
+ done:
+ sshkey_free(privkey);
+ free(privpath);
+ return ret;
+}
+
+static int
+sign_one(struct sshkey *signkey, const char *filename, int fd,
+ const char *sig_namespace, sshsig_signer *signer, void *signer_ctx)
+{
+ struct sshbuf *sigbuf = NULL, *abuf = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR, wfd = -1, oerrno;
+ char *wfile = NULL, *asig = NULL, *fp = NULL;
+
+ if (!quiet) {
+ if (fd == STDIN_FILENO)
+ fprintf(stderr, "Signing data on standard input\n");
+ 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 ((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));
+ goto out;
+ }
+ if ((r = sshsig_armor(sigbuf, &abuf)) != 0) {
+ error("%s: sshsig_armor: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if ((asig = sshbuf_dup_string(abuf)) == NULL) {
+ error("%s: buffer error", __func__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ if (fd == STDIN_FILENO) {
+ fputs(asig, stdout);
+ fflush(stdout);
+ } else {
+ xasprintf(&wfile, "%s.sig", filename);
+ if (confirm_overwrite(wfile)) {
+ if ((wfd = open(wfile, O_WRONLY|O_CREAT|O_TRUNC,
+ 0666)) == -1) {
+ oerrno = errno;
+ error("Cannot open %s: %s",
+ wfile, strerror(errno));
+ errno = oerrno;
+ r = SSH_ERR_SYSTEM_ERROR;
+ goto out;
+ }
+ if (atomicio(vwrite, wfd, asig,
+ strlen(asig)) != strlen(asig)) {
+ oerrno = errno;
+ error("Cannot write to %s: %s",
+ wfile, strerror(errno));
+ errno = oerrno;
+ r = SSH_ERR_SYSTEM_ERROR;
+ goto out;
+ }
+ if (!quiet) {
+ fprintf(stderr, "Write signature to %s\n",
+ wfile);
+ }
+ }
+ }
+ /* success */
+ r = 0;
+ out:
+ free(wfile);
+ free(asig);
+ sshbuf_free(abuf);
+ sshbuf_free(sigbuf);
+ if (wfd != -1)
+ close(wfd);
+ return r;
+}
+
+static int
+sig_sign(const char *keypath, const char *sig_namespace, int argc, char **argv)
+{
+ int i, fd = -1, r, ret = -1;
+ int agent_fd = -1;
+ struct sshkey *pubkey = NULL, *privkey = NULL, *signkey = NULL;
+ sshsig_signer *signer = NULL;
+
+ /* Check file arguments. */
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "-") != 0)
+ continue;
+ if (i > 0 || argc > 1)
+ fatal("Cannot sign mix of paths and standard input");
+ }
+
+ if ((r = sshkey_load_public(keypath, &pubkey, NULL)) != 0) {
+ error("Couldn't load public key %s: %s", keypath, ssh_err(r));
+ goto done;
+ }
+
+ if ((r = ssh_get_authentication_socket(&agent_fd)) != 0)
+ debug("Couldn't get agent socket: %s", ssh_err(r));
+ 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));
+ }
+
+ if (signer == NULL) {
+ /* Not using agent - try to load private key */
+ if ((privkey = load_sign_key(keypath, pubkey)) == NULL)
+ goto done;
+ signkey = privkey;
+ } else {
+ /* Will use key in agent */
+ signkey = pubkey;
+ }
+
+ if (argc == 0) {
+ if ((r = sign_one(signkey, "(stdin)", STDIN_FILENO,
+ sig_namespace, signer, &agent_fd)) != 0)
+ goto done;
+ } else {
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "-") == 0)
+ fd = STDIN_FILENO;
+ else if ((fd = open(argv[i], O_RDONLY)) == -1) {
+ error("Cannot open %s for signing: %s",
+ argv[i], strerror(errno));
+ goto done;
+ }
+ if ((r = sign_one(signkey, argv[i], fd, sig_namespace,
+ signer, &agent_fd)) != 0)
+ goto done;
+ if (fd != STDIN_FILENO)
+ close(fd);
+ fd = -1;
+ }
+ }
+
+ ret = 0;
+done:
+ if (fd != -1 && fd != STDIN_FILENO)
+ close(fd);
+ sshkey_free(pubkey);
+ sshkey_free(privkey);
+ return ret;
+}
+
+static int
+sig_verify(const char *signature, const char *sig_namespace,
+ const char *principal, const char *allowed_keys, const char *revoked_keys)
+{
+ int r, ret = -1;
+ struct sshbuf *sigbuf = NULL, *abuf = NULL;
+ struct sshkey *sign_key = NULL;
+ char *fp = NULL;
+ struct sshkey_sig_details *sig_details = NULL;
+
+ 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));
+ goto done;
+ }
+
+ if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) {
+ error("%s: sshsig_armor: %s", __func__, ssh_err(r));
+ goto done;
+ }
+ if ((r = sshsig_verify_fd(sigbuf, STDIN_FILENO, sig_namespace,
+ &sign_key, &sig_details)) != 0)
+ goto done; /* sshsig_verify() prints error */
+
+ if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash,
+ SSH_FP_DEFAULT)) == NULL)
+ fatal("%s: sshkey_fingerprint failed", __func__);
+ 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);
+ }
+ 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));
+ 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));
+ goto done;
+ }
+ /* success */
+ ret = 0;
+done:
+ if (!quiet) {
+ if (ret == 0) {
+ if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash,
+ SSH_FP_DEFAULT)) == NULL) {
+ fatal("%s: sshkey_fingerprint failed",
+ __func__);
+ }
+ if (principal == NULL) {
+ printf("Good \"%s\" signature with %s key %s\n",
+ 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);
+ }
+ } else {
+ printf("Could not verify signature.\n");
+ }
+ }
+ sshbuf_free(sigbuf);
+ sshbuf_free(abuf);
+ sshkey_free(sign_key);
+ sshkey_sig_details_free(sig_details);
+ free(fp);
+ return ret;
+}
+
+static int
+sig_find_principals(const char *signature, const char *allowed_keys) {
+ int r, ret = -1;
+ struct sshbuf *sigbuf = NULL, *abuf = NULL;
+ struct sshkey *sign_key = NULL;
+ char *principals = NULL, *cp, *tmp;
+
+ if ((r = sshbuf_load_file(signature, &abuf)) != 0) {
+ error("Couldn't read signature file: %s", ssh_err(r));
+ goto done;
+ }
+ if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) {
+ error("%s: sshsig_armor: %s", __func__, ssh_err(r));
+ goto done;
+ }
+ if ((r = sshsig_get_pubkey(sigbuf, &sign_key)) != 0) {
+ error("%s: sshsig_get_pubkey: %s",
+ __func__, ssh_err(r));
+ goto done;
+ }
+ if ((r = sshsig_find_principals(allowed_keys, sign_key,
+ &principals)) != 0) {
+ error("%s: sshsig_get_principal: %s",
+ __func__, ssh_err(r));
+ goto done;
+ }
+ ret = 0;
+done:
+ if (ret == 0 ) {
+ /* Emit matching principals one per line */
+ tmp = principals;
+ while ((cp = strsep(&tmp, ",")) != NULL && *cp != '\0')
+ puts(cp);
+ } else {
+ fprintf(stderr, "No principal matched.\n");
+ }
+ sshbuf_free(sigbuf);
+ sshbuf_free(abuf);
+ sshkey_free(sign_key);
+ free(principals);
+ return ret;
+}
+
+static void
+do_moduli_gen(const char *out_file, char **opts, size_t nopts)
+{
+#ifdef WITH_OPENSSL
+ /* Moduli generation/screening */
+ u_int32_t memory = 0;
+ BIGNUM *start = NULL;
+ int moduli_bits = 0;
+ FILE *out;
+ size_t i;
+ const char *errstr;
+
+ /* Parse options */
+ for (i = 0; i < nopts; i++) {
+ if (strncmp(opts[i], "memory=", 7) == 0) {
+ memory = (u_int32_t)strtonum(opts[i]+7, 1,
+ UINT_MAX, &errstr);
+ if (errstr) {
+ fatal("Memory limit is %s: %s",
+ errstr, opts[i]+7);
+ }
+ } else if (strncmp(opts[i], "start=", 6) == 0) {
+ /* XXX - also compare length against bits */
+ if (BN_hex2bn(&start, opts[i]+6) == 0)
+ fatal("Invalid start point.");
+ } else if (strncmp(opts[i], "bits=", 5) == 0) {
+ moduli_bits = (int)strtonum(opts[i]+5, 1,
+ INT_MAX, &errstr);
+ if (errstr) {
+ fatal("Invalid number: %s (%s)",
+ opts[i]+12, errstr);
+ }
+ } else {
+ fatal("Option \"%s\" is unsupported for moduli "
+ "generation", opts[i]);
+ }
+ }
+
+ if ((out = fopen(out_file, "w")) == NULL) {
+ fatal("Couldn't open modulus candidate file \"%s\": %s",
+ out_file, strerror(errno));
+ }
+ setvbuf(out, NULL, _IOLBF, 0);
+
+ if (moduli_bits == 0)
+ moduli_bits = DEFAULT_BITS;
+ if (gen_candidates(out, memory, moduli_bits, start) != 0)
+ fatal("modulus candidate generation failed");
+#else /* WITH_OPENSSL */
+ fatal("Moduli generation is not supported");
+#endif /* WITH_OPENSSL */
+}
+
+static void
+do_moduli_screen(const char *out_file, char **opts, size_t nopts)
+{
+#ifdef WITH_OPENSSL
+ /* Moduli generation/screening */
+ char *checkpoint = NULL;
+ u_int32_t generator_wanted = 0;
+ unsigned long start_lineno = 0, lines_to_process = 0;
+ int prime_tests = 0;
+ FILE *out, *in = stdin;
+ size_t i;
+ const char *errstr;
+
+ /* Parse options */
+ for (i = 0; i < nopts; i++) {
+ if (strncmp(opts[i], "lines=", 6) == 0) {
+ lines_to_process = strtoul(opts[i]+6, NULL, 10);
+ } else if (strncmp(opts[i], "start-line=", 11) == 0) {
+ start_lineno = strtoul(opts[i]+11, NULL, 10);
+ } else if (strncmp(opts[i], "checkpoint=", 11) == 0) {
+ checkpoint = xstrdup(opts[i]+11);
+ } else if (strncmp(opts[i], "generator=", 10) == 0) {
+ generator_wanted = (u_int32_t)strtonum(
+ opts[i]+10, 1, UINT_MAX, &errstr);
+ if (errstr != NULL) {
+ fatal("Generator invalid: %s (%s)",
+ opts[i]+10, errstr);
+ }
+ } else if (strncmp(opts[i], "prime-tests=", 12) == 0) {
+ prime_tests = (int)strtonum(opts[i]+12, 1,
+ INT_MAX, &errstr);
+ if (errstr) {
+ fatal("Invalid number: %s (%s)",
+ opts[i]+12, errstr);
+ }
+ } else {
+ fatal("Option \"%s\" is unsupported for moduli "
+ "screening", opts[i]);
+ }
+ }
+
+ if (have_identity && strcmp(identity_file, "-") != 0) {
+ if ((in = fopen(identity_file, "r")) == NULL) {
+ fatal("Couldn't open modulus candidate "
+ "file \"%s\": %s", identity_file,
+ strerror(errno));
+ }
+ }
+
+ if ((out = fopen(out_file, "a")) == NULL) {
+ fatal("Couldn't open moduli file \"%s\": %s",
+ out_file, strerror(errno));
+ }
+ setvbuf(out, NULL, _IOLBF, 0);
+ if (prime_test(in, out, prime_tests == 0 ? 100 : prime_tests,
+ generator_wanted, checkpoint,
+ start_lineno, lines_to_process) != 0)
+ fatal("modulus screening failed");
+#else /* WITH_OPENSSL */
+ fatal("Moduli screening is not supported");
+#endif /* WITH_OPENSSL */
+}
+
+static char *
+private_key_passphrase(void)
+{
+ char *passphrase1, *passphrase2;
+
+ /* Ask for a passphrase (twice). */
+ if (identity_passphrase)
+ passphrase1 = xstrdup(identity_passphrase);
+ else if (identity_new_passphrase)
+ passphrase1 = xstrdup(identity_new_passphrase);
+ else {
+passphrase_again:
+ passphrase1 =
+ read_passphrase("Enter passphrase (empty for no "
+ "passphrase): ", RP_ALLOW_STDIN);
+ passphrase2 = read_passphrase("Enter same passphrase again: ",
+ RP_ALLOW_STDIN);
+ if (strcmp(passphrase1, passphrase2) != 0) {
+ /*
+ * The passphrases do not match. Clear them and
+ * retry.
+ */
+ freezero(passphrase1, strlen(passphrase1));
+ freezero(passphrase2, strlen(passphrase2));
+ printf("Passphrases do not match. Try again.\n");
+ goto passphrase_again;
+ }
+ /* Clear the other copy of the passphrase. */
+ freezero(passphrase2, strlen(passphrase2));
+ }
+ return passphrase1;
+}
+
+static const char *
+skip_ssh_url_preamble(const char *s)
+{
+ if (strncmp(s, "ssh://", 6) == 0)
+ return s + 6;
+ else if (strncmp(s, "ssh:", 4) == 0)
+ return s + 4;
+ return s;
+}
+
+static int
+do_download_sk(const char *skprovider, const char *device)
+{
+ struct sshkey **keys;
+ size_t nkeys, i;
+ int r, ok = -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;
+ }
+ }
+ if (nkeys == 0)
+ logit("No keys to download");
+ if (pin != NULL)
+ freezero(pin, strlen(pin));
+
+ for (i = 0; i < nkeys; i++) {
+ if (keys[i]->type != KEY_ECDSA_SK &&
+ keys[i]->type != KEY_ED25519_SK) {
+ error("Unsupported key type %s (%d)",
+ sshkey_type(keys[i]), keys[i]->type);
+ continue;
+ }
+ if ((fp = sshkey_fingerprint(keys[i],
+ fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
+ fatal("%s: sshkey_fingerprint failed", __func__);
+ debug("%s: key %zu: %s %s %s (flags 0x%02x)", __func__, i,
+ sshkey_type(keys[i]), fp, keys[i]->sk_application,
+ keys[i]->sk_flags);
+ ext = skip_ssh_url_preamble(keys[i]->sk_application);
+ xasprintf(&path, "id_%s_rk%s%s",
+ keys[i]->type == KEY_ECDSA_SK ? "ecdsa_sk" : "ed25519_sk",
+ *ext == '\0' ? "" : "_", ext);
+
+ /* If the file already exists, ask the user to confirm. */
+ if (!confirm_overwrite(path)) {
+ free(path);
+ break;
+ }
+
+ /* Save the key with the application string as the comment */
+ if (pass == NULL)
+ pass = private_key_passphrase();
+ if ((r = sshkey_save_private(keys[i], path, pass,
+ keys[i]->sk_application, private_key_format,
+ openssh_format_cipher, rounds)) != 0) {
+ error("Saving key \"%s\" failed: %s",
+ path, ssh_err(r));
+ free(path);
+ break;
+ }
+ if (!quiet) {
+ printf("Saved %s key%s%s to %s\n",
+ sshkey_type(keys[i]),
+ *ext != '\0' ? " " : "",
+ *ext != '\0' ? keys[i]->sk_application : "",
+ path);
+ }
+
+ /* Save public key too */
+ xasprintf(&pubpath, "%s.pub", path);
+ free(path);
+ if ((r = sshkey_save_public(keys[i], pubpath,
+ keys[i]->sk_application)) != 0) {
+ error("Saving public key \"%s\" failed: %s",
+ pubpath, ssh_err(r));
+ free(pubpath);
+ break;
+ }
+ free(pubpath);
+ }
+
+ if (i >= nkeys)
+ ok = 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;
+}
+
static void
usage(void)
{
fprintf(stderr,
- "usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1]\n"
- " [-N new_passphrase] [-C comment] [-f output_keyfile]\n"
- " ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]\n"
- " ssh-keygen -i [-m key_format] [-f input_keyfile]\n"
- " ssh-keygen -e [-m key_format] [-f input_keyfile]\n"
+ "usage: ssh-keygen [-q] [-b bits] [-C comment] [-f output_keyfile] [-m format]\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"
+ " ssh-keygen -i [-f input_keyfile] [-m key_format]\n"
+ " ssh-keygen -e [-f input_keyfile] [-m key_format]\n"
" ssh-keygen -y [-f input_keyfile]\n"
- " ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n"
+ " ssh-keygen -c [-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
@@ -2212,20 +3047,28 @@ usage(void)
" ssh-keygen -D pkcs11\n");
#endif
fprintf(stderr,
- " ssh-keygen -F hostname [-f known_hosts_file] [-l]\n"
+ " 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 -R hostname [-f known_hosts_file]\n"
- " ssh-keygen -r hostname [-f input_keyfile] [-g]\n"
- " ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]\n"
- " ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]\n"
- " [-j start_line] [-K checkpt] [-W generator]\n"
- " ssh-keygen -s ca_key -I certificate_identity [-h] [-n principals]\n"
- " [-O option] [-V validity_interval] [-z serial_number] file ...\n"
+ " ssh-keygen -r hostname [-g] [-f input_keyfile]\n"
+#ifdef WITH_OPENSSL
+ " ssh-keygen -M generate [-O option] output_file\n"
+ " ssh-keygen -M screen [-f input_file] [-O option] output_file\n"
+#endif
+ " ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n"
+ " [-n principals] [-O option] [-V validity_interval]\n"
+ " [-z serial_number] file ...\n"
" ssh-keygen -L [-f input_keyfile]\n"
- " ssh-keygen -A\n"
+ " ssh-keygen -A [-f prefix_path]\n"
" ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n"
" file ...\n"
- " ssh-keygen -Q -f krl_file file ...\n");
+ " ssh-keygen -Q [-l] -f krl_file [file ...]\n"
+ " ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n"
+ " ssh-keygen -Y check-novalidate -n namespace -s signature_file\n"
+ " ssh-keygen -Y sign -f key_file -n namespace file ...\n"
+ " ssh-keygen -Y verify -f allowed_signers_file -I signer_identity\n"
+ " -n namespace -s signature_file [-r revocation_file]\n");
exit(1);
}
@@ -2235,20 +3078,29 @@ usage(void)
int
main(int argc, char **argv)
{
- char dotsshdir[PATH_MAX], comment[1024], *passphrase1, *passphrase2;
- char *checkpoint = NULL;
- char out_file[PATH_MAX], *rr_hostname = NULL, *ep, *fp, *ra;
+ char dotsshdir[PATH_MAX], comment[1024], *passphrase;
+ char *rr_hostname = NULL, *ep, *fp, *ra;
struct sshkey *private, *public;
struct passwd *pw;
struct stat st;
- int r, opt, type, fd;
- u_int32_t memory = 0, generator_wanted = 0;
- int do_gen_candidates = 0, do_screen_candidates = 0;
+ int r, opt, type;
+ int change_passphrase = 0, change_comment = 0, show_cert = 0;
+ int find_host = 0, delete_host = 0, hash_hosts = 0;
int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
- unsigned long start_lineno = 0, lines_to_process = 0;
- BIGNUM *start = NULL;
- FILE *f;
+ int prefer_agent = 0, convert_to = 0, convert_from = 0;
+ int print_public = 0, print_generic = 0, cert_serial_autoinc = 0;
+ int do_gen_candidates = 0, do_screen_candidates = 0, download_sk = 0;
+ unsigned long long cert_serial = 0;
+ char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL;
+ char *sk_application = NULL, *sk_device = NULL, *sk_user = NULL;
+ char *sk_attestaion_path = NULL;
+ struct sshbuf *challenge = NULL, *attest = NULL;
+ size_t i, nopts = 0;
+ u_int32_t bits = 0;
+ uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD;
const char *errstr;
+ int log_level = SYSLOG_LEVEL_INFO;
+ char *sign_op = NULL;
extern int optind;
extern char *optarg;
@@ -2258,34 +3110,32 @@ main(int argc, char **argv)
__progname = ssh_get_progname(argv[0]);
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
-#endif
+ seed_rng();
+
log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
- seed_rng();
+ msetlocale();
/* we need this for the home * directory. */
pw = getpwuid(getuid());
- if (!pw) {
- printf("No user exists for uid %lu\n", (u_long)getuid());
- exit(1);
- }
- if (gethostname(hostname, sizeof(hostname)) < 0) {
- perror("gethostname");
- exit(1);
- }
+ if (!pw)
+ fatal("No user exists for uid %lu", (u_long)getuid());
+ if (gethostname(hostname, sizeof(hostname)) == -1)
+ fatal("gethostname: %s", strerror(errno));
- /* Remaining characters: UYdw */
- while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy"
- "C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:"
- "a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
+ sk_provider = getenv("SSH_SK_PROVIDER");
+
+ /* Remaining characters: dGjJSTWx */
+ while ((opt = getopt(argc, argv, "ABHKLQUXceghiklopquvy"
+ "C:D:E:F:I:M:N:O:P:R:V:Y:Z:"
+ "a:b:f:g:m:n:r:s:t:w:z:")) != -1) {
switch (opt) {
case 'A':
gen_all_hostkeys = 1;
break;
case 'b':
- bits = (u_int32_t)strtonum(optarg, 256, 32768, &errstr);
+ bits = (u_int32_t)strtonum(optarg, 1, UINT32_MAX,
+ &errstr);
if (errstr)
fatal("Bits has bad value %s (%s)",
optarg, errstr);
@@ -2305,12 +3155,6 @@ main(int argc, char **argv)
case 'I':
cert_key_id = optarg;
break;
- case 'J':
- lines_to_process = strtoul(optarg, NULL, 10);
- break;
- case 'j':
- start_lineno = strtoul(optarg, NULL, 10);
- break;
case 'R':
delete_host = 1;
rr_hostname = optarg;
@@ -2332,10 +3176,12 @@ main(int argc, char **argv)
}
if (strcasecmp(optarg, "PKCS8") == 0) {
convert_format = FMT_PKCS8;
+ private_key_format = SSHKEY_PRIVATE_PKCS8;
break;
}
if (strcasecmp(optarg, "PEM") == 0) {
convert_format = FMT_PEM;
+ private_key_format = SSHKEY_PRIVATE_PEM;
break;
}
fatal("Unsupported conversion format \"%s\"", optarg);
@@ -2343,7 +3189,7 @@ main(int argc, char **argv)
cert_principals = optarg;
break;
case 'o':
- use_new_format = 1;
+ /* no-op; new format is already the default */
break;
case 'p':
change_passphrase = 1;
@@ -2352,14 +3198,17 @@ main(int argc, char **argv)
change_comment = 1;
break;
case 'f':
- if (strlcpy(identity_file, optarg, sizeof(identity_file)) >=
- sizeof(identity_file))
+ if (strlcpy(identity_file, optarg,
+ sizeof(identity_file)) >= sizeof(identity_file))
fatal("Identity filename too long");
have_identity = 1;
break;
case 'g':
print_generic = 1;
break;
+ case 'K':
+ download_sk = 1;
+ break;
case 'P':
identity_passphrase = optarg;
break;
@@ -2370,10 +3219,12 @@ main(int argc, char **argv)
check_krl = 1;
break;
case 'O':
- add_cert_option(optarg);
+ opts = xrecallocarray(opts, nopts, nopts + 1,
+ sizeof(*opts));
+ opts[nopts++] = xstrdup(optarg);
break;
case 'Z':
- new_format_cipher = optarg;
+ openssh_format_cipher = optarg;
break;
case 'C':
identity_comment = optarg;
@@ -2382,7 +3233,6 @@ main(int argc, char **argv)
quiet = 1;
break;
case 'e':
- case 'x':
/* export key */
convert_to = 1;
break;
@@ -2410,6 +3260,9 @@ main(int argc, char **argv)
case 'D':
pkcs11provider = optarg;
break;
+ case 'U':
+ prefer_agent = 1;
+ break;
case 'u':
update_krl = 1;
break;
@@ -2425,185 +3278,238 @@ main(int argc, char **argv)
case 'r':
rr_hostname = optarg;
break;
- case 'W':
- generator_wanted = (u_int32_t)strtonum(optarg, 1,
- UINT_MAX, &errstr);
- if (errstr)
- fatal("Desired generator has bad value: %s (%s)",
- optarg, errstr);
- break;
case 'a':
rounds = (int)strtonum(optarg, 1, INT_MAX, &errstr);
if (errstr)
fatal("Invalid number: %s (%s)",
optarg, errstr);
break;
-#ifdef WITH_OPENSSL
- case 'M':
- memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
- if (errstr)
- fatal("Memory limit is %s: %s", errstr, optarg);
- break;
- case 'G':
- do_gen_candidates = 1;
- if (strlcpy(out_file, optarg, sizeof(out_file)) >=
- sizeof(out_file))
- fatal("Output filename too long");
- break;
- case 'T':
- do_screen_candidates = 1;
- if (strlcpy(out_file, optarg, sizeof(out_file)) >=
- sizeof(out_file))
- fatal("Output filename too long");
- break;
- case 'K':
- if (strlen(optarg) >= PATH_MAX)
- fatal("Checkpoint filename too long");
- checkpoint = xstrdup(optarg);
- break;
- case 'S':
- /* XXX - also compare length against bits */
- if (BN_hex2bn(&start, optarg) == 0)
- fatal("Invalid start point.");
- break;
-#endif /* WITH_OPENSSL */
case 'V':
parse_cert_times(optarg);
break;
+ case 'Y':
+ sign_op = optarg;
+ break;
+ case 'w':
+ sk_provider = optarg;
+ break;
case 'z':
errno = 0;
+ if (*optarg == '+') {
+ cert_serial_autoinc = 1;
+ optarg++;
+ }
cert_serial = strtoull(optarg, &ep, 10);
if (*optarg < '0' || *optarg > '9' || *ep != '\0' ||
(errno == ERANGE && cert_serial == ULLONG_MAX))
fatal("Invalid serial number \"%s\"", optarg);
break;
+ case 'M':
+ if (strcmp(optarg, "generate") == 0)
+ do_gen_candidates = 1;
+ else if (strcmp(optarg, "screen") == 0)
+ do_screen_candidates = 1;
+ else
+ fatal("Unsupported moduli option %s", optarg);
+ break;
case '?':
default:
usage();
}
}
+#ifdef ENABLE_SK_INTERNAL
+ if (sk_provider == NULL)
+ sk_provider = "internal";
+#endif
+
/* reinit */
log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1);
argv += optind;
argc -= optind;
+ if (sign_op != NULL) {
+ if (strncmp(sign_op, "find-principals", 15) == 0) {
+ if (ca_key_path == NULL) {
+ error("Too few arguments for find-principals:"
+ "missing signature file");
+ exit(1);
+ }
+ if (!have_identity) {
+ error("Too few arguments for find-principals:"
+ "missing allowed keys file");
+ exit(1);
+ }
+ return sig_find_principals(ca_key_path, identity_file);
+ } else if (strncmp(sign_op, "sign", 4) == 0) {
+ if (cert_principals == NULL ||
+ *cert_principals == '\0') {
+ error("Too few arguments for sign: "
+ "missing namespace");
+ exit(1);
+ }
+ if (!have_identity) {
+ error("Too few arguments for sign: "
+ "missing key");
+ exit(1);
+ }
+ return sig_sign(identity_file, cert_principals,
+ argc, argv);
+ } else if (strncmp(sign_op, "check-novalidate", 16) == 0) {
+ if (ca_key_path == NULL) {
+ error("Too few arguments for check-novalidate: "
+ "missing signature file");
+ exit(1);
+ }
+ return sig_verify(ca_key_path, cert_principals,
+ NULL, NULL, NULL);
+ } else if (strncmp(sign_op, "verify", 6) == 0) {
+ if (cert_principals == NULL ||
+ *cert_principals == '\0') {
+ error("Too few arguments for verify: "
+ "missing namespace");
+ exit(1);
+ }
+ if (ca_key_path == NULL) {
+ error("Too few arguments for verify: "
+ "missing signature file");
+ exit(1);
+ }
+ if (!have_identity) {
+ error("Too few arguments for sign: "
+ "missing allowed keys file");
+ exit(1);
+ }
+ if (cert_key_id == NULL) {
+ error("Too few arguments for verify: "
+ "missing principal ID");
+ exit(1);
+ }
+ return sig_verify(ca_key_path, cert_principals,
+ cert_key_id, identity_file, rr_hostname);
+ }
+ error("Unsupported operation for -Y: \"%s\"", sign_op);
+ usage();
+ /* NOTREACHED */
+ }
+
if (ca_key_path != NULL) {
if (argc < 1 && !gen_krl) {
- printf("Too few arguments.\n");
+ error("Too few arguments.");
usage();
}
- } else if (argc > 0 && !gen_krl && !check_krl) {
- printf("Too many arguments.\n");
+ } else if (argc > 0 && !gen_krl && !check_krl &&
+ !do_gen_candidates && !do_screen_candidates) {
+ error("Too many arguments.");
usage();
}
if (change_passphrase && change_comment) {
- printf("Can only have one of -p and -c.\n");
+ error("Can only have one of -p and -c.");
usage();
}
if (print_fingerprint && (delete_host || hash_hosts)) {
- printf("Cannot use -l with -H or -R.\n");
+ error("Cannot use -l with -H or -R.");
usage();
}
if (gen_krl) {
- do_gen_krl(pw, update_krl, argc, argv);
+ do_gen_krl(pw, update_krl, ca_key_path,
+ cert_serial, identity_comment, argc, argv);
return (0);
}
if (check_krl) {
- do_check_krl(pw, argc, argv);
+ do_check_krl(pw, print_fingerprint, argc, argv);
return (0);
}
if (ca_key_path != NULL) {
if (cert_key_id == NULL)
fatal("Must specify key id (-I) when certifying");
- do_ca_sign(pw, argc, argv);
+ for (i = 0; i < nopts; i++)
+ add_cert_option(opts[i]);
+ do_ca_sign(pw, ca_key_path, prefer_agent,
+ cert_serial, cert_serial_autoinc, argc, argv);
}
if (show_cert)
do_show_cert(pw);
- if (delete_host || hash_hosts || find_host)
- do_known_hosts(pw, rr_hostname);
+ if (delete_host || hash_hosts || find_host) {
+ do_known_hosts(pw, rr_hostname, find_host,
+ delete_host, hash_hosts);
+ }
if (pkcs11provider != NULL)
do_download(pw);
+ if (download_sk) {
+ for (i = 0; i < nopts; i++) {
+ if (strncasecmp(opts[i], "device=", 7) == 0) {
+ sk_device = xstrdup(opts[i] + 7);
+ } else {
+ fatal("Option \"%s\" is unsupported for "
+ "FIDO authenticator download", opts[i]);
+ }
+ }
+ return do_download_sk(sk_provider, sk_device);
+ }
if (print_fingerprint || print_bubblebabble)
do_fingerprint(pw);
if (change_passphrase)
do_change_passphrase(pw);
if (change_comment)
- do_change_comment(pw);
+ do_change_comment(pw, identity_comment);
#ifdef WITH_OPENSSL
if (convert_to)
do_convert_to(pw);
if (convert_from)
do_convert_from(pw);
-#endif
+#else /* WITH_OPENSSL */
+ if (convert_to || convert_from)
+ fatal("key conversion disabled at compile time");
+#endif /* WITH_OPENSSL */
if (print_public)
do_print_public(pw);
if (rr_hostname != NULL) {
unsigned int n = 0;
if (have_identity) {
- n = do_print_resource_record(pw,
- identity_file, rr_hostname);
- if (n == 0) {
- perror(identity_file);
- exit(1);
- }
+ n = do_print_resource_record(pw, identity_file,
+ rr_hostname, print_generic);
+ if (n == 0)
+ fatal("%s: %s", identity_file, strerror(errno));
exit(0);
} else {
n += do_print_resource_record(pw,
- _PATH_HOST_RSA_KEY_FILE, rr_hostname);
+ _PATH_HOST_RSA_KEY_FILE, rr_hostname,
+ print_generic);
+ n += do_print_resource_record(pw,
+ _PATH_HOST_DSA_KEY_FILE, rr_hostname,
+ print_generic);
n += do_print_resource_record(pw,
- _PATH_HOST_DSA_KEY_FILE, rr_hostname);
+ _PATH_HOST_ECDSA_KEY_FILE, rr_hostname,
+ print_generic);
n += do_print_resource_record(pw,
- _PATH_HOST_ECDSA_KEY_FILE, rr_hostname);
+ _PATH_HOST_ED25519_KEY_FILE, rr_hostname,
+ print_generic);
n += do_print_resource_record(pw,
- _PATH_HOST_ED25519_KEY_FILE, rr_hostname);
+ _PATH_HOST_XMSS_KEY_FILE, rr_hostname,
+ print_generic);
if (n == 0)
fatal("no keys found.");
exit(0);
}
}
+ if (do_gen_candidates || do_screen_candidates) {
+ if (argc <= 0)
+ fatal("No output file specified");
+ else if (argc > 1)
+ fatal("Too many output files specified");
+ }
if (do_gen_candidates) {
- FILE *out = fopen(out_file, "w");
-
- if (out == NULL) {
- error("Couldn't open modulus candidate file \"%s\": %s",
- out_file, strerror(errno));
- return (1);
- }
- if (bits == 0)
- bits = DEFAULT_BITS;
- if (gen_candidates(out, memory, bits, start) != 0)
- fatal("modulus candidate generation failed");
-
- return (0);
+ do_moduli_gen(argv[0], opts, nopts);
+ return 0;
}
-
if (do_screen_candidates) {
- FILE *in;
- FILE *out = fopen(out_file, "a");
-
- if (have_identity && strcmp(identity_file, "-") != 0) {
- if ((in = fopen(identity_file, "r")) == NULL) {
- fatal("Couldn't open modulus candidate "
- "file \"%s\": %s", identity_file,
- strerror(errno));
- }
- } else
- in = stdin;
-
- if (out == NULL) {
- fatal("Couldn't open moduli file \"%s\": %s",
- out_file, strerror(errno));
- }
- if (prime_test(in, out, rounds == 0 ? 100 : rounds,
- generator_wanted, checkpoint,
- start_lineno, lines_to_process) != 0)
- fatal("modulus screening failed");
- return (0);
+ do_moduli_screen(argv[0], opts, nopts);
+ return 0;
}
if (gen_all_hostkeys) {
@@ -2612,7 +3518,7 @@ main(int argc, char **argv)
}
if (key_type_name == NULL)
- key_type_name = "rsa";
+ key_type_name = DEFAULT_KEY_TYPE_NAME;
type = sshkey_type_from_name(key_type_name);
type_bits_valid(type, key_type_name, &bits);
@@ -2620,14 +3526,80 @@ main(int argc, char **argv)
if (!quiet)
printf("Generating public/private %s key pair.\n",
key_type_name);
- if ((r = sshkey_generate(type, bits, &private)) != 0) {
- fprintf(stderr, "key_generate failed\n");
- exit(1);
- }
- if ((r = sshkey_from_private(private, &public)) != 0) {
- fprintf(stderr, "key_from_private failed: %s\n", ssh_err(r));
- exit(1);
+ switch (type) {
+ case KEY_ECDSA_SK:
+ case KEY_ED25519_SK:
+ for (i = 0; i < nopts; i++) {
+ if (strcasecmp(opts[i], "no-touch-required") == 0) {
+ sk_flags &= ~SSH_SK_USER_PRESENCE_REQD;
+ } else if (strcasecmp(opts[i], "resident") == 0) {
+ sk_flags |= SSH_SK_RESIDENT_KEY;
+ } else if (strncasecmp(opts[i], "device=", 7) == 0) {
+ sk_device = xstrdup(opts[i] + 7);
+ } else if (strncasecmp(opts[i], "user=", 5) == 0) {
+ sk_user = xstrdup(opts[i] + 5);
+ } else if (strncasecmp(opts[i], "challenge=", 10) == 0) {
+ if ((r = sshbuf_load_file(opts[i] + 10,
+ &challenge)) != 0) {
+ fatal("Unable to load FIDO enrollment "
+ "challenge \"%s\": %s",
+ opts[i] + 10, ssh_err(r));
+ }
+ } else if (strncasecmp(opts[i],
+ "write-attestation=", 18) == 0) {
+ sk_attestaion_path = opts[i] + 18;
+ } else if (strncasecmp(opts[i],
+ "application=", 12) == 0) {
+ sk_application = xstrdup(opts[i] + 12);
+ if (strncmp(sk_application, "ssh:", 4) != 0) {
+ fatal("FIDO application string must "
+ "begin with \"ssh:\"");
+ }
+ } else {
+ fatal("Option \"%s\" is unsupported for "
+ "FIDO authenticator enrollment", opts[i]);
+ }
+ }
+ if (!quiet) {
+ printf("You may need to touch your authenticator "
+ "to authorize key generation.\n");
+ }
+ passphrase = NULL;
+ if ((attest = sshbuf_new()) == NULL)
+ fatal("sshbuf_new failed");
+ for (i = 0 ; ; i++) {
+ fflush(stdout);
+ r = sshsk_enroll(type, sk_provider, sk_device,
+ sk_application == NULL ? "ssh:" : sk_application,
+ sk_user, sk_flags, passphrase, challenge,
+ &private, attest);
+ if (r == 0)
+ break;
+ if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
+ fatal("Key enrollment failed: %s", ssh_err(r));
+ else if (i > 0)
+ error("PIN incorrect");
+ if (passphrase != NULL) {
+ freezero(passphrase, strlen(passphrase));
+ passphrase = NULL;
+ }
+ if (i >= 3)
+ fatal("Too many incorrect PINs");
+ passphrase = read_passphrase("Enter PIN for "
+ "authenticator: ", RP_ALLOW_STDIN);
+ }
+ if (passphrase != NULL) {
+ freezero(passphrase, strlen(passphrase));
+ passphrase = NULL;
+ }
+ break;
+ default:
+ if ((r = sshkey_generate(type, bits, &private)) != 0)
+ fatal("sshkey_generate failed");
+ break;
}
+ if ((r = sshkey_from_private(private, &public)) != 0)
+ fatal("sshkey_from_private failed: %s\n", ssh_err(r));
if (!have_identity)
ask_filename(pw, "Enter file in which to save the key");
@@ -2636,11 +3608,11 @@ main(int argc, char **argv)
snprintf(dotsshdir, sizeof dotsshdir, "%s/%s",
pw->pw_dir, _PATH_SSH_USER_DIR);
if (strstr(identity_file, dotsshdir) != NULL) {
- if (stat(dotsshdir, &st) < 0) {
+ if (stat(dotsshdir, &st) == -1) {
if (errno != ENOENT) {
error("Could not stat %s: %s", dotsshdir,
strerror(errno));
- } else if (mkdir(dotsshdir, 0700) < 0) {
+ } else if (mkdir(dotsshdir, 0700) == -1) {
error("Could not create directory '%s': %s",
dotsshdir, strerror(errno));
} else if (!quiet)
@@ -2648,45 +3620,11 @@ main(int argc, char **argv)
}
}
/* If the file already exists, ask the user to confirm. */
- if (stat(identity_file, &st) >= 0) {
- char yesno[3];
- printf("%s already exists.\n", identity_file);
- printf("Overwrite (y/n)? ");
- fflush(stdout);
- if (fgets(yesno, sizeof(yesno), stdin) == NULL)
- exit(1);
- if (yesno[0] != 'y' && yesno[0] != 'Y')
- exit(1);
- }
- /* Ask for a passphrase (twice). */
- if (identity_passphrase)
- passphrase1 = xstrdup(identity_passphrase);
- else if (identity_new_passphrase)
- passphrase1 = xstrdup(identity_new_passphrase);
- else {
-passphrase_again:
- passphrase1 =
- read_passphrase("Enter passphrase (empty for no "
- "passphrase): ", RP_ALLOW_STDIN);
- passphrase2 = read_passphrase("Enter same passphrase again: ",
- RP_ALLOW_STDIN);
- if (strcmp(passphrase1, passphrase2) != 0) {
- /*
- * The passphrases do not match. Clear them and
- * retry.
- */
- explicit_bzero(passphrase1, strlen(passphrase1));
- explicit_bzero(passphrase2, strlen(passphrase2));
- free(passphrase1);
- free(passphrase2);
- printf("Passphrases do not match. Try again.\n");
- goto passphrase_again;
- }
- /* Clear the other copy of the passphrase. */
- explicit_bzero(passphrase2, strlen(passphrase2));
- free(passphrase2);
- }
+ if (!confirm_overwrite(identity_file))
+ exit(1);
+ /* Determine the passphrase for the private key */
+ passphrase = private_key_passphrase();
if (identity_comment) {
strlcpy(comment, identity_comment, sizeof(comment));
} else {
@@ -2695,39 +3633,26 @@ passphrase_again:
}
/* Save the key with the given passphrase and comment. */
- if ((r = sshkey_save_private(private, identity_file, passphrase1,
- comment, use_new_format, new_format_cipher, rounds)) != 0) {
- printf("Saving key \"%s\" failed: %s\n",
+ if ((r = sshkey_save_private(private, identity_file, passphrase,
+ comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
+ error("Saving key \"%s\" failed: %s",
identity_file, ssh_err(r));
- explicit_bzero(passphrase1, strlen(passphrase1));
- free(passphrase1);
+ freezero(passphrase, strlen(passphrase));
exit(1);
}
- /* Clear the passphrase. */
- explicit_bzero(passphrase1, strlen(passphrase1));
- free(passphrase1);
-
- /* Clear the private key and the random number generator. */
+ freezero(passphrase, strlen(passphrase));
sshkey_free(private);
- if (!quiet)
- printf("Your identification has been saved in %s.\n", identity_file);
+ if (!quiet) {
+ printf("Your identification has been saved in %s\n",
+ identity_file);
+ }
strlcat(identity_file, ".pub", sizeof(identity_file));
- fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (fd == -1) {
- printf("Could not save your public key in %s\n", identity_file);
- exit(1);
- }
- f = fdopen(fd, "w");
- if (f == NULL) {
- printf("fdopen %s failed\n", identity_file);
- exit(1);
+ 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_write(public, f)) != 0)
- fprintf(stderr, "write key failed: %s\n", ssh_err(r));
- fprintf(f, " %s\n", comment);
- fclose(f);
if (!quiet) {
fp = sshkey_fingerprint(public, fingerprint_hash,
@@ -2736,7 +3661,7 @@ passphrase_again:
SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
fatal("sshkey_fingerprint failed");
- printf("Your public key has been saved in %s.\n",
+ printf("Your public key has been saved in %s\n",
identity_file);
printf("The key fingerprint is:\n");
printf("%s %s\n", fp, comment);
@@ -2746,6 +3671,22 @@ passphrase_again:
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);
+ }
+ }
+ sshbuf_free(attest);
sshkey_free(public);
+
exit(0);
}
diff --git a/ssh-keyscan.0 b/ssh-keyscan.0
deleted file mode 100644
index fe7aa855..00000000
--- a/ssh-keyscan.0
+++ /dev/null
@@ -1,109 +0,0 @@
-SSH-KEYSCAN(1) General Commands Manual SSH-KEYSCAN(1)
-
-NAME
- ssh-keyscan M-bM-^@M-^S gather ssh public keys
-
-SYNOPSIS
- ssh-keyscan [-46Hv] [-f file] [-p port] [-T timeout] [-t type]
- [host | addrlist namelist] ...
-
-DESCRIPTION
- ssh-keyscan is a utility for gathering the public ssh host keys of a
- number of hosts. It was designed to aid in building and verifying
- ssh_known_hosts files. ssh-keyscan provides a minimal interface suitable
- for use by shell and perl scripts.
-
- ssh-keyscan uses non-blocking socket I/O to contact as many hosts as
- possible in parallel, so it is very efficient. The keys from a domain of
- 1,000 hosts can be collected in tens of seconds, even when some of those
- hosts are down or do not run ssh. For scanning, one does not need login
- access to the machines that are being scanned, nor does the scanning
- process involve any encryption.
-
- The options are as follows:
-
- -4 Forces ssh-keyscan to use IPv4 addresses only.
-
- -6 Forces ssh-keyscan to use IPv6 addresses only.
-
- -f file
- Read hosts or M-bM-^@M-^\addrlist namelistM-bM-^@M-^] pairs from file, one per line.
- If - is supplied instead of a filename, ssh-keyscan will read
- hosts or M-bM-^@M-^\addrlist namelistM-bM-^@M-^] pairs from the standard input.
-
- -H Hash all hostnames and addresses in the output. Hashed names may
- be used normally by ssh and sshd, but they do not reveal
- identifying information should the file's contents be disclosed.
-
- -p port
- Port to connect to on the remote host.
-
- -T timeout
- Set the timeout for connection attempts. If timeout seconds have
- elapsed since a connection was initiated to a host or since the
- last time anything was read from that host, then the connection
- is closed and the host in question considered unavailable.
- Default is 5 seconds.
-
- -t type
- Specifies the type of the key to fetch from the scanned hosts.
- The possible values are M-bM-^@M-^\rsa1M-bM-^@M-^] for protocol version 1 and M-bM-^@M-^\dsaM-bM-^@M-^],
- M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^], or M-bM-^@M-^\rsaM-bM-^@M-^] for protocol version 2. Multiple
- values may be specified by separating them with commas. The
- default is to fetch M-bM-^@M-^\rsaM-bM-^@M-^], M-bM-^@M-^\ecdsaM-bM-^@M-^], and M-bM-^@M-^\ed25519M-bM-^@M-^] keys.
-
- -v Verbose mode. Causes ssh-keyscan to print debugging messages
- about its progress.
-
-SECURITY
- If an ssh_known_hosts file is constructed using ssh-keyscan without
- verifying the keys, users will be vulnerable to man in the middle
- attacks. On the other hand, if the security model allows such a risk,
- ssh-keyscan can help in the detection of tampered keyfiles or man in the
- middle attacks which have begun after the ssh_known_hosts file was
- created.
-
-FILES
- Input format:
-
- 1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4
-
- Output format for RSA1 keys:
-
- host-or-namelist bits exponent modulus
-
- Output format for RSA, DSA, ECDSA, and Ed25519 keys:
-
- host-or-namelist keytype base64-encoded-key
-
- Where keytype is either M-bM-^@M-^\ecdsa-sha2-nistp256M-bM-^@M-^], M-bM-^@M-^\ecdsa-sha2-nistp384M-bM-^@M-^],
- M-bM-^@M-^\ecdsa-sha2-nistp521M-bM-^@M-^], M-bM-^@M-^\ssh-ed25519M-bM-^@M-^], M-bM-^@M-^\ssh-dssM-bM-^@M-^] or M-bM-^@M-^\ssh-rsaM-bM-^@M-^].
-
- /etc/ssh/ssh_known_hosts
-
-EXAMPLES
- Print the rsa host key for machine hostname:
-
- $ ssh-keyscan hostname
-
- Find all hosts from the file ssh_hosts which have new or different keys
- from those in the sorted file ssh_known_hosts:
-
- $ ssh-keyscan -t rsa,dsa,ecdsa,ed25519 -f ssh_hosts | \
- sort -u - ssh_known_hosts | diff ssh_known_hosts -
-
-SEE ALSO
- ssh(1), sshd(8)
-
-AUTHORS
- David Mazieres <dm@lcs.mit.edu> wrote the initial version, and Wayne
- Davison <wayned@users.sourceforge.net> added support for protocol version
- 2.
-
-BUGS
- It generates "Connection closed by remote host" messages on the consoles
- of all the machines it scans if the server is older than version 2.9.
- This is because it opens a connection to the ssh port, reads the public
- key, and drops the connection as soon as it gets the key.
-
-OpenBSD 5.7 August 30, 2014 OpenBSD 5.7
diff --git a/ssh-keyscan.1 b/ssh-keyscan.1
index 6bbc480c..f9df75d4 100644
--- a/ssh-keyscan.1
+++ b/ssh-keyscan.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-keyscan.1,v 1.36 2014/08/30 15:33:50 sobrado Exp $
+.\" $OpenBSD: ssh-keyscan.1,v 1.45 2019/11/30 07:07:59 jmc Exp $
.\"
.\" Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
.\"
@@ -6,30 +6,29 @@
.\" permitted provided that due credit is given to the author and the
.\" OpenBSD project by leaving this copyright notice intact.
.\"
-.Dd $Mdocdate: August 30 2014 $
+.Dd $Mdocdate: November 30 2019 $
.Dt SSH-KEYSCAN 1
.Os
.Sh NAME
.Nm ssh-keyscan
-.Nd gather ssh public keys
+.Nd gather SSH public keys from servers
.Sh SYNOPSIS
.Nm ssh-keyscan
-.Bk -words
-.Op Fl 46Hv
+.Op Fl 46cDHv
.Op Fl f Ar file
.Op Fl p Ar port
.Op Fl T Ar timeout
.Op Fl t Ar type
.Op Ar host | addrlist namelist
-.Ar ...
-.Ek
.Sh DESCRIPTION
.Nm
-is a utility for gathering the public ssh host keys of a number of
+is a utility for gathering the public SSH host keys of a number of
hosts.
It was designed to aid in building and verifying
.Pa ssh_known_hosts
-files.
+files,
+the format of which is documented in
+.Xr sshd 8 .
.Nm
provides a minimal interface suitable for use by shell and perl
scripts.
@@ -39,7 +38,8 @@ uses non-blocking socket I/O to contact as many hosts as possible in
parallel, so it is very efficient.
The keys from a domain of 1,000
hosts can be collected in tens of seconds, even when some of those
-hosts are down or do not run ssh.
+hosts are down or do not run
+.Xr sshd 8 .
For scanning, one does not need
login access to the machines that are being scanned, nor does the
scanning process involve any encryption.
@@ -47,13 +47,21 @@ scanning process involve any encryption.
The options are as follows:
.Bl -tag -width Ds
.It Fl 4
-Forces
+Force
.Nm
to use IPv4 addresses only.
.It Fl 6
-Forces
+Force
.Nm
to use IPv6 addresses only.
+.It Fl c
+Request certificates from target hosts instead of plain keys.
+.It Fl D
+Print keys found as SSHFP DNS records.
+The default is to print keys in a format usable as a
+.Xr ssh 1
+.Pa known_hosts
+file.
.It Fl f Ar file
Read hosts or
.Dq addrlist namelist
@@ -61,41 +69,42 @@ pairs from
.Ar file ,
one per line.
If
-.Pa -
+.Sq -
is supplied instead of a filename,
.Nm
-will read hosts or
-.Dq addrlist namelist
-pairs from the standard input.
+will read from the standard input.
+Input is expected in the format:
+.Bd -literal
+1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4
+.Ed
.It Fl H
Hash all hostnames and addresses in the output.
Hashed names may be used normally by
-.Nm ssh
+.Xr ssh 1
and
-.Nm sshd ,
+.Xr sshd 8 ,
but they do not reveal identifying information should the file's contents
be disclosed.
.It Fl p Ar port
-Port to connect to on the remote host.
+Connect to
+.Ar port
+on the remote host.
.It Fl T Ar timeout
Set the timeout for connection attempts.
If
.Ar timeout
seconds have elapsed since a connection was initiated to a host or since the
-last time anything was read from that host, then the connection is
+last time anything was read from that host, the connection is
closed and the host in question considered unavailable.
-Default is 5 seconds.
+The default is 5 seconds.
.It Fl t Ar type
-Specifies the type of the key to fetch from the scanned hosts.
+Specify the type of the key to fetch from the scanned hosts.
The possible values are
-.Dq rsa1
-for protocol version 1 and
.Dq dsa ,
.Dq ecdsa ,
.Dq ed25519 ,
or
-.Dq rsa
-for protocol version 2.
+.Dq rsa .
Multiple values may be specified by separating them with commas.
The default is to fetch
.Dq rsa ,
@@ -104,12 +113,10 @@ and
.Dq ed25519
keys.
.It Fl v
-Verbose mode.
-Causes
-.Nm
-to print debugging messages about its progress.
+Verbose mode:
+print debugging messages about progress.
.El
-.Sh SECURITY
+.Pp
If an ssh_known_hosts file is constructed using
.Nm
without verifying the keys, users will be vulnerable to
@@ -120,59 +127,32 @@ On the other hand, if the security model allows such a risk,
can help in the detection of tampered keyfiles or man in the middle
attacks which have begun after the ssh_known_hosts file was created.
.Sh FILES
-Input format:
-.Bd -literal
-1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4
-.Ed
-.Pp
-Output format for RSA1 keys:
-.Bd -literal
-host-or-namelist bits exponent modulus
-.Ed
-.Pp
-Output format for RSA, DSA, ECDSA, and Ed25519 keys:
-.Bd -literal
-host-or-namelist keytype base64-encoded-key
-.Ed
-.Pp
-Where
-.Ar keytype
-is either
-.Dq ecdsa-sha2-nistp256 ,
-.Dq ecdsa-sha2-nistp384 ,
-.Dq ecdsa-sha2-nistp521 ,
-.Dq ssh-ed25519 ,
-.Dq ssh-dss
-or
-.Dq ssh-rsa .
-.Pp
.Pa /etc/ssh/ssh_known_hosts
.Sh EXAMPLES
-Print the rsa host key for machine
+Print the RSA host key for machine
.Ar hostname :
-.Bd -literal
-$ ssh-keyscan hostname
-.Ed
+.Pp
+.Dl $ ssh-keyscan -t rsa hostname
.Pp
Find all hosts from the file
.Pa ssh_hosts
which have new or different keys from those in the sorted file
.Pa ssh_known_hosts :
-.Bd -literal
+.Bd -literal -offset indent
$ ssh-keyscan -t rsa,dsa,ecdsa,ed25519 -f ssh_hosts | \e
sort -u - ssh_known_hosts | diff ssh_known_hosts -
.Ed
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr sshd 8
+.Rs
+.%D 2006
+.%R RFC 4255
+.%T Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
+.Re
.Sh AUTHORS
.An -nosplit
.An David Mazieres Aq Mt dm@lcs.mit.edu
wrote the initial version, and
.An Wayne Davison Aq Mt wayned@users.sourceforge.net
added support for protocol version 2.
-.Sh BUGS
-It generates "Connection closed by remote host" messages on the consoles
-of all the machines it scans if the server is older than version 2.9.
-This is because it opens a connection to the ssh port, reads the public
-key, and drops the connection as soon as it gets the key.
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index c5fb3b52..a5e64407 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keyscan.c,v 1.99 2015/01/30 10:44:49 djm Exp $ */
+/* $OpenBSD: ssh-keyscan.c,v 1.131 2019/12/15 19:47:10 djm Exp $ */
/*
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
*
@@ -19,7 +19,9 @@
#include <netinet/in.h>
#include <arpa/inet.h>
+#ifdef WITH_OPENSSL
#include <openssl/bn.h>
+#endif
#include <netdb.h>
#include <errno.h>
@@ -32,7 +34,6 @@
#include "xmalloc.h"
#include "ssh.h"
-#include "ssh1.h"
#include "sshbuf.h"
#include "sshkey.h"
#include "cipher.h"
@@ -47,6 +48,7 @@
#include "hostfile.h"
#include "ssherr.h"
#include "ssh_api.h"
+#include "dns.h"
/* Flag indicating whether IPv4 or IPv6. This can be set on the command line.
Default value is AF_UNSPEC means both IPv4 and IPv6. */
@@ -54,16 +56,26 @@ int IPv4or6 = AF_UNSPEC;
int ssh_port = SSH_DEFAULT_PORT;
-#define KT_RSA1 1
-#define KT_DSA 2
-#define KT_RSA 4
-#define KT_ECDSA 8
-#define KT_ED25519 16
+#define KT_DSA (1)
+#define KT_RSA (1<<1)
+#define KT_ECDSA (1<<2)
+#define KT_ED25519 (1<<3)
+#define KT_XMSS (1<<4)
+#define KT_ECDSA_SK (1<<5)
+#define KT_ED25519_SK (1<<6)
+
+#define KT_MIN KT_DSA
+#define KT_MAX KT_ED25519_SK
-int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519;
+int get_cert = 0;
+int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519|KT_ECDSA_SK|KT_ED25519_SK;
int hash_hosts = 0; /* Hash hostname on output */
+int print_sshfp = 0; /* Print SSHFP records instead of known_hosts */
+
+int found_one = 0; /* Successfully found a key */
+
#define MAXMAXFD 256
/* The number of seconds after which to give up on a TCP connection */
@@ -77,8 +89,6 @@ fd_set *read_wait;
size_t read_wait_nfdset;
int ncon;
-struct ssh *active_state = NULL; /* XXX needed for linking */
-
/*
* Keep a connection structure for each file descriptor. The state
* associated with file descriptor n is held in fdcon[n].
@@ -93,8 +103,8 @@ typedef struct Connection {
int c_plen; /* Packet length field for ssh packet */
int c_len; /* Total bytes which must be read. */
int c_off; /* Length of data read so far. */
- int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */
- int c_done; /* SSH2 done */
+ int c_keytype; /* Only one of KT_* */
+ sig_atomic_t c_done; /* SSH2 done */
char *c_namebase; /* Address to free for c_name and c_namelist */
char *c_name; /* Hostname of connection for errors */
char *c_namelist; /* Pointer to other possible addresses */
@@ -116,7 +126,7 @@ fdlim_get(int hard)
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
struct rlimit rlfd;
- if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0)
+ if (getrlimit(RLIMIT_NOFILE, &rlfd) == -1)
return (-1);
if ((hard ? rlfd.rlim_max : rlfd.rlim_cur) == RLIM_INFINITY)
return SSH_SYSFDMAX;
@@ -137,10 +147,10 @@ fdlim_set(int lim)
if (lim <= 0)
return (-1);
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
- if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0)
+ if (getrlimit(RLIMIT_NOFILE, &rlfd) == -1)
return (-1);
rlfd.rlim_cur = lim;
- if (setrlimit(RLIMIT_NOFILE, &rlfd) < 0)
+ if (setrlimit(RLIMIT_NOFILE, &rlfd) == -1)
return (-1);
#elif defined (HAVE_SETDTABLESIZE)
setdtablesize(lim);
@@ -186,52 +196,6 @@ strnnsep(char **stringp, char *delim)
return (tok);
}
-#ifdef WITH_SSH1
-static struct sshkey *
-keygrab_ssh1(con *c)
-{
- static struct sshkey *rsa;
- static struct sshbuf *msg;
- int r;
- u_char type;
-
- if (rsa == NULL) {
- if ((rsa = sshkey_new(KEY_RSA1)) == NULL) {
- error("%s: sshkey_new failed", __func__);
- return NULL;
- }
- if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
- }
- if ((r = sshbuf_put(msg, c->c_data, c->c_plen)) != 0 ||
- (r = sshbuf_consume(msg, 8 - (c->c_plen & 7))) != 0 || /* padding */
- (r = sshbuf_get_u8(msg, &type)) != 0)
- goto buf_err;
- if (type != (int) SSH_SMSG_PUBLIC_KEY) {
- error("%s: invalid packet type", c->c_name);
- sshbuf_reset(msg);
- return NULL;
- }
- if ((r = sshbuf_consume(msg, 8)) != 0 || /* cookie */
- /* server key */
- (r = sshbuf_get_u32(msg, NULL)) != 0 ||
- (r = sshbuf_get_bignum1(msg, NULL)) != 0 ||
- (r = sshbuf_get_bignum1(msg, NULL)) != 0 ||
- /* host key */
- (r = sshbuf_get_u32(msg, NULL)) != 0 ||
- (r = sshbuf_get_bignum1(msg, rsa->rsa->e)) != 0 ||
- (r = sshbuf_get_bignum1(msg, rsa->rsa->n)) != 0) {
- buf_err:
- error("%s: buffer error: %s", __func__, ssh_err(r));
- sshbuf_reset(msg);
- return NULL;
- }
-
- sshbuf_reset(msg);
-
- return (rsa);
-}
-#endif
static int
key_print_wrapper(struct sshkey *hostkey, struct ssh *ssh)
@@ -266,48 +230,119 @@ keygrab_ssh2(con *c)
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
int r;
- enable_compat20();
- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
- c->c_keytype == KT_DSA ? "ssh-dss" :
- (c->c_keytype == KT_RSA ? "ssh-rsa" :
- (c->c_keytype == KT_ED25519 ? "ssh-ed25519" :
- "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"));
+ switch (c->c_keytype) {
+ case KT_DSA:
+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
+ "ssh-dss-cert-v01@openssh.com" : "ssh-dss";
+ break;
+ case KT_RSA:
+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
+ "rsa-sha2-512-cert-v01@openssh.com,"
+ "rsa-sha2-256-cert-v01@openssh.com,"
+ "ssh-rsa-cert-v01@openssh.com" :
+ "rsa-sha2-512,"
+ "rsa-sha2-256,"
+ "ssh-rsa";
+ break;
+ case KT_ED25519:
+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
+ "ssh-ed25519-cert-v01@openssh.com" : "ssh-ed25519";
+ break;
+ case KT_XMSS:
+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
+ "ssh-xmss-cert-v01@openssh.com" : "ssh-xmss@openssh.com";
+ break;
+ case KT_ECDSA:
+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
+ "ecdsa-sha2-nistp256-cert-v01@openssh.com,"
+ "ecdsa-sha2-nistp384-cert-v01@openssh.com,"
+ "ecdsa-sha2-nistp521-cert-v01@openssh.com" :
+ "ecdsa-sha2-nistp256,"
+ "ecdsa-sha2-nistp384,"
+ "ecdsa-sha2-nistp521";
+ break;
+ case KT_ECDSA_SK:
+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
+ "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" :
+ "sk-ecdsa-sha2-nistp256@openssh.com";
+ break;
+ case KT_ED25519_SK:
+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
+ "sk-ssh-ed25519-cert-v01@openssh.com" :
+ "sk-ssh-ed25519@openssh.com";
+ break;
+ default:
+ fatal("unknown key type %d", c->c_keytype);
+ break;
+ }
if ((r = kex_setup(c->c_ssh, myproposal)) != 0) {
free(c->c_ssh);
fprintf(stderr, "kex_setup: %s\n", ssh_err(r));
exit(1);
}
#ifdef WITH_OPENSSL
- c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
- c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
+ c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client;
+ c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client;
+ c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client;
+ c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client;
+ c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client;
c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
# ifdef OPENSSL_HAS_ECC
- c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
+ c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client;
# endif
#endif
- c->c_ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client;
+ c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
+ c->c_ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper);
/*
* do the key-exchange until an error occurs or until
* the key_print_wrapper() callback sets c_done.
*/
- ssh_dispatch_run(c->c_ssh, DISPATCH_BLOCK, &c->c_done, c->c_ssh);
+ ssh_dispatch_run(c->c_ssh, DISPATCH_BLOCK, &c->c_done);
}
static void
-keyprint(con *c, struct sshkey *key)
+keyprint_one(const char *host, struct sshkey *key)
{
- char *host = c->c_output_name ? c->c_output_name : c->c_name;
+ char *hostport;
+ const char *known_host, *hashed;
+
+ found_one = 1;
- if (!key)
+ if (print_sshfp) {
+ export_dns_rr(host, key, stdout, 0);
return;
- if (hash_hosts && (host = host_hash(host, NULL, 0)) == NULL)
- fatal("host_hash failed");
+ }
- fprintf(stdout, "%s ", host);
+ hostport = put_host_port(host, ssh_port);
+ lowercase(hostport);
+ if (hash_hosts && (hashed = host_hash(host, NULL, 0)) == NULL)
+ fatal("host_hash failed");
+ known_host = hash_hosts ? hashed : hostport;
+ if (!get_cert)
+ fprintf(stdout, "%s ", known_host);
sshkey_write(key, stdout);
fputs("\n", stdout);
+ free(hostport);
+}
+
+static void
+keyprint(con *c, struct sshkey *key)
+{
+ char *hosts = c->c_output_name ? c->c_output_name : c->c_name;
+ char *host, *ohosts;
+
+ if (key == NULL)
+ return;
+ if (get_cert || (!hash_hosts && ssh_port == SSH_DEFAULT_PORT)) {
+ keyprint_one(hosts, key);
+ return;
+ }
+ ohosts = hosts = xstrdup(hosts);
+ while ((host = strsep(&hosts, ",")) != NULL)
+ keyprint_one(host, key);
+ free(ohosts);
}
static int
@@ -327,13 +362,13 @@ tcpconnect(char *host)
}
for (ai = aitop; ai; ai = ai->ai_next) {
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (s < 0) {
+ if (s == -1) {
error("socket: %s", strerror(errno));
continue;
}
if (set_nonblock(s) == -1)
fatal("%s: set_nonblock(%d)", __func__, s);
- if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0 &&
+ if (connect(s, ai->ai_addr, ai->ai_addrlen) == -1 &&
errno != EINPROGRESS)
error("connect (`%s'): %s", host, strerror(errno));
else
@@ -366,6 +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);
fdcon[s].c_fd = s;
fdcon[s].c_status = CS_CON;
fdcon[s].c_namebase = namebase;
@@ -376,7 +412,7 @@ conalloc(char *iname, char *oname, int keytype)
fdcon[s].c_len = 4;
fdcon[s].c_off = 0;
fdcon[s].c_keytype = keytype;
- gettimeofday(&fdcon[s].c_tv, NULL);
+ monotime_tv(&fdcon[s].c_tv);
fdcon[s].c_tv.tv_sec += timeout;
TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link);
FD_SET(s, read_wait);
@@ -389,7 +425,6 @@ confree(int s)
{
if (s >= maxfd || fdcon[s].c_status == CS_UNUSED)
fatal("confree: attempt to free bad fdno %d", s);
- close(s);
free(fdcon[s].c_namebase);
free(fdcon[s].c_output_name);
if (fdcon[s].c_status == CS_KEYS)
@@ -400,7 +435,8 @@ confree(int s)
ssh_packet_close(fdcon[s].c_ssh);
free(fdcon[s].c_ssh);
fdcon[s].c_ssh = NULL;
- }
+ } else
+ close(s);
TAILQ_REMOVE(&tq, &fdcon[s], c_link);
FD_CLR(s, read_wait);
ncon--;
@@ -410,7 +446,7 @@ static void
contouch(int s)
{
TAILQ_REMOVE(&tq, &fdcon[s], c_link);
- gettimeofday(&fdcon[s].c_tv, NULL);
+ monotime_tv(&fdcon[s].c_tv);
fdcon[s].c_tv.tv_sec += timeout;
TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link);
}
@@ -435,6 +471,20 @@ congreet(int s)
size_t bufsiz;
con *c = &fdcon[s];
+ /* send client banner */
+ n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n",
+ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2);
+ if (n < 0 || (size_t)n >= sizeof(buf)) {
+ error("snprintf: buffer too small");
+ confree(s);
+ return;
+ }
+ if (atomicio(vwrite, s, buf, n) != (size_t)n) {
+ error("write (%s): %s", c->c_name, strerror(errno));
+ confree(s);
+ return;
+ }
+
for (;;) {
memset(buf, '\0', sizeof(buf));
bufsiz = sizeof(buf);
@@ -477,38 +527,15 @@ congreet(int s)
c->c_ssh->compat = compat_datafellows(remote_version);
else
c->c_ssh->compat = 0;
- if (c->c_keytype != KT_RSA1) {
- if (!ssh2_capable(remote_major, remote_minor)) {
- debug("%s doesn't support ssh2", c->c_name);
- confree(s);
- return;
- }
- } else if (remote_major != 1) {
- debug("%s doesn't support ssh1", c->c_name);
+ if (!ssh2_capable(remote_major, remote_minor)) {
+ debug("%s doesn't support ssh2", c->c_name);
confree(s);
return;
}
- fprintf(stderr, "# %s %s\n", c->c_name, chop(buf));
- n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n",
- c->c_keytype == KT_RSA1? PROTOCOL_MAJOR_1 : PROTOCOL_MAJOR_2,
- c->c_keytype == KT_RSA1? PROTOCOL_MINOR_1 : PROTOCOL_MINOR_2);
- if (n < 0 || (size_t)n >= sizeof(buf)) {
- error("snprintf: buffer too small");
- confree(s);
- return;
- }
- if (atomicio(vwrite, s, buf, n) != (size_t)n) {
- error("write (%s): %s", c->c_name, strerror(errno));
- confree(s);
- return;
- }
- if (c->c_keytype != KT_RSA1) {
- keygrab_ssh2(c);
- confree(s);
- return;
- }
- c->c_status = CS_SIZE;
- contouch(s);
+ fprintf(stderr, "%c %s:%d %s\n", print_sshfp ? ';' : '#',
+ c->c_name, ssh_port, chop(buf));
+ keygrab_ssh2(c);
+ confree(s);
}
static void
@@ -538,12 +565,6 @@ conread(int s)
c->c_data = xmalloc(c->c_len);
c->c_status = CS_KEYS;
break;
-#ifdef WITH_SSH1
- case CS_KEYS:
- keyprint(c, keygrab_ssh1(c));
- confree(s);
- return;
-#endif
default:
fatal("conread: invalid status %d", c->c_status);
break;
@@ -560,7 +581,7 @@ conloop(void)
con *c;
int i;
- gettimeofday(&now, NULL);
+ monotime_tv(&now);
c = TAILQ_FIRST(&tq);
if (c && (c->c_tv.tv_sec > now.tv_sec ||
@@ -612,7 +633,7 @@ do_host(char *host)
if (name == NULL)
return;
- for (j = KT_RSA1; j <= KT_ED25519; j *= 2) {
+ for (j = KT_MIN; j <= KT_MAX; j *= 2) {
if (get_keytypes & j) {
while (ncon >= MAXCON)
conloop();
@@ -636,8 +657,8 @@ static void
usage(void)
{
fprintf(stderr,
- "usage: %s [-46Hv] [-f file] [-p port] [-T timeout] [-t type]\n"
- "\t\t [host | addrlist namelist] ...\n",
+ "usage: %s [-46cDHv] [-f file] [-p port] [-T timeout] [-t type]\n"
+ "\t\t [host | addrlist namelist]\n",
__progname);
exit(1);
}
@@ -647,9 +668,9 @@ main(int argc, char **argv)
{
int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO;
int opt, fopt_count = 0, j;
- char *tname, *cp, line[NI_MAXHOST];
+ char *tname, *cp, *line = NULL;
+ size_t linesize = 0;
FILE *fp;
- u_long linenum;
extern int optind;
extern char *optarg;
@@ -664,11 +685,17 @@ main(int argc, char **argv)
if (argc <= 1)
usage();
- while ((opt = getopt(argc, argv, "Hv46p:T:t:f:")) != -1) {
+ while ((opt = getopt(argc, argv, "cDHv46p:T:t:f:")) != -1) {
switch (opt) {
case 'H':
hash_hosts = 1;
break;
+ case 'c':
+ get_cert = 1;
+ break;
+ case 'D':
+ print_sshfp = 1;
+ break;
case 'p':
ssh_port = a2port(optarg);
if (ssh_port <= 0) {
@@ -703,10 +730,8 @@ main(int argc, char **argv)
tname = strtok(optarg, ",");
while (tname) {
int type = sshkey_type_from_name(tname);
+
switch (type) {
- case KEY_RSA1:
- get_keytypes |= KT_RSA1;
- break;
case KEY_DSA:
get_keytypes |= KT_DSA;
break;
@@ -719,8 +744,18 @@ main(int argc, char **argv)
case KEY_ED25519:
get_keytypes |= KT_ED25519;
break;
+ case KEY_XMSS:
+ get_keytypes |= KT_XMSS;
+ break;
+ case KEY_ED25519_SK:
+ get_keytypes |= KT_ED25519_SK;
+ break;
+ case KEY_ECDSA_SK:
+ get_keytypes |= KT_ECDSA_SK;
+ break;
case KEY_UNSPEC:
- fatal("unknown key type %s", tname);
+ default:
+ fatal("Unknown key type \"%s\"", tname);
}
tname = strtok(NULL, ",");
}
@@ -761,11 +796,8 @@ main(int argc, char **argv)
else if ((fp = fopen(argv[j], "r")) == NULL)
fatal("%s: %s: %s", __progname, argv[j],
strerror(errno));
- linenum = 0;
- while (read_keyfile_line(fp,
- argv[j] == NULL ? "(stdin)" : argv[j], line, sizeof(line),
- &linenum) != -1) {
+ while (getline(&line, &linesize, fp) != -1) {
/* Chomp off trailing whitespace and comments */
if ((cp = strchr(line, '#')) == NULL)
cp = line + strlen(line) - 1;
@@ -790,6 +822,7 @@ main(int argc, char **argv)
fclose(fp);
}
+ free(line);
while (optind < argc)
do_host(argv[optind++]);
@@ -797,5 +830,5 @@ main(int argc, char **argv)
while (ncon > 0)
conloop();
- return (0);
+ return found_one ? 0 : 1;
}
diff --git a/ssh-keysign.0 b/ssh-keysign.0
deleted file mode 100644
index b0610761..00000000
--- a/ssh-keysign.0
+++ /dev/null
@@ -1,53 +0,0 @@
-SSH-KEYSIGN(8) System Manager's Manual SSH-KEYSIGN(8)
-
-NAME
- ssh-keysign M-bM-^@M-^S ssh helper program for host-based authentication
-
-SYNOPSIS
- ssh-keysign
-
-DESCRIPTION
- ssh-keysign is used by ssh(1) to access the local host keys and generate
- the digital signature required during host-based authentication with SSH
- protocol version 2.
-
- ssh-keysign is disabled by default and can only be enabled in the global
- client configuration file /etc/ssh/ssh_config by setting EnableSSHKeysign
- to M-bM-^@M-^\yesM-bM-^@M-^].
-
- ssh-keysign is not intended to be invoked by the user, but from ssh(1).
- See ssh(1) and sshd(8) for more information about host-based
- authentication.
-
-FILES
- /etc/ssh/ssh_config
- Controls whether ssh-keysign is enabled.
-
- /etc/ssh/ssh_host_dsa_key
- /etc/ssh/ssh_host_ecdsa_key
- /etc/ssh/ssh_host_ed25519_key
- /etc/ssh/ssh_host_rsa_key
- These files contain the private parts of the host keys used to
- generate the digital signature. They should be owned by root,
- readable only by root, and not accessible to others. Since they
- are readable only by root, ssh-keysign must be set-uid root if
- host-based authentication is used.
-
- /etc/ssh/ssh_host_dsa_key-cert.pub
- /etc/ssh/ssh_host_ecdsa_key-cert.pub
- /etc/ssh/ssh_host_ed25519_key-cert.pub
- /etc/ssh/ssh_host_rsa_key-cert.pub
- If these files exist they are assumed to contain public
- certificate information corresponding with the private keys
- above.
-
-SEE ALSO
- ssh(1), ssh-keygen(1), ssh_config(5), sshd(8)
-
-HISTORY
- ssh-keysign first appeared in OpenBSD 3.2.
-
-AUTHORS
- Markus Friedl <markus@openbsd.org>
-
-OpenBSD 5.7 December 7, 2013 OpenBSD 5.7
diff --git a/ssh-keysign.8 b/ssh-keysign.8
index 69d08295..73b62397 100644
--- a/ssh-keysign.8
+++ b/ssh-keysign.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-keysign.8,v 1.14 2013/12/07 11:58:46 naddy Exp $
+.\" $OpenBSD: ssh-keysign.8,v 1.16 2019/11/30 07:07:59 jmc Exp $
.\"
.\" Copyright (c) 2002 Markus Friedl. All rights reserved.
.\"
@@ -22,12 +22,12 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: December 7 2013 $
+.Dd $Mdocdate: November 30 2019 $
.Dt SSH-KEYSIGN 8
.Os
.Sh NAME
.Nm ssh-keysign
-.Nd ssh helper program for host-based authentication
+.Nd OpenSSH helper for host-based authentication
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
@@ -35,7 +35,7 @@
is used by
.Xr ssh 1
to access the local host keys and generate the digital signature
-required during host-based authentication with SSH protocol version 2.
+required during host-based authentication.
.Pp
.Nm
is disabled by default and can only be enabled in the
diff --git a/ssh-keysign.c b/ssh-keysign.c
index bcf897a0..3e3ea3e1 100644
--- a/ssh-keysign.c
+++ b/ssh-keysign.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keysign.c,v 1.47 2015/01/28 22:36:00 djm Exp $ */
+/* $OpenBSD: ssh-keysign.c,v 1.63 2019/11/18 16:10:05 naddy Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
@@ -31,14 +31,17 @@
#endif
#include <pwd.h>
#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#ifdef WITH_OPENSSL
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
+#include "openbsd-compat/openssl-compat.h"
#endif
#include "xmalloc.h"
@@ -54,14 +57,8 @@
#include "pathnames.h"
#include "readconf.h"
#include "uidswap.h"
-#include "sshkey.h"
#include "ssherr.h"
-struct ssh *active_state = NULL; /* XXX needed for linking */
-
-/* XXX readconf.c needs these */
-uid_t original_real_uid;
-
extern char *__progname;
static int
@@ -155,9 +152,9 @@ valid_request(struct passwd *pw, char *host, struct sshkey **ret,
debug3("%s: fail %d", __func__, fail);
- if (fail && key != NULL)
+ if (fail)
sshkey_free(key);
- else
+ else if (ret != NULL)
*ret = key;
return (fail ? -1 : 0);
@@ -168,16 +165,16 @@ main(int argc, char **argv)
{
struct sshbuf *b;
Options options;
-#define NUM_KEYTYPES 4
+#define NUM_KEYTYPES 5
struct sshkey *keys[NUM_KEYTYPES], *key = NULL;
struct passwd *pw;
int r, key_fd[NUM_KEYTYPES], i, found, version = 2, fd;
u_char *signature, *data, rver;
char *host, *fp;
size_t slen, dlen;
-#ifdef WITH_OPENSSL
- u_int32_t rnd[256];
-#endif
+
+ if (pledge("stdio rpath getpw dns id", NULL) != 0)
+ fatal("%s: pledge: %s", __progname, strerror(errno));
/* Ensure that stdin and stdout are connected */
if ((fd = open(_PATH_DEVNULL, O_RDWR)) < 2)
@@ -187,13 +184,14 @@ main(int argc, char **argv)
close(fd);
i = 0;
+ /* XXX This really needs to read sshd_config for the paths */
key_fd[i++] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY);
key_fd[i++] = open(_PATH_HOST_ECDSA_KEY_FILE, O_RDONLY);
key_fd[i++] = open(_PATH_HOST_ED25519_KEY_FILE, O_RDONLY);
+ key_fd[i++] = open(_PATH_HOST_XMSS_KEY_FILE, O_RDONLY);
key_fd[i++] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY);
- original_real_uid = getuid(); /* XXX readconf.c needs this */
- if ((pw = getpwuid(original_real_uid)) == NULL)
+ if ((pw = getpwuid(getuid())) == NULL)
fatal("getpwuid failed");
pw = pwcopy(pw);
@@ -207,7 +205,8 @@ main(int argc, char **argv)
/* verify that ssh-keysign is enabled by the admin */
initialize_options(&options);
- (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "", &options, 0);
+ (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "",
+ &options, 0, NULL);
fill_default_options(&options);
if (options.enable_ssh_keysign != 1)
fatal("ssh-keysign not enabled in %s",
@@ -220,12 +219,6 @@ main(int argc, char **argv)
if (found == 0)
fatal("could not open any host key");
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
- arc4random_buf(rnd, sizeof(rnd));
- RAND_seed(rnd, sizeof(rnd));
-#endif
-
found = 0;
for (i = 0; i < NUM_KEYTYPES; i++) {
keys[i] = NULL;
@@ -244,23 +237,26 @@ main(int argc, char **argv)
if (!found)
fatal("no hostkey found");
+ if (pledge("stdio dns", NULL) != 0)
+ fatal("%s: pledge: %s", __progname, strerror(errno));
+
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal("%s: sshbuf_new failed", __progname);
if (ssh_msg_recv(STDIN_FILENO, b) < 0)
fatal("ssh_msg_recv failed");
if ((r = sshbuf_get_u8(b, &rver)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal("%s: buffer error: %s", __progname, ssh_err(r));
if (rver != version)
fatal("bad version: received %d, expected %d", rver, version);
if ((r = sshbuf_get_u32(b, (u_int *)&fd)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal("%s: buffer error: %s", __progname, ssh_err(r));
if (fd < 0 || fd == STDIN_FILENO || fd == STDOUT_FILENO)
- fatal("bad fd");
+ fatal("bad fd = %d", fd);
if ((host = get_local_name(fd)) == NULL)
fatal("cannot get local name for fd");
if ((r = sshbuf_get_string(b, &data, &dlen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal("%s: buffer error: %s", __progname, ssh_err(r));
if (valid_request(pw, host, &key, data, dlen) < 0)
fatal("not a valid request");
free(host);
@@ -276,19 +272,20 @@ main(int argc, char **argv)
if (!found) {
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
- fatal("%s: sshkey_fingerprint failed", __func__);
+ fatal("%s: sshkey_fingerprint failed", __progname);
fatal("no matching hostkey found for key %s %s",
sshkey_type(key), fp ? fp : "");
}
- if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, 0)) != 0)
+ if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen,
+ NULL, NULL, 0)) != 0)
fatal("sshkey_sign failed: %s", ssh_err(r));
free(data);
/* send reply */
sshbuf_reset(b);
if ((r = sshbuf_put_string(b, signature, slen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal("%s: buffer error: %s", __progname, ssh_err(r));
if (ssh_msg_send(STDOUT_FILENO, version, b) == -1)
fatal("ssh_msg_send failed");
diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c
index 8c74864a..8a0ffef5 100644
--- a/ssh-pkcs11-client.c
+++ b/ssh-pkcs11-client.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: ssh-pkcs11-client.c,v 1.5 2014/06/24 01:13:21 djm Exp $ */
+/* $OpenBSD: ssh-pkcs11-client.c,v 1.16 2020/01/25 00:03:36 djm Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
+ * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -30,52 +31,59 @@
#include <unistd.h>
#include <errno.h>
+#include <openssl/ecdsa.h>
#include <openssl/rsa.h>
+#include "openbsd-compat/openssl-compat.h"
+
#include "pathnames.h"
#include "xmalloc.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "log.h"
#include "misc.h"
-#include "key.h"
+#include "sshkey.h"
#include "authfd.h"
#include "atomicio.h"
#include "ssh-pkcs11.h"
+#include "ssherr.h"
/* borrows code from sftp-server and ssh-agent */
-int fd = -1;
-pid_t pid = -1;
+static int fd = -1;
+static pid_t pid = -1;
static void
-send_msg(Buffer *m)
+send_msg(struct sshbuf *m)
{
u_char buf[4];
- int mlen = buffer_len(m);
+ size_t mlen = sshbuf_len(m);
+ int r;
- put_u32(buf, mlen);
+ POKE_U32(buf, mlen);
if (atomicio(vwrite, fd, buf, 4) != 4 ||
- atomicio(vwrite, fd, buffer_ptr(m),
- buffer_len(m)) != buffer_len(m))
+ atomicio(vwrite, fd, sshbuf_mutable_ptr(m),
+ sshbuf_len(m)) != sshbuf_len(m))
error("write to helper failed");
- buffer_consume(m, mlen);
+ if ((r = sshbuf_consume(m, mlen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
static int
-recv_msg(Buffer *m)
+recv_msg(struct sshbuf *m)
{
u_int l, len;
- u_char buf[1024];
+ u_char c, buf[1024];
+ int r;
if ((len = atomicio(read, fd, buf, 4)) != 4) {
error("read from helper failed: %u", len);
return (0); /* XXX */
}
- len = get_u32(buf);
+ len = PEEK_U32(buf);
if (len > 256 * 1024)
fatal("response too long: %u", len);
/* read len bytes into m */
- buffer_clear(m);
+ sshbuf_reset(m);
while (len > 0) {
l = len;
if (l > sizeof(buf))
@@ -84,10 +92,13 @@ recv_msg(Buffer *m)
error("response from helper failed.");
return (0); /* XXX */
}
- buffer_append(m, buf, l);
+ if ((r = sshbuf_put(m, buf, l)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
len -= l;
}
- return (buffer_get_char(m));
+ if ((r = sshbuf_get_u8(m, &c)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ return c;
}
int
@@ -99,56 +110,161 @@ pkcs11_init(int interactive)
void
pkcs11_terminate(void)
{
- close(fd);
+ if (fd >= 0)
+ close(fd);
}
static int
-pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
- int padding)
+rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
{
- Key key;
- u_char *blob, *signature = NULL;
- u_int blen, slen = 0;
- int ret = -1;
- Buffer msg;
+ struct sshkey *key = NULL;
+ struct sshbuf *msg = NULL;
+ u_char *blob = NULL, *signature = NULL;
+ size_t blen, slen = 0;
+ int r, ret = -1;
if (padding != RSA_PKCS1_PADDING)
- return (-1);
- key.type = KEY_RSA;
- key.rsa = rsa;
- if (key_to_blob(&key, &blob, &blen) == 0)
- return -1;
- buffer_init(&msg);
- buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
- buffer_put_string(&msg, blob, blen);
- buffer_put_string(&msg, from, flen);
- buffer_put_int(&msg, 0);
- free(blob);
- send_msg(&msg);
- buffer_clear(&msg);
+ goto fail;
+ key = sshkey_new(KEY_UNSPEC);
+ if (key == NULL) {
+ error("%s: sshkey_new failed", __func__);
+ goto fail;
+ }
+ key->type = KEY_RSA;
+ RSA_up_ref(rsa);
+ key->rsa = rsa;
+ if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
+ error("%s: sshkey_to_blob: %s", __func__, ssh_err(r));
+ goto fail;
+ }
+ if ((msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
+ (r = sshbuf_put_string(msg, blob, blen)) != 0 ||
+ (r = sshbuf_put_string(msg, from, flen)) != 0 ||
+ (r = sshbuf_put_u32(msg, 0)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ send_msg(msg);
+ sshbuf_reset(msg);
- if (recv_msg(&msg) == SSH2_AGENT_SIGN_RESPONSE) {
- signature = buffer_get_string(&msg, &slen);
- if (slen <= (u_int)RSA_size(rsa)) {
+ if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
+ if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (slen <= (size_t)RSA_size(rsa)) {
memcpy(to, signature, slen);
ret = slen;
}
free(signature);
}
- buffer_free(&msg);
+ fail:
+ free(blob);
+ sshkey_free(key);
+ sshbuf_free(msg);
return (ret);
}
-/* redirect the private key encrypt operation to the ssh-pkcs11-helper */
+#ifdef HAVE_EC_KEY_METHOD_NEW
+static ECDSA_SIG *
+ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
+ const BIGNUM *rp, EC_KEY *ec)
+{
+ struct sshkey *key = NULL;
+ struct sshbuf *msg = NULL;
+ ECDSA_SIG *ret = NULL;
+ const u_char *cp;
+ u_char *blob = NULL, *signature = NULL;
+ size_t blen, slen = 0;
+ int r, nid;
+
+ nid = sshkey_ecdsa_key_to_nid(ec);
+ if (nid < 0) {
+ error("%s: couldn't get curve nid", __func__);
+ goto fail;
+ }
+
+ key = sshkey_new(KEY_UNSPEC);
+ if (key == NULL) {
+ error("%s: sshkey_new failed", __func__);
+ goto fail;
+ }
+ key->ecdsa = ec;
+ key->ecdsa_nid = nid;
+ key->type = KEY_ECDSA;
+ EC_KEY_up_ref(ec);
+
+ if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
+ error("%s: sshkey_to_blob: %s", __func__, ssh_err(r));
+ goto fail;
+ }
+ if ((msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
+ (r = sshbuf_put_string(msg, blob, blen)) != 0 ||
+ (r = sshbuf_put_string(msg, dgst, dgst_len)) != 0 ||
+ (r = sshbuf_put_u32(msg, 0)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ send_msg(msg);
+ sshbuf_reset(msg);
+
+ if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
+ if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ cp = signature;
+ ret = d2i_ECDSA_SIG(NULL, &cp, slen);
+ free(signature);
+ }
+
+ fail:
+ free(blob);
+ sshkey_free(key);
+ sshbuf_free(msg);
+ return (ret);
+}
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+
+static RSA_METHOD *helper_rsa;
+#ifdef HAVE_EC_KEY_METHOD_NEW
+static EC_KEY_METHOD *helper_ecdsa;
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+
+/* redirect private key crypto operations to the ssh-pkcs11-helper */
+static void
+wrap_key(struct sshkey *k)
+{
+ if (k->type == KEY_RSA)
+ RSA_set_method(k->rsa, helper_rsa);
+#ifdef HAVE_EC_KEY_METHOD_NEW
+ else if (k->type == KEY_ECDSA)
+ EC_KEY_set_method(k->ecdsa, helper_ecdsa);
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+ else
+ fatal("%s: unknown key type", __func__);
+}
+
static int
-wrap_key(RSA *rsa)
+pkcs11_start_helper_methods(void)
{
- static RSA_METHOD helper_rsa;
+ if (helper_rsa != NULL)
+ return (0);
+
+#ifdef HAVE_EC_KEY_METHOD_NEW
+ int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
+ unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
+ if (helper_ecdsa != NULL)
+ return (0);
+ helper_ecdsa = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
+ if (helper_ecdsa == NULL)
+ return (-1);
+ EC_KEY_METHOD_get_sign(helper_ecdsa, &orig_sign, NULL, NULL);
+ EC_KEY_METHOD_set_sign(helper_ecdsa, orig_sign, NULL, ecdsa_do_sign);
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+
+ if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL)
+ fatal("%s: RSA_meth_dup failed", __func__);
+ if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") ||
+ !RSA_meth_set_priv_enc(helper_rsa, rsa_encrypt))
+ fatal("%s: failed to prepare method", __func__);
- memcpy(&helper_rsa, RSA_get_default_method(), sizeof(helper_rsa));
- helper_rsa.name = "ssh-pkcs11-helper";
- helper_rsa.rsa_priv_enc = pkcs11_rsa_private_encrypt;
- RSA_set_method(rsa, &helper_rsa);
return (0);
}
@@ -156,6 +272,15 @@ static int
pkcs11_start_helper(void)
{
int pair[2];
+ char *helper, *verbosity = NULL;
+
+ if (log_level_get() >= SYSLOG_LEVEL_DEBUG1)
+ verbosity = "-vvv";
+
+ if (pkcs11_start_helper_methods() == -1) {
+ error("pkcs11_start_helper_methods failed");
+ return (-1);
+ }
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
error("socketpair: %s", strerror(errno));
@@ -172,10 +297,13 @@ pkcs11_start_helper(void)
}
close(pair[0]);
close(pair[1]);
- execlp(_PATH_SSH_PKCS11_HELPER, _PATH_SSH_PKCS11_HELPER,
- (char *) 0);
- fprintf(stderr, "exec: %s: %s\n", _PATH_SSH_PKCS11_HELPER,
- strerror(errno));
+ helper = getenv("SSH_PKCS11_HELPER");
+ if (helper == NULL || strlen(helper) == 0)
+ helper = _PATH_SSH_PKCS11_HELPER;
+ debug("%s: starting %s %s", __func__, helper,
+ verbosity == NULL ? "" : verbosity);
+ execlp(helper, helper, verbosity, (char *)NULL);
+ fprintf(stderr, "exec: %s: %s\n", helper, strerror(errno));
_exit(1);
}
close(pair[1]);
@@ -184,58 +312,80 @@ pkcs11_start_helper(void)
}
int
-pkcs11_add_provider(char *name, char *pin, Key ***keysp)
+pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
+ char ***labelsp)
{
- Key *k;
- int i, nkeys;
+ struct sshkey *k;
+ int r, type;
u_char *blob;
- u_int blen;
- Buffer msg;
+ char *label;
+ size_t blen;
+ u_int nkeys, i;
+ struct sshbuf *msg;
if (fd < 0 && pkcs11_start_helper() < 0)
return (-1);
- buffer_init(&msg);
- buffer_put_char(&msg, SSH_AGENTC_ADD_SMARTCARD_KEY);
- buffer_put_cstring(&msg, name);
- buffer_put_cstring(&msg, pin);
- send_msg(&msg);
- buffer_clear(&msg);
+ if ((msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u8(msg, SSH_AGENTC_ADD_SMARTCARD_KEY)) != 0 ||
+ (r = sshbuf_put_cstring(msg, name)) != 0 ||
+ (r = sshbuf_put_cstring(msg, pin)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ send_msg(msg);
+ sshbuf_reset(msg);
- if (recv_msg(&msg) == SSH2_AGENT_IDENTITIES_ANSWER) {
- nkeys = buffer_get_int(&msg);
- *keysp = xcalloc(nkeys, sizeof(Key *));
+ type = recv_msg(msg);
+ if (type == SSH2_AGENT_IDENTITIES_ANSWER) {
+ if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ *keysp = xcalloc(nkeys, sizeof(struct sshkey *));
+ if (labelsp)
+ *labelsp = xcalloc(nkeys, sizeof(char *));
for (i = 0; i < nkeys; i++) {
- blob = buffer_get_string(&msg, &blen);
- free(buffer_get_string(&msg, NULL));
- k = key_from_blob(blob, blen);
- wrap_key(k->rsa);
+ /* 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));
+ if ((r = sshkey_from_blob(blob, blen, &k)) != 0)
+ fatal("%s: bad key: %s", __func__, ssh_err(r));
+ wrap_key(k);
(*keysp)[i] = k;
+ if (labelsp)
+ (*labelsp)[i] = label;
+ else
+ free(label);
free(blob);
}
+ } else if (type == SSH2_AGENT_FAILURE) {
+ if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
+ nkeys = -1;
} else {
nkeys = -1;
}
- buffer_free(&msg);
+ sshbuf_free(msg);
return (nkeys);
}
int
pkcs11_del_provider(char *name)
{
- int ret = -1;
- Buffer msg;
+ int r, ret = -1;
+ struct sshbuf *msg;
- buffer_init(&msg);
- buffer_put_char(&msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY);
- buffer_put_cstring(&msg, name);
- buffer_put_cstring(&msg, "");
- send_msg(&msg);
- buffer_clear(&msg);
+ if ((msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u8(msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY)) != 0 ||
+ (r = sshbuf_put_cstring(msg, name)) != 0 ||
+ (r = sshbuf_put_cstring(msg, "")) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ send_msg(msg);
+ sshbuf_reset(msg);
- if (recv_msg(&msg) == SSH_AGENT_SUCCESS)
+ if (recv_msg(msg) == SSH_AGENT_SUCCESS)
ret = 0;
- buffer_free(&msg);
+ sshbuf_free(msg);
return (ret);
}
diff --git a/ssh-pkcs11-helper.0 b/ssh-pkcs11-helper.0
deleted file mode 100644
index a4d6dd4c..00000000
--- a/ssh-pkcs11-helper.0
+++ /dev/null
@@ -1,25 +0,0 @@
-SSH-PKCS11-HELPER(8) System Manager's Manual SSH-PKCS11-HELPER(8)
-
-NAME
- ssh-pkcs11-helper M-bM-^@M-^S ssh-agent helper program for PKCS#11 support
-
-SYNOPSIS
- ssh-pkcs11-helper
-
-DESCRIPTION
- ssh-pkcs11-helper is used by ssh-agent(1) to access keys provided by a
- PKCS#11 token.
-
- ssh-pkcs11-helper is not intended to be invoked by the user, but from
- ssh-agent(1).
-
-SEE ALSO
- ssh(1), ssh-add(1), ssh-agent(1)
-
-HISTORY
- ssh-pkcs11-helper first appeared in OpenBSD 4.7.
-
-AUTHORS
- Markus Friedl <markus@openbsd.org>
-
-OpenBSD 5.7 July 16, 2013 OpenBSD 5.7
diff --git a/ssh-pkcs11-helper.8 b/ssh-pkcs11-helper.8
index 3728c4e4..6a592b1f 100644
--- a/ssh-pkcs11-helper.8
+++ b/ssh-pkcs11-helper.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-pkcs11-helper.8,v 1.4 2013/07/16 00:07:52 schwarze Exp $
+.\" $OpenBSD: ssh-pkcs11-helper.8,v 1.6 2019/11/30 07:07:59 jmc Exp $
.\"
.\" Copyright (c) 2010 Markus Friedl. All rights reserved.
.\"
@@ -14,14 +14,15 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: July 16 2013 $
+.Dd $Mdocdate: November 30 2019 $
.Dt SSH-PKCS11-HELPER 8
.Os
.Sh NAME
.Nm ssh-pkcs11-helper
-.Nd ssh-agent helper program for PKCS#11 support
+.Nd OpenSSH helper for PKCS#11 support
.Sh SYNOPSIS
.Nm
+.Op Fl v
.Sh DESCRIPTION
.Nm
is used by
@@ -31,6 +32,28 @@ to access keys provided by a PKCS#11 token.
.Nm
is not intended to be invoked by the user, but from
.Xr ssh-agent 1 .
+.Pp
+A single option is supported:
+.Bl -tag -width Ds
+.It Fl v
+Verbose mode.
+Causes
+.Nm
+to print debugging messages about its progress.
+This is helpful in debugging problems.
+Multiple
+.Fl v
+options increase the verbosity.
+The maximum is 3.
+.Pp
+Note that
+.Xr ssh-agent 1
+will automatically pass the
+.Fl v
+flag to
+.Nm
+when it has itself been placed in debug mode.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c
index ceabc8ba..d73e8357 100644
--- a/ssh-pkcs11-helper.c
+++ b/ssh-pkcs11-helper.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-pkcs11-helper.c,v 1.10 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: ssh-pkcs11-helper.c,v 1.23 2020/03/06 18:26:21 markus Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
*
@@ -24,26 +24,33 @@
#include "openbsd-compat/sys-queue.h"
+#include <stdlib.h>
+#include <errno.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
-#include <errno.h>
#include "xmalloc.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "log.h"
#include "misc.h"
-#include "key.h"
+#include "sshkey.h"
#include "authfd.h"
#include "ssh-pkcs11.h"
+#include "ssherr.h"
#ifdef ENABLE_PKCS11
+#ifdef WITH_OPENSSL
+
/* borrows code from sftp-server and ssh-agent */
struct pkcs11_keyinfo {
- Key *key;
- char *providername;
+ struct sshkey *key;
+ char *providername, *label;
TAILQ_ENTRY(pkcs11_keyinfo) next;
};
@@ -51,22 +58,19 @@ TAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist;
#define MAX_MSG_LENGTH 10240 /*XXX*/
-/* helper */
-#define get_int() buffer_get_int(&iqueue);
-#define get_string(lenp) buffer_get_string(&iqueue, lenp);
-
/* input and output queue */
-Buffer iqueue;
-Buffer oqueue;
+struct sshbuf *iqueue;
+struct sshbuf *oqueue;
static void
-add_key(Key *k, char *name)
+add_key(struct sshkey *k, char *name, char *label)
{
struct pkcs11_keyinfo *ki;
ki = xcalloc(1, sizeof(*ki));
ki->providername = xstrdup(name);
ki->key = k;
+ ki->label = xstrdup(label);
TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next);
}
@@ -80,131 +84,175 @@ del_keys_by_name(char *name)
if (!strcmp(ki->providername, name)) {
TAILQ_REMOVE(&pkcs11_keylist, ki, next);
free(ki->providername);
- key_free(ki->key);
+ free(ki->label);
+ sshkey_free(ki->key);
free(ki);
}
}
}
/* lookup matching 'private' key */
-static Key *
-lookup_key(Key *k)
+static struct sshkey *
+lookup_key(struct sshkey *k)
{
struct pkcs11_keyinfo *ki;
TAILQ_FOREACH(ki, &pkcs11_keylist, next) {
- debug("check %p %s", ki, ki->providername);
- if (key_equal(k, ki->key))
+ debug("check %p %s %s", ki, ki->providername, ki->label);
+ if (sshkey_equal(k, ki->key))
return (ki->key);
}
return (NULL);
}
static void
-send_msg(Buffer *m)
+send_msg(struct sshbuf *m)
{
- int mlen = buffer_len(m);
+ int r;
- buffer_put_int(&oqueue, mlen);
- buffer_append(&oqueue, buffer_ptr(m), mlen);
- buffer_consume(m, mlen);
+ if ((r = sshbuf_put_stringb(oqueue, m)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
static void
process_add(void)
{
char *name, *pin;
- Key **keys;
- int i, nkeys;
+ struct sshkey **keys = NULL;
+ int r, i, nkeys;
u_char *blob;
- u_int blen;
- Buffer msg;
-
- buffer_init(&msg);
- name = get_string(NULL);
- pin = get_string(NULL);
- if ((nkeys = pkcs11_add_provider(name, pin, &keys)) > 0) {
- buffer_put_char(&msg, SSH2_AGENT_IDENTITIES_ANSWER);
- buffer_put_int(&msg, nkeys);
+ size_t blen;
+ struct sshbuf *msg;
+ char **labels = NULL;
+
+ if ((msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if ((nkeys = pkcs11_add_provider(name, pin, &keys, &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));
for (i = 0; i < nkeys; i++) {
- if (key_to_blob(keys[i], &blob, &blen) == 0)
+ if ((r = sshkey_to_blob(keys[i], &blob, &blen)) != 0) {
+ debug("%s: sshkey_to_blob: %s",
+ __func__, ssh_err(r));
continue;
- buffer_put_string(&msg, blob, blen);
- buffer_put_cstring(&msg, name);
+ }
+ 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));
free(blob);
- add_key(keys[i], name);
+ add_key(keys[i], name, labels[i]);
+ free(labels[i]);
}
- free(keys);
} else {
- buffer_put_char(&msg, SSH_AGENT_FAILURE);
+ if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if ((r = sshbuf_put_u32(msg, -nkeys)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
+ free(labels);
+ free(keys); /* keys themselves are transferred to pkcs11_keylist */
free(pin);
free(name);
- send_msg(&msg);
- buffer_free(&msg);
+ send_msg(msg);
+ sshbuf_free(msg);
}
static void
process_del(void)
{
char *name, *pin;
- Buffer msg;
-
- buffer_init(&msg);
- name = get_string(NULL);
- pin = get_string(NULL);
+ struct sshbuf *msg;
+ int r;
+
+ if ((msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
del_keys_by_name(name);
- if (pkcs11_del_provider(name) == 0)
- buffer_put_char(&msg, SSH_AGENT_SUCCESS);
- else
- buffer_put_char(&msg, SSH_AGENT_FAILURE);
+ if ((r = sshbuf_put_u8(msg, pkcs11_del_provider(name) == 0 ?
+ SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(pin);
free(name);
- send_msg(&msg);
- buffer_free(&msg);
+ send_msg(msg);
+ sshbuf_free(msg);
}
static void
process_sign(void)
{
u_char *blob, *data, *signature = NULL;
- u_int blen, dlen, slen = 0;
- int ok = -1;
- Key *key, *found;
- Buffer msg;
-
- blob = get_string(&blen);
- data = get_string(&dlen);
- (void)get_int(); /* XXX ignore flags */
-
- if ((key = key_from_blob(blob, blen)) != NULL) {
+ size_t blen, dlen, slen = 0;
+ int r, ok = -1;
+ struct sshkey *key, *found;
+ struct sshbuf *msg;
+
+ /* XXX support SHA2 signature flags */
+ if ((r = sshbuf_get_string(iqueue, &blob, &blen)) != 0 ||
+ (r = sshbuf_get_string(iqueue, &data, &dlen)) != 0 ||
+ (r = sshbuf_get_u32(iqueue, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
+ if ((r = sshkey_from_blob(blob, blen, &key)) != 0)
+ error("%s: sshkey_from_blob: %s", __func__, ssh_err(r));
+ else {
if ((found = lookup_key(key)) != NULL) {
#ifdef WITH_OPENSSL
int ret;
- slen = RSA_size(key->rsa);
- signature = xmalloc(slen);
- if ((ret = RSA_private_encrypt(dlen, data, signature,
- found->rsa, RSA_PKCS1_PADDING)) != -1) {
- slen = ret;
- ok = 0;
- }
+ if (key->type == KEY_RSA) {
+ slen = RSA_size(key->rsa);
+ signature = xmalloc(slen);
+ ret = RSA_private_encrypt(dlen, data, signature,
+ found->rsa, RSA_PKCS1_PADDING);
+ if (ret != -1) {
+ slen = ret;
+ ok = 0;
+ }
+#ifdef OPENSSL_HAS_ECC
+ } else if (key->type == KEY_ECDSA) {
+ u_int xslen = ECDSA_size(key->ecdsa);
+
+ signature = xmalloc(xslen);
+ /* "The parameter type is ignored." */
+ ret = ECDSA_sign(-1, data, dlen, signature,
+ &xslen, found->ecdsa);
+ if (ret != 0)
+ ok = 0;
+ else
+ error("%s: ECDSA_sign"
+ " returns %d", __func__, ret);
+ slen = xslen;
+#endif /* OPENSSL_HAS_ECC */
+ } else
+ error("%s: don't know how to sign with key "
+ "type %d", __func__, (int)key->type);
#endif /* WITH_OPENSSL */
}
- key_free(key);
+ sshkey_free(key);
}
- buffer_init(&msg);
+ if ((msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
if (ok == 0) {
- buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
- buffer_put_string(&msg, signature, slen);
+ if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
+ (r = sshbuf_put_string(msg, signature, slen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
} else {
- buffer_put_char(&msg, SSH_AGENT_FAILURE);
+ if ((r = sshbuf_put_u8(msg, SSH2_AGENT_FAILURE)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
free(data);
free(blob);
free(signature);
- send_msg(&msg);
- buffer_free(&msg);
+ send_msg(msg);
+ sshbuf_free(msg);
}
static void
@@ -213,13 +261,14 @@ process(void)
u_int msg_len;
u_int buf_len;
u_int consumed;
- u_int type;
- u_char *cp;
+ u_char type;
+ const u_char *cp;
+ int r;
- buf_len = buffer_len(&iqueue);
+ buf_len = sshbuf_len(iqueue);
if (buf_len < 5)
return; /* Incomplete message. */
- cp = buffer_ptr(&iqueue);
+ cp = sshbuf_ptr(iqueue);
msg_len = get_u32(cp);
if (msg_len > MAX_MSG_LENGTH) {
error("bad message len %d", msg_len);
@@ -227,9 +276,10 @@ process(void)
}
if (buf_len < msg_len + 4)
return;
- buffer_consume(&iqueue, 4);
+ if ((r = sshbuf_consume(iqueue, 4)) != 0 ||
+ (r = sshbuf_get_u8(iqueue, &type)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
buf_len -= 4;
- type = buffer_get_char(&iqueue);
switch (type) {
case SSH_AGENTC_ADD_SMARTCARD_KEY:
debug("process_add");
@@ -248,17 +298,19 @@ process(void)
break;
}
/* discard the remaining bytes from the current packet */
- if (buf_len < buffer_len(&iqueue)) {
+ if (buf_len < sshbuf_len(iqueue)) {
error("iqueue grew unexpectedly");
cleanup_exit(255);
}
- consumed = buf_len - buffer_len(&iqueue);
+ consumed = buf_len - sshbuf_len(iqueue);
if (msg_len < consumed) {
error("msg_len %d < consumed %d", msg_len, consumed);
cleanup_exit(255);
}
- if (msg_len > consumed)
- buffer_consume(&iqueue, msg_len - consumed);
+ if (msg_len > consumed) {
+ if ((r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ }
}
void
@@ -268,68 +320,78 @@ cleanup_exit(int i)
_exit(i);
}
+
int
main(int argc, char **argv)
{
- fd_set *rset, *wset;
- int in, out, max, log_stderr = 0;
- ssize_t len, olen, set_size;
+ int r, ch, in, out, log_stderr = 0;
+ ssize_t len;
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
LogLevel log_level = SYSLOG_LEVEL_ERROR;
char buf[4*4096];
-
extern char *__progname;
+ struct pollfd pfd[2];
+ __progname = ssh_get_progname(argv[0]);
+ seed_rng();
TAILQ_INIT(&pkcs11_keylist);
- pkcs11_init(0);
- seed_rng();
- __progname = ssh_get_progname(argv[0]);
+ log_init(__progname, log_level, log_facility, log_stderr);
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ log_stderr = 1;
+ if (log_level == SYSLOG_LEVEL_ERROR)
+ log_level = SYSLOG_LEVEL_DEBUG1;
+ else if (log_level < SYSLOG_LEVEL_DEBUG3)
+ log_level++;
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", __progname);
+ exit(1);
+ }
+ }
log_init(__progname, log_level, log_facility, log_stderr);
+ pkcs11_init(0);
+
in = STDIN_FILENO;
out = STDOUT_FILENO;
- max = 0;
- if (in > max)
- max = in;
- if (out > max)
- max = out;
+ if ((iqueue = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((oqueue = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
- buffer_init(&iqueue);
- buffer_init(&oqueue);
-
- set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
- rset = (fd_set *)xmalloc(set_size);
- wset = (fd_set *)xmalloc(set_size);
-
- for (;;) {
- memset(rset, 0, set_size);
- memset(wset, 0, set_size);
+ while (1) {
+ memset(pfd, 0, sizeof(pfd));
+ pfd[0].fd = in;
+ pfd[1].fd = out;
/*
* Ensure that we can read a full buffer and handle
* the worst-case length packet it can generate,
* otherwise apply backpressure by stopping reads.
*/
- if (buffer_check_alloc(&iqueue, sizeof(buf)) &&
- buffer_check_alloc(&oqueue, MAX_MSG_LENGTH))
- FD_SET(in, rset);
+ if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
+ (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));
- olen = buffer_len(&oqueue);
- if (olen > 0)
- FD_SET(out, wset);
+ if (sshbuf_len(oqueue) > 0)
+ pfd[1].events = POLLOUT;
- if (select(max+1, rset, wset, NULL, NULL) < 0) {
- if (errno == EINTR)
+ if ((r = poll(pfd, 2, -1 /* INFTIM */)) <= 0) {
+ if (r == 0 || errno == EINTR)
continue;
- error("select: %s", strerror(errno));
- cleanup_exit(2);
+ fatal("poll: %s", strerror(errno));
}
/* copy stdin to iqueue */
- if (FD_ISSET(in, rset)) {
+ if ((pfd[0].revents & (POLLIN|POLLERR)) != 0) {
len = read(in, buf, sizeof buf);
if (len == 0) {
debug("read eof");
@@ -337,18 +399,21 @@ main(int argc, char **argv)
} else if (len < 0) {
error("read: %s", strerror(errno));
cleanup_exit(1);
- } else {
- buffer_append(&iqueue, buf, len);
+ } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
}
}
/* send oqueue to stdout */
- if (FD_ISSET(out, wset)) {
- len = write(out, buffer_ptr(&oqueue), olen);
+ if ((pfd[1].revents & (POLLOUT|POLLHUP)) != 0) {
+ len = write(out, sshbuf_ptr(oqueue),
+ sshbuf_len(oqueue));
if (len < 0) {
error("write: %s", strerror(errno));
cleanup_exit(1);
- } else {
- buffer_consume(&oqueue, len);
+ } else if ((r = sshbuf_consume(oqueue, len)) != 0) {
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
}
}
@@ -357,10 +422,27 @@ main(int argc, char **argv)
* into the output buffer, otherwise stop processing input
* and let the output queue drain.
*/
- if (buffer_check_alloc(&oqueue, MAX_MSG_LENGTH))
+ if ((r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
process();
+ else if (r != SSH_ERR_NO_BUFFER_SPACE)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
}
+
+#else /* WITH_OPENSSL */
+void
+cleanup_exit(int i)
+{
+ _exit(i);
+}
+
+int
+main(int argc, char **argv)
+{
+ fprintf(stderr, "PKCS#11 code is not enabled\n");
+ return 1;
+}
+#endif /* WITH_OPENSSL */
#else /* ENABLE_PKCS11 */
int
main(int argc, char **argv)
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index c3a112fa..ec0e9186 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: ssh-pkcs11.c,v 1.17 2015/02/03 08:07:20 deraadt Exp $ */
+/* $OpenBSD: ssh-pkcs11.c,v 1.49 2020/03/13 04:16:27 djm Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
+ * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -19,19 +20,24 @@
#ifdef ENABLE_PKCS11
-#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
+
+#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
+#include <ctype.h>
#include <string.h>
#include <dlfcn.h>
#include "openbsd-compat/sys-queue.h"
+#include "openbsd-compat/openssl-compat.h"
+#include <openssl/ecdsa.h>
#include <openssl/x509.h>
+#include <openssl/err.h>
#define CRYPTOKI_COMPAT
#include "pkcs11.h"
@@ -66,14 +72,25 @@ TAILQ_HEAD(, pkcs11_provider) pkcs11_providers;
struct pkcs11_key {
struct pkcs11_provider *provider;
CK_ULONG slotidx;
- int (*orig_finish)(RSA *rsa);
- RSA_METHOD rsa_method;
char *keyid;
int keyid_len;
};
int pkcs11_interactive = 0;
+#ifdef HAVE_EC_KEY_METHOD_NEW
+static void
+ossl_error(const char *msg)
+{
+ unsigned long e;
+
+ error("%s: %s", __func__, msg);
+ while ((e = ERR_get_error()) != 0)
+ error("%s: libcrypto error: %.100s", __func__,
+ ERR_error_string(e, NULL));
+}
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+
int
pkcs11_init(int interactive)
{
@@ -83,9 +100,9 @@ pkcs11_init(int interactive)
}
/*
- * finalize a provider shared libarary, it's no longer usable.
+ * finalize a provider shared library, it's no longer usable.
* however, there might still be keys referencing this provider,
- * so the actuall freeing of memory is handled by pkcs11_provider_unref().
+ * so the actual freeing of memory is handled by pkcs11_provider_unref().
* this is called when a provider gets unregistered.
*/
static void
@@ -122,6 +139,7 @@ pkcs11_provider_unref(struct pkcs11_provider *p)
if (--p->refcount <= 0) {
if (p->valid)
error("pkcs11_provider_unref: %p still valid", p);
+ free(p->name);
free(p->slotlist);
free(p->slotinfo);
free(p);
@@ -170,22 +188,27 @@ pkcs11_del_provider(char *provider_id)
return (-1);
}
-/* openssl callback for freeing an RSA key */
-static int
-pkcs11_rsa_finish(RSA *rsa)
+static RSA_METHOD *rsa_method;
+static int rsa_idx = 0;
+#ifdef HAVE_EC_KEY_METHOD_NEW
+static EC_KEY_METHOD *ec_key_method;
+static int ec_key_idx = 0;
+#endif
+
+/* release a wrapped object */
+static void
+pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
+ long argl, void *argp)
{
- struct pkcs11_key *k11;
- int rv = -1;
+ struct pkcs11_key *k11 = ptr;
- if ((k11 = RSA_get_app_data(rsa)) != NULL) {
- if (k11->orig_finish)
- rv = k11->orig_finish(rsa);
- if (k11->provider)
- pkcs11_provider_unref(k11->provider);
- free(k11->keyid);
- free(k11);
- }
- return (rv);
+ debug("%s: parent %p ptr %p idx %d", __func__, parent, ptr, idx);
+ if (k11 == NULL)
+ return;
+ if (k11->provider)
+ pkcs11_provider_unref(k11->provider);
+ free(k11->keyid);
+ free(k11);
}
/* find a single 'obj' for given attributes */
@@ -216,80 +239,217 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr,
return (ret);
}
-/* openssl callback doing the actual signing operation */
static int
-pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
- int padding)
+pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si,
+ CK_USER_TYPE type)
+{
+ char *pin = NULL, prompt[1024];
+ CK_RV rv;
+
+ if (provider == NULL || si == NULL || !provider->valid) {
+ error("no pkcs11 (valid) provider found");
+ return (-1);
+ }
+
+ if (!pkcs11_interactive) {
+ error("need pin entry%s",
+ (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ?
+ " on reader keypad" : "");
+ return (-1);
+ }
+ if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
+ verbose("Deferring PIN entry to reader keypad.");
+ else {
+ snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
+ si->token.label);
+ if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) {
+ debug("%s: no pin specified", __func__);
+ return (-1); /* bail out */
+ }
+ }
+ rv = provider->function_list->C_Login(si->session, type, (u_char *)pin,
+ (pin != NULL) ? strlen(pin) : 0);
+ if (pin != NULL)
+ freezero(pin, strlen(pin));
+
+ switch (rv) {
+ case CKR_OK:
+ case CKR_USER_ALREADY_LOGGED_IN:
+ /* success */
+ break;
+ case CKR_PIN_LEN_RANGE:
+ error("PKCS#11 login failed: PIN length out of range");
+ return -1;
+ case CKR_PIN_INCORRECT:
+ error("PKCS#11 login failed: PIN incorrect");
+ return -1;
+ case CKR_PIN_LOCKED:
+ error("PKCS#11 login failed: PIN locked");
+ return -1;
+ default:
+ error("PKCS#11 login failed: error %lu", rv);
+ return -1;
+ }
+ si->logged_in = 1;
+ return (0);
+}
+
+static int
+pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type)
+{
+ if (k11 == NULL || k11->provider == NULL || !k11->provider->valid) {
+ error("no pkcs11 (valid) provider found");
+ return (-1);
+ }
+
+ return pkcs11_login_slot(k11->provider,
+ &k11->provider->slotinfo[k11->slotidx], type);
+}
+
+
+static int
+pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_TYPE type, int *val)
{
- struct pkcs11_key *k11;
struct pkcs11_slotinfo *si;
CK_FUNCTION_LIST *f;
- CK_OBJECT_HANDLE obj;
- CK_ULONG tlen = 0;
- CK_RV rv;
- CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY;
- CK_BBOOL true_val = CK_TRUE;
- CK_MECHANISM mech = {
- CKM_RSA_PKCS, NULL_PTR, 0
- };
- CK_ATTRIBUTE key_filter[] = {
- {CKA_CLASS, NULL, sizeof(private_key_class) },
- {CKA_ID, NULL, 0},
- {CKA_SIGN, NULL, sizeof(true_val) }
- };
- char *pin, prompt[1024];
- int rval = -1;
+ CK_BBOOL flag = 0;
+ CK_ATTRIBUTE attr;
+ CK_RV rv;
- key_filter[0].pValue = &private_key_class;
- key_filter[2].pValue = &true_val;
+ *val = 0;
- if ((k11 = RSA_get_app_data(rsa)) == NULL) {
- error("RSA_get_app_data failed for rsa %p", rsa);
+ if (!k11->provider || !k11->provider->valid) {
+ error("no pkcs11 (valid) provider found");
return (-1);
}
+
+ f = k11->provider->function_list;
+ si = &k11->provider->slotinfo[k11->slotidx];
+
+ attr.type = type;
+ attr.pValue = &flag;
+ attr.ulValueLen = sizeof(flag);
+
+ rv = f->C_GetAttributeValue(si->session, obj, &attr, 1);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ return (-1);
+ }
+ *val = flag != 0;
+ debug("%s: provider %p slot %lu object %lu: attrib %lu = %d",
+ __func__, k11->provider, k11->slotidx, obj, type, *val);
+ return (0);
+}
+
+static int
+pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
+{
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ CK_OBJECT_HANDLE obj;
+ CK_RV rv;
+ CK_OBJECT_CLASS private_key_class;
+ CK_BBOOL true_val;
+ CK_MECHANISM mech;
+ CK_ATTRIBUTE key_filter[3];
+ int always_auth = 0;
+ int did_login = 0;
+
if (!k11->provider || !k11->provider->valid) {
- error("no pkcs11 (valid) provider for rsa %p", rsa);
+ error("no pkcs11 (valid) provider found");
return (-1);
}
+
f = k11->provider->function_list;
si = &k11->provider->slotinfo[k11->slotidx];
+
if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
- if (!pkcs11_interactive) {
- error("need pin");
+ if (pkcs11_login(k11, CKU_USER) < 0) {
+ error("login failed");
return (-1);
}
- snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
- si->token.label);
- pin = read_passphrase(prompt, RP_ALLOW_EOF);
- if (pin == NULL)
- return (-1); /* bail out */
- rv = f->C_Login(si->session, CKU_USER,
- (u_char *)pin, strlen(pin));
- if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
- free(pin);
- error("C_Login failed: %lu", rv);
- return (-1);
- }
- free(pin);
- si->logged_in = 1;
+ did_login = 1;
}
+
+ memset(&key_filter, 0, sizeof(key_filter));
+ private_key_class = CKO_PRIVATE_KEY;
+ key_filter[0].type = CKA_CLASS;
+ key_filter[0].pValue = &private_key_class;
+ key_filter[0].ulValueLen = sizeof(private_key_class);
+
+ key_filter[1].type = CKA_ID;
key_filter[1].pValue = k11->keyid;
key_filter[1].ulValueLen = k11->keyid_len;
+
+ true_val = CK_TRUE;
+ key_filter[2].type = CKA_SIGN;
+ key_filter[2].pValue = &true_val;
+ key_filter[2].ulValueLen = sizeof(true_val);
+
/* try to find object w/CKA_SIGN first, retry w/o */
if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 &&
pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) {
error("cannot find private key");
- } else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
+ return (-1);
+ }
+
+ memset(&mech, 0, sizeof(mech));
+ mech.mechanism = mech_type;
+ mech.pParameter = NULL_PTR;
+ mech.ulParameterLen = 0;
+
+ if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
error("C_SignInit failed: %lu", rv);
- } else {
- /* XXX handle CKR_BUFFER_TOO_SMALL */
- tlen = RSA_size(rsa);
- rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen);
- if (rv == CKR_OK)
- rval = tlen;
- else
- error("C_Sign failed: %lu", rv);
+ return (-1);
+ }
+
+ pkcs11_check_obj_bool_attrib(k11, obj, CKA_ALWAYS_AUTHENTICATE,
+ &always_auth); /* ignore errors here */
+ if (always_auth && !did_login) {
+ debug("%s: always-auth key", __func__);
+ if (pkcs11_login(k11, CKU_CONTEXT_SPECIFIC) < 0) {
+ error("login failed for always-auth key");
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+/* openssl callback doing the actual signing operation */
+static int
+pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
+ int padding)
+{
+ struct pkcs11_key *k11;
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ CK_ULONG tlen = 0;
+ CK_RV rv;
+ int rval = -1;
+
+ if ((k11 = RSA_get_ex_data(rsa, rsa_idx)) == NULL) {
+ error("RSA_get_ex_data failed for rsa %p", rsa);
+ return (-1);
+ }
+
+ if (pkcs11_get_key(k11, CKM_RSA_PKCS) == -1) {
+ error("pkcs11_get_key failed");
+ return (-1);
}
+
+ f = k11->provider->function_list;
+ si = &k11->provider->slotinfo[k11->slotidx];
+ tlen = RSA_size(rsa);
+
+ /* XXX handle CKR_BUFFER_TOO_SMALL */
+ rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen);
+ if (rv == CKR_OK)
+ rval = tlen;
+ else
+ error("C_Sign failed: %lu", rv);
+
return (rval);
}
@@ -300,13 +460,36 @@ pkcs11_rsa_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
return (-1);
}
+static int
+pkcs11_rsa_start_wrapper(void)
+{
+ if (rsa_method != NULL)
+ return (0);
+ rsa_method = RSA_meth_dup(RSA_get_default_method());
+ if (rsa_method == NULL)
+ return (-1);
+ rsa_idx = RSA_get_ex_new_index(0, "ssh-pkcs11-rsa",
+ NULL, NULL, pkcs11_k11_free);
+ if (rsa_idx == -1)
+ return (-1);
+ if (!RSA_meth_set1_name(rsa_method, "pkcs11") ||
+ !RSA_meth_set_priv_enc(rsa_method, pkcs11_rsa_private_encrypt) ||
+ !RSA_meth_set_priv_dec(rsa_method, pkcs11_rsa_private_decrypt)) {
+ error("%s: setup pkcs11 method failed", __func__);
+ return (-1);
+ }
+ return (0);
+}
+
/* redirect private key operations for rsa key to pkcs11 token */
static int
pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
CK_ATTRIBUTE *keyid_attrib, RSA *rsa)
{
struct pkcs11_key *k11;
- const RSA_METHOD *def = RSA_get_default_method();
+
+ if (pkcs11_rsa_start_wrapper() == -1)
+ return (-1);
k11 = xcalloc(1, sizeof(*k11));
k11->provider = provider;
@@ -314,18 +497,129 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
k11->slotidx = slotidx;
/* identify key object on smartcard */
k11->keyid_len = keyid_attrib->ulValueLen;
+ if (k11->keyid_len > 0) {
+ k11->keyid = xmalloc(k11->keyid_len);
+ memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
+ }
+
+ RSA_set_method(rsa, rsa_method);
+ RSA_set_ex_data(rsa, rsa_idx, k11);
+ return (0);
+}
+
+#ifdef HAVE_EC_KEY_METHOD_NEW
+/* openssl callback doing the actual signing operation */
+static ECDSA_SIG *
+ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
+ const BIGNUM *rp, EC_KEY *ec)
+{
+ struct pkcs11_key *k11;
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ CK_ULONG siglen = 0, bnlen;
+ CK_RV rv;
+ ECDSA_SIG *ret = NULL;
+ u_char *sig;
+ BIGNUM *r = NULL, *s = NULL;
+
+ if ((k11 = EC_KEY_get_ex_data(ec, ec_key_idx)) == NULL) {
+ ossl_error("EC_KEY_get_key_method_data failed for ec");
+ return (NULL);
+ }
+
+ if (pkcs11_get_key(k11, CKM_ECDSA) == -1) {
+ error("pkcs11_get_key failed");
+ return (NULL);
+ }
+
+ f = k11->provider->function_list;
+ si = &k11->provider->slotinfo[k11->slotidx];
+
+ siglen = ECDSA_size(ec);
+ sig = xmalloc(siglen);
+
+ /* XXX handle CKR_BUFFER_TOO_SMALL */
+ rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, &siglen);
+ if (rv != CKR_OK) {
+ error("C_Sign failed: %lu", rv);
+ goto done;
+ }
+ if (siglen < 64 || siglen > 132 || siglen % 2) {
+ ossl_error("d2i_ECDSA_SIG failed");
+ goto done;
+ }
+ bnlen = siglen/2;
+ if ((ret = ECDSA_SIG_new()) == NULL) {
+ error("ECDSA_SIG_new failed");
+ goto done;
+ }
+ if ((r = BN_bin2bn(sig, bnlen, NULL)) == NULL ||
+ (s = BN_bin2bn(sig+bnlen, bnlen, NULL)) == NULL) {
+ ossl_error("d2i_ECDSA_SIG failed");
+ ECDSA_SIG_free(ret);
+ ret = NULL;
+ goto done;
+ }
+ if (!ECDSA_SIG_set0(ret, r, s)) {
+ error("%s: ECDSA_SIG_set0 failed", __func__);
+ ECDSA_SIG_free(ret);
+ ret = NULL;
+ goto done;
+ }
+ r = s = NULL; /* now owned by ret */
+ /* success */
+ done:
+ BN_free(r);
+ BN_free(s);
+ free(sig);
+
+ return (ret);
+}
+
+static int
+pkcs11_ecdsa_start_wrapper(void)
+{
+ int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
+ unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
+
+ if (ec_key_method != NULL)
+ return (0);
+ ec_key_idx = EC_KEY_get_ex_new_index(0, "ssh-pkcs11-ecdsa",
+ NULL, NULL, pkcs11_k11_free);
+ if (ec_key_idx == -1)
+ return (-1);
+ ec_key_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
+ if (ec_key_method == NULL)
+ return (-1);
+ EC_KEY_METHOD_get_sign(ec_key_method, &orig_sign, NULL, NULL);
+ EC_KEY_METHOD_set_sign(ec_key_method, orig_sign, NULL, ecdsa_do_sign);
+ return (0);
+}
+
+static int
+pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
+ CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec)
+{
+ struct pkcs11_key *k11;
+
+ if (pkcs11_ecdsa_start_wrapper() == -1)
+ return (-1);
+
+ k11 = xcalloc(1, sizeof(*k11));
+ k11->provider = provider;
+ provider->refcount++; /* provider referenced by ECDSA key */
+ k11->slotidx = slotidx;
+ /* identify key object on smartcard */
+ k11->keyid_len = keyid_attrib->ulValueLen;
k11->keyid = xmalloc(k11->keyid_len);
memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
- k11->orig_finish = def->finish;
- memcpy(&k11->rsa_method, def, sizeof(k11->rsa_method));
- k11->rsa_method.name = "pkcs11";
- k11->rsa_method.rsa_priv_enc = pkcs11_rsa_private_encrypt;
- k11->rsa_method.rsa_priv_dec = pkcs11_rsa_private_decrypt;
- k11->rsa_method.finish = pkcs11_rsa_finish;
- RSA_set_method(rsa, &k11->rsa_method);
- RSA_set_app_data(rsa, k11);
+
+ EC_KEY_set_method(ec, ec_key_method);
+ EC_KEY_set_ex_data(ec, ec_key_idx, k11);
+
return (0);
}
+#endif /* HAVE_EC_KEY_METHOD_NEW */
/* remove trailing spaces */
static void
@@ -347,79 +641,45 @@ rmspace(u_char *buf, size_t len)
* if pin == NULL we delay login until key use
*/
static int
-pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin)
+pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin,
+ CK_ULONG user)
{
- CK_RV rv;
+ struct pkcs11_slotinfo *si;
CK_FUNCTION_LIST *f;
+ CK_RV rv;
CK_SESSION_HANDLE session;
- int login_required;
+ int login_required, ret;
f = p->function_list;
- login_required = p->slotinfo[slotidx].token.flags & CKF_LOGIN_REQUIRED;
- if (pin && login_required && !strlen(pin)) {
+ si = &p->slotinfo[slotidx];
+
+ login_required = si->token.flags & CKF_LOGIN_REQUIRED;
+
+ /* fail early before opening session */
+ if (login_required && !pkcs11_interactive &&
+ (pin == NULL || strlen(pin) == 0)) {
error("pin required");
- return (-1);
+ return (-SSH_PKCS11_ERR_PIN_REQUIRED);
}
if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION|
- CKF_SERIAL_SESSION, NULL, NULL, &session))
- != CKR_OK) {
+ CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) {
error("C_OpenSession failed: %lu", rv);
return (-1);
}
- if (login_required && pin) {
- rv = f->C_Login(session, CKU_USER,
- (u_char *)pin, strlen(pin));
+ if (login_required && pin != NULL && strlen(pin) != 0) {
+ rv = f->C_Login(session, user, (u_char *)pin, strlen(pin));
if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
error("C_Login failed: %lu", rv);
+ ret = (rv == CKR_PIN_LOCKED) ?
+ -SSH_PKCS11_ERR_PIN_LOCKED :
+ -SSH_PKCS11_ERR_LOGIN_FAIL;
if ((rv = f->C_CloseSession(session)) != CKR_OK)
error("C_CloseSession failed: %lu", rv);
- return (-1);
+ return (ret);
}
- p->slotinfo[slotidx].logged_in = 1;
+ si->logged_in = 1;
}
- p->slotinfo[slotidx].session = session;
- return (0);
-}
-
-/*
- * lookup public keys for token in slot identified by slotidx,
- * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
- * keysp points to an (possibly empty) array with *nkeys keys.
- */
-static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG,
- CK_ATTRIBUTE [], CK_ATTRIBUTE [3], struct sshkey ***, int *)
- __attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE))));
-
-static int
-pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
- struct sshkey ***keysp, int *nkeys)
-{
- CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY;
- CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
- CK_ATTRIBUTE pubkey_filter[] = {
- { CKA_CLASS, NULL, sizeof(pubkey_class) }
- };
- CK_ATTRIBUTE cert_filter[] = {
- { CKA_CLASS, NULL, sizeof(cert_class) }
- };
- CK_ATTRIBUTE pubkey_attribs[] = {
- { CKA_ID, NULL, 0 },
- { CKA_MODULUS, NULL, 0 },
- { CKA_PUBLIC_EXPONENT, NULL, 0 }
- };
- CK_ATTRIBUTE cert_attribs[] = {
- { CKA_ID, NULL, 0 },
- { CKA_SUBJECT, NULL, 0 },
- { CKA_VALUE, NULL, 0 }
- };
- pubkey_filter[0].pValue = &pubkey_class;
- cert_filter[0].pValue = &cert_class;
-
- if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, pubkey_attribs,
- keysp, nkeys) < 0 ||
- pkcs11_fetch_keys_filter(p, slotidx, cert_filter, cert_attribs,
- keysp, nkeys) < 0)
- return (-1);
+ si->session = session;
return (0);
}
@@ -434,121 +694,804 @@ pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key)
return (0);
}
+#ifdef HAVE_EC_KEY_METHOD_NEW
+static struct sshkey *
+pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
+ CK_OBJECT_HANDLE *obj)
+{
+ CK_ATTRIBUTE key_attr[3];
+ CK_SESSION_HANDLE session;
+ CK_FUNCTION_LIST *f = NULL;
+ CK_RV rv;
+ ASN1_OCTET_STRING *octet = NULL;
+ EC_KEY *ec = NULL;
+ EC_GROUP *group = NULL;
+ struct sshkey *key = NULL;
+ const unsigned char *attrp = NULL;
+ int i;
+ int nid;
+
+ memset(&key_attr, 0, sizeof(key_attr));
+ key_attr[0].type = CKA_ID;
+ key_attr[1].type = CKA_EC_POINT;
+ key_attr[2].type = CKA_EC_PARAMS;
+
+ session = p->slotinfo[slotidx].session;
+ f = p->function_list;
+
+ /* figure out size of the attributes */
+ rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ return (NULL);
+ }
+
+ /*
+ * Allow CKA_ID (always first attribute) to be empty, but
+ * ensure that none of the others are zero length.
+ * XXX assumes CKA_ID is always first.
+ */
+ if (key_attr[1].ulValueLen == 0 ||
+ key_attr[2].ulValueLen == 0) {
+ error("invalid attribute length");
+ return (NULL);
+ }
+
+ /* allocate buffers for attributes */
+ for (i = 0; i < 3; i++)
+ if (key_attr[i].ulValueLen > 0)
+ key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
+
+ /* retrieve ID, public point and curve parameters of EC key */
+ rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ goto fail;
+ }
+
+ ec = EC_KEY_new();
+ if (ec == NULL) {
+ error("EC_KEY_new failed");
+ goto fail;
+ }
+
+ attrp = key_attr[2].pValue;
+ group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen);
+ if (group == NULL) {
+ ossl_error("d2i_ECPKParameters failed");
+ goto fail;
+ }
+
+ if (EC_KEY_set_group(ec, group) == 0) {
+ ossl_error("EC_KEY_set_group failed");
+ goto fail;
+ }
+
+ if (key_attr[1].ulValueLen <= 2) {
+ error("CKA_EC_POINT too small");
+ goto fail;
+ }
+
+ attrp = key_attr[1].pValue;
+ octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen);
+ if (octet == NULL) {
+ ossl_error("d2i_ASN1_OCTET_STRING failed");
+ goto fail;
+ }
+ attrp = octet->data;
+ if (o2i_ECPublicKey(&ec, &attrp, octet->length) == NULL) {
+ ossl_error("o2i_ECPublicKey failed");
+ goto fail;
+ }
+
+ nid = sshkey_ecdsa_key_to_nid(ec);
+ if (nid < 0) {
+ error("couldn't get curve nid");
+ goto fail;
+ }
+
+ if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec))
+ goto fail;
+
+ key = sshkey_new(KEY_UNSPEC);
+ if (key == NULL) {
+ error("sshkey_new failed");
+ goto fail;
+ }
+
+ key->ecdsa = ec;
+ key->ecdsa_nid = nid;
+ key->type = KEY_ECDSA;
+ key->flags |= SSHKEY_FLAG_EXT;
+ ec = NULL; /* now owned by key */
+
+fail:
+ for (i = 0; i < 3; i++)
+ free(key_attr[i].pValue);
+ if (ec)
+ EC_KEY_free(ec);
+ if (group)
+ EC_GROUP_free(group);
+ if (octet)
+ ASN1_OCTET_STRING_free(octet);
+
+ return (key);
+}
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+
+static struct sshkey *
+pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
+ CK_OBJECT_HANDLE *obj)
+{
+ CK_ATTRIBUTE key_attr[3];
+ CK_SESSION_HANDLE session;
+ CK_FUNCTION_LIST *f = NULL;
+ CK_RV rv;
+ RSA *rsa = NULL;
+ BIGNUM *rsa_n, *rsa_e;
+ struct sshkey *key = NULL;
+ int i;
+
+ memset(&key_attr, 0, sizeof(key_attr));
+ key_attr[0].type = CKA_ID;
+ key_attr[1].type = CKA_MODULUS;
+ key_attr[2].type = CKA_PUBLIC_EXPONENT;
+
+ session = p->slotinfo[slotidx].session;
+ f = p->function_list;
+
+ /* figure out size of the attributes */
+ rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ return (NULL);
+ }
+
+ /*
+ * Allow CKA_ID (always first attribute) to be empty, but
+ * ensure that none of the others are zero length.
+ * XXX assumes CKA_ID is always first.
+ */
+ if (key_attr[1].ulValueLen == 0 ||
+ key_attr[2].ulValueLen == 0) {
+ error("invalid attribute length");
+ return (NULL);
+ }
+
+ /* allocate buffers for attributes */
+ for (i = 0; i < 3; i++)
+ if (key_attr[i].ulValueLen > 0)
+ key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
+
+ /* retrieve ID, modulus and public exponent of RSA key */
+ rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ goto fail;
+ }
+
+ rsa = RSA_new();
+ if (rsa == NULL) {
+ error("RSA_new failed");
+ goto fail;
+ }
+
+ rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL);
+ rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL);
+ if (rsa_n == NULL || rsa_e == NULL) {
+ error("BN_bin2bn failed");
+ goto fail;
+ }
+ if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL))
+ fatal("%s: set key", __func__);
+ rsa_n = rsa_e = NULL; /* transferred */
+
+ if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa))
+ goto fail;
+
+ key = sshkey_new(KEY_UNSPEC);
+ if (key == NULL) {
+ error("sshkey_new failed");
+ goto fail;
+ }
+
+ key->rsa = rsa;
+ key->type = KEY_RSA;
+ key->flags |= SSHKEY_FLAG_EXT;
+ rsa = NULL; /* now owned by key */
+
+fail:
+ for (i = 0; i < 3; i++)
+ free(key_attr[i].pValue);
+ RSA_free(rsa);
+
+ return (key);
+}
+
static int
-pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
- CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3],
- struct sshkey ***keysp, int *nkeys)
+pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
+ CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp)
{
- struct sshkey *key;
- RSA *rsa;
- X509 *x509;
+ CK_ATTRIBUTE cert_attr[3];
+ CK_SESSION_HANDLE session;
+ CK_FUNCTION_LIST *f = NULL;
+ CK_RV rv;
+ X509 *x509 = NULL;
+ X509_NAME *x509_name = NULL;
EVP_PKEY *evp;
- int i;
+ RSA *rsa = NULL;
+#ifdef OPENSSL_HAS_ECC
+ EC_KEY *ec = NULL;
+#endif
+ struct sshkey *key = NULL;
+ int i;
+#ifdef HAVE_EC_KEY_METHOD_NEW
+ int nid;
+#endif
const u_char *cp;
- CK_RV rv;
- CK_OBJECT_HANDLE obj;
- CK_ULONG nfound;
- CK_SESSION_HANDLE session;
- CK_FUNCTION_LIST *f;
+ char *subject = NULL;
+ *keyp = NULL;
+ *labelp = NULL;
+
+ memset(&cert_attr, 0, sizeof(cert_attr));
+ cert_attr[0].type = CKA_ID;
+ cert_attr[1].type = CKA_SUBJECT;
+ cert_attr[2].type = CKA_VALUE;
+
+ session = p->slotinfo[slotidx].session;
f = p->function_list;
+
+ /* figure out size of the attributes */
+ rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ return -1;
+ }
+
+ /*
+ * Allow CKA_ID (always first attribute) to be empty, but
+ * ensure that none of the others are zero length.
+ * XXX assumes CKA_ID is always first.
+ */
+ if (cert_attr[1].ulValueLen == 0 ||
+ cert_attr[2].ulValueLen == 0) {
+ error("invalid attribute length");
+ return -1;
+ }
+
+ /* allocate buffers for attributes */
+ for (i = 0; i < 3; i++)
+ if (cert_attr[i].ulValueLen > 0)
+ cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen);
+
+ /* retrieve ID, subject and value of certificate */
+ rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ goto out;
+ }
+
+ /* Decode DER-encoded cert subject */
+ cp = cert_attr[2].pValue;
+ if ((x509_name = d2i_X509_NAME(NULL, &cp,
+ cert_attr[1].ulValueLen)) == NULL ||
+ (subject = X509_NAME_oneline(x509_name, NULL, 0)) == NULL)
+ subject = xstrdup("invalid subject");
+ X509_NAME_free(x509_name);
+
+ cp = cert_attr[2].pValue;
+ if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) {
+ error("d2i_x509 failed");
+ goto out;
+ }
+
+ if ((evp = X509_get_pubkey(x509)) == NULL) {
+ error("X509_get_pubkey failed");
+ goto out;
+ }
+
+ if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) {
+ if (EVP_PKEY_get0_RSA(evp) == NULL) {
+ error("invalid x509; no rsa key");
+ goto out;
+ }
+ if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) {
+ error("RSAPublicKey_dup failed");
+ goto out;
+ }
+
+ if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa))
+ goto out;
+
+ key = sshkey_new(KEY_UNSPEC);
+ if (key == NULL) {
+ error("sshkey_new failed");
+ goto out;
+ }
+
+ key->rsa = rsa;
+ key->type = KEY_RSA;
+ key->flags |= SSHKEY_FLAG_EXT;
+ rsa = NULL; /* now owned by key */
+#ifdef HAVE_EC_KEY_METHOD_NEW
+ } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
+ if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {
+ error("invalid x509; no ec key");
+ goto out;
+ }
+ if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) {
+ error("EC_KEY_dup failed");
+ goto out;
+ }
+
+ nid = sshkey_ecdsa_key_to_nid(ec);
+ if (nid < 0) {
+ error("couldn't get curve nid");
+ goto out;
+ }
+
+ if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec))
+ goto out;
+
+ key = sshkey_new(KEY_UNSPEC);
+ if (key == NULL) {
+ error("sshkey_new failed");
+ goto out;
+ }
+
+ key->ecdsa = ec;
+ key->ecdsa_nid = nid;
+ key->type = KEY_ECDSA;
+ key->flags |= SSHKEY_FLAG_EXT;
+ ec = NULL; /* now owned by key */
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+ } else {
+ error("unknown certificate key type");
+ goto out;
+ }
+ out:
+ for (i = 0; i < 3; i++)
+ free(cert_attr[i].pValue);
+ X509_free(x509);
+ RSA_free(rsa);
+#ifdef OPENSSL_HAS_ECC
+ EC_KEY_free(ec);
+#endif
+ if (key == NULL) {
+ free(subject);
+ return -1;
+ }
+ /* success */
+ *keyp = key;
+ *labelp = subject;
+ return 0;
+}
+
+#if 0
+static int
+have_rsa_key(const RSA *rsa)
+{
+ const BIGNUM *rsa_n, *rsa_e;
+
+ RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
+ return rsa_n != NULL && rsa_e != NULL;
+}
+#endif
+
+/*
+ * lookup certificates for token in slot identified by slotidx,
+ * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
+ * keysp points to an (possibly empty) array with *nkeys keys.
+ */
+static int
+pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
+ struct sshkey ***keysp, char ***labelsp, int *nkeys)
+{
+ struct sshkey *key = NULL;
+ CK_OBJECT_CLASS key_class;
+ CK_ATTRIBUTE key_attr[1];
+ CK_SESSION_HANDLE session;
+ CK_FUNCTION_LIST *f = NULL;
+ CK_RV rv;
+ CK_OBJECT_HANDLE obj;
+ CK_ULONG n = 0;
+ int ret = -1;
+ char *label;
+
+ memset(&key_attr, 0, sizeof(key_attr));
+ memset(&obj, 0, sizeof(obj));
+
+ key_class = CKO_CERTIFICATE;
+ key_attr[0].type = CKA_CLASS;
+ key_attr[0].pValue = &key_class;
+ key_attr[0].ulValueLen = sizeof(key_class);
+
session = p->slotinfo[slotidx].session;
- /* setup a filter the looks for public keys */
- if ((rv = f->C_FindObjectsInit(session, filter, 1)) != CKR_OK) {
+ f = p->function_list;
+
+ rv = f->C_FindObjectsInit(session, key_attr, 1);
+ if (rv != CKR_OK) {
error("C_FindObjectsInit failed: %lu", rv);
- return (-1);
+ goto fail;
}
+
while (1) {
- /* XXX 3 attributes in attribs[] */
- for (i = 0; i < 3; i++) {
- attribs[i].pValue = NULL;
- attribs[i].ulValueLen = 0;
+ CK_CERTIFICATE_TYPE ck_cert_type;
+
+ rv = f->C_FindObjects(session, &obj, 1, &n);
+ if (rv != CKR_OK) {
+ error("C_FindObjects failed: %lu", rv);
+ goto fail;
}
- if ((rv = f->C_FindObjects(session, &obj, 1, &nfound)) != CKR_OK
- || nfound == 0)
+ if (n == 0)
break;
- /* found a key, so figure out size of the attributes */
- if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
- != CKR_OK) {
+
+ memset(&ck_cert_type, 0, sizeof(ck_cert_type));
+ memset(&key_attr, 0, sizeof(key_attr));
+ key_attr[0].type = CKA_CERTIFICATE_TYPE;
+ key_attr[0].pValue = &ck_cert_type;
+ key_attr[0].ulValueLen = sizeof(ck_cert_type);
+
+ rv = f->C_GetAttributeValue(session, obj, key_attr, 1);
+ if (rv != CKR_OK) {
error("C_GetAttributeValue failed: %lu", rv);
- continue;
+ goto fail;
}
- /* check that none of the attributes are zero length */
- if (attribs[0].ulValueLen == 0 ||
- attribs[1].ulValueLen == 0 ||
- attribs[2].ulValueLen == 0) {
+
+ key = NULL;
+ label = NULL;
+ switch (ck_cert_type) {
+ case CKC_X_509:
+ if (pkcs11_fetch_x509_pubkey(p, slotidx, &obj,
+ &key, &label) != 0) {
+ error("failed to fetch key");
+ continue;
+ }
+ break;
+ default:
+ error("skipping unsupported certificate type %lu",
+ ck_cert_type);
continue;
}
- /* allocate buffers for attributes */
- for (i = 0; i < 3; i++)
- attribs[i].pValue = xmalloc(attribs[i].ulValueLen);
- /*
- * retrieve ID, modulus and public exponent of RSA key,
- * or ID, subject and value for certificates.
- */
- rsa = NULL;
- if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
- != CKR_OK) {
- error("C_GetAttributeValue failed: %lu", rv);
- } else if (attribs[1].type == CKA_MODULUS ) {
- if ((rsa = RSA_new()) == NULL) {
- error("RSA_new failed");
- } else {
- rsa->n = BN_bin2bn(attribs[1].pValue,
- attribs[1].ulValueLen, NULL);
- rsa->e = BN_bin2bn(attribs[2].pValue,
- attribs[2].ulValueLen, NULL);
- }
+
+ if (pkcs11_key_included(keysp, nkeys, key)) {
+ sshkey_free(key);
} else {
- cp = attribs[2].pValue;
- if ((x509 = X509_new()) == NULL) {
- error("X509_new failed");
- } else if (d2i_X509(&x509, &cp, attribs[2].ulValueLen)
- == NULL) {
- error("d2i_X509 failed");
- } else if ((evp = X509_get_pubkey(x509)) == NULL ||
- evp->type != EVP_PKEY_RSA ||
- evp->pkey.rsa == NULL) {
- debug("X509_get_pubkey failed or no rsa");
- } else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa))
- == NULL) {
- error("RSAPublicKey_dup");
+ /* expand key array and add key */
+ *keysp = xrecallocarray(*keysp, *nkeys,
+ *nkeys + 1, sizeof(struct sshkey *));
+ (*keysp)[*nkeys] = key;
+ if (labelsp != NULL) {
+ *labelsp = xrecallocarray(*labelsp, *nkeys,
+ *nkeys + 1, sizeof(char *));
+ (*labelsp)[*nkeys] = xstrdup((char *)label);
}
- if (x509)
- X509_free(x509);
+ *nkeys = *nkeys + 1;
+ debug("have %d keys", *nkeys);
+ }
+ }
+
+ ret = 0;
+fail:
+ rv = f->C_FindObjectsFinal(session);
+ if (rv != CKR_OK) {
+ error("C_FindObjectsFinal failed: %lu", rv);
+ ret = -1;
+ }
+
+ return (ret);
+}
+
+/*
+ * lookup public keys for token in slot identified by slotidx,
+ * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
+ * keysp points to an (possibly empty) array with *nkeys keys.
+ */
+static int
+pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
+ struct sshkey ***keysp, char ***labelsp, int *nkeys)
+{
+ struct sshkey *key = NULL;
+ CK_OBJECT_CLASS key_class;
+ CK_ATTRIBUTE key_attr[2];
+ CK_SESSION_HANDLE session;
+ CK_FUNCTION_LIST *f = NULL;
+ CK_RV rv;
+ CK_OBJECT_HANDLE obj;
+ CK_ULONG n = 0;
+ int ret = -1;
+
+ memset(&key_attr, 0, sizeof(key_attr));
+ memset(&obj, 0, sizeof(obj));
+
+ key_class = CKO_PUBLIC_KEY;
+ key_attr[0].type = CKA_CLASS;
+ key_attr[0].pValue = &key_class;
+ key_attr[0].ulValueLen = sizeof(key_class);
+
+ session = p->slotinfo[slotidx].session;
+ f = p->function_list;
+
+ rv = f->C_FindObjectsInit(session, key_attr, 1);
+ if (rv != CKR_OK) {
+ error("C_FindObjectsInit failed: %lu", rv);
+ goto fail;
+ }
+
+ while (1) {
+ CK_KEY_TYPE ck_key_type;
+ CK_UTF8CHAR label[256];
+
+ rv = f->C_FindObjects(session, &obj, 1, &n);
+ if (rv != CKR_OK) {
+ error("C_FindObjects failed: %lu", rv);
+ goto fail;
+ }
+ if (n == 0)
+ break;
+
+ memset(&ck_key_type, 0, sizeof(ck_key_type));
+ memset(&key_attr, 0, sizeof(key_attr));
+ key_attr[0].type = CKA_KEY_TYPE;
+ key_attr[0].pValue = &ck_key_type;
+ key_attr[0].ulValueLen = sizeof(ck_key_type);
+ key_attr[1].type = CKA_LABEL;
+ key_attr[1].pValue = &label;
+ key_attr[1].ulValueLen = sizeof(label) - 1;
+
+ rv = f->C_GetAttributeValue(session, obj, key_attr, 2);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ goto fail;
}
- if (rsa && rsa->n && rsa->e &&
- pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
- key = sshkey_new(KEY_UNSPEC);
- key->rsa = rsa;
- key->type = KEY_RSA;
- key->flags |= SSHKEY_FLAG_EXT;
- if (pkcs11_key_included(keysp, nkeys, key)) {
- sshkey_free(key);
- } else {
- /* expand key array and add key */
- *keysp = xrealloc(*keysp, *nkeys + 1,
- sizeof(struct sshkey *));
- (*keysp)[*nkeys] = key;
- *nkeys = *nkeys + 1;
- debug("have %d keys", *nkeys);
+
+ label[key_attr[1].ulValueLen] = '\0';
+
+ switch (ck_key_type) {
+ case CKK_RSA:
+ key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
+ break;
+#ifdef HAVE_EC_KEY_METHOD_NEW
+ case CKK_ECDSA:
+ key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
+ break;
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+ default:
+ /* XXX print key type? */
+ key = NULL;
+ error("skipping unsupported key type");
+ }
+
+ if (key == NULL) {
+ error("failed to fetch key");
+ continue;
+ }
+
+ if (pkcs11_key_included(keysp, nkeys, key)) {
+ sshkey_free(key);
+ } else {
+ /* expand key array and add key */
+ *keysp = xrecallocarray(*keysp, *nkeys,
+ *nkeys + 1, sizeof(struct sshkey *));
+ (*keysp)[*nkeys] = key;
+ if (labelsp != NULL) {
+ *labelsp = xrecallocarray(*labelsp, *nkeys,
+ *nkeys + 1, sizeof(char *));
+ (*labelsp)[*nkeys] = xstrdup((char *)label);
}
- } else if (rsa) {
- RSA_free(rsa);
+ *nkeys = *nkeys + 1;
+ debug("have %d keys", *nkeys);
}
- for (i = 0; i < 3; i++)
- free(attribs[i].pValue);
}
- if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK)
+
+ ret = 0;
+fail:
+ rv = f->C_FindObjectsFinal(session);
+ if (rv != CKR_OK) {
error("C_FindObjectsFinal failed: %lu", rv);
- return (0);
+ ret = -1;
+ }
+
+ return (ret);
}
-/* register a new provider, fails if provider already exists */
-int
-pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
+#ifdef WITH_PKCS11_KEYGEN
+#define FILL_ATTR(attr, idx, typ, val, len) \
+ { (attr[idx]).type=(typ); (attr[idx]).pValue=(val); (attr[idx]).ulValueLen=len; idx++; }
+
+static struct sshkey *
+pkcs11_rsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
+ char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err)
+{
+ struct pkcs11_slotinfo *si;
+ char *plabel = label ? label : "";
+ int npub = 0, npriv = 0;
+ CK_RV rv;
+ CK_FUNCTION_LIST *f;
+ CK_SESSION_HANDLE session;
+ CK_BBOOL true_val = CK_TRUE, false_val = CK_FALSE;
+ CK_OBJECT_HANDLE pubKey, privKey;
+ CK_ATTRIBUTE tpub[16], tpriv[16];
+ CK_MECHANISM mech = {
+ CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0
+ };
+ CK_BYTE pubExponent[] = {
+ 0x01, 0x00, 0x01 /* RSA_F4 in bytes */
+ };
+ pubkey_filter[0].pValue = &pubkey_class;
+ cert_filter[0].pValue = &cert_class;
+
+ *err = 0;
+
+ FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val));
+ FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel));
+ FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val));
+ FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val,
+ sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_MODULUS_BITS, &bits, sizeof(bits));
+ FILL_ATTR(tpub, npub, CKA_PUBLIC_EXPONENT, pubExponent,
+ sizeof(pubExponent));
+ FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid));
+
+ FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel));
+ FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val,
+ sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid));
+
+ f = p->function_list;
+ si = &p->slotinfo[slotidx];
+ session = si->session;
+
+ if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
+ &pubKey, &privKey)) != CKR_OK) {
+ error("%s: key generation failed: error 0x%lx", __func__, rv);
+ *err = rv;
+ return NULL;
+ }
+
+ return pkcs11_fetch_rsa_pubkey(p, slotidx, &pubKey);
+}
+
+static int
+pkcs11_decode_hex(const char *hex, unsigned char **dest, size_t *rlen)
+{
+ size_t i, len;
+ char ptr[3];
+
+ if (dest)
+ *dest = NULL;
+ if (rlen)
+ *rlen = 0;
+
+ if ((len = strlen(hex)) % 2)
+ return -1;
+ len /= 2;
+
+ *dest = xmalloc(len);
+
+ ptr[2] = '\0';
+ for (i = 0; i < len; i++) {
+ ptr[0] = hex[2 * i];
+ ptr[1] = hex[(2 * i) + 1];
+ if (!isxdigit(ptr[0]) || !isxdigit(ptr[1]))
+ return -1;
+ (*dest)[i] = (unsigned char)strtoul(ptr, NULL, 16);
+ }
+
+ if (rlen)
+ *rlen = len;
+
+ return 0;
+}
+
+static struct ec_curve_info {
+ const char *name;
+ const char *oid;
+ const char *oid_encoded;
+ size_t size;
+} ec_curve_infos[] = {
+ {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256},
+ {"secp384r1", "1.3.132.0.34", "06052B81040022", 384},
+ {"secp521r1", "1.3.132.0.35", "06052B81040023", 521},
+ {NULL, NULL, NULL, 0},
+};
+
+static struct sshkey *
+pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
+ char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err)
+{
+ struct pkcs11_slotinfo *si;
+ char *plabel = label ? label : "";
+ int i;
+ size_t ecparams_size;
+ unsigned char *ecparams = NULL;
+ int npub = 0, npriv = 0;
+ CK_RV rv;
+ CK_FUNCTION_LIST *f;
+ CK_SESSION_HANDLE session;
+ CK_BBOOL true_val = CK_TRUE, false_val = CK_FALSE;
+ CK_OBJECT_HANDLE pubKey, privKey;
+ CK_MECHANISM mech = {
+ CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0
+ };
+ CK_ATTRIBUTE tpub[16], tpriv[16];
+
+ *err = 0;
+
+ for (i = 0; ec_curve_infos[i].name; i++) {
+ if (ec_curve_infos[i].size == bits)
+ break;
+ }
+ if (!ec_curve_infos[i].name) {
+ error("%s: invalid key size %lu", __func__, bits);
+ return NULL;
+ }
+ if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams,
+ &ecparams_size) == -1) {
+ error("%s: invalid oid", __func__);
+ return NULL;
+ }
+
+ FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val));
+ FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel));
+ FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val));
+ FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val,
+ sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_EC_PARAMS, ecparams, ecparams_size);
+ FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid));
+
+ FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel));
+ FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val,
+ sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid));
+
+ f = p->function_list;
+ si = &p->slotinfo[slotidx];
+ session = si->session;
+
+ if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
+ &pubKey, &privKey)) != CKR_OK) {
+ error("%s: key generation failed: error 0x%lx", __func__, rv);
+ *err = rv;
+ return NULL;
+ }
+
+ return pkcs11_fetch_ecdsa_pubkey(p, slotidx, &pubKey);
+}
+#endif /* WITH_PKCS11_KEYGEN */
+
+/*
+ * register a new provider, fails if provider already exists. if
+ * keyp is provided, fetch keys.
+ */
+static int
+pkcs11_register_provider(char *provider_id, char *pin,
+ struct sshkey ***keyp, char ***labelsp,
+ struct pkcs11_provider **providerp, CK_ULONG user)
{
int nkeys, need_finalize = 0;
+ int ret = -1;
struct pkcs11_provider *p = NULL;
void *handle = NULL;
CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **);
@@ -557,12 +1500,21 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
CK_TOKEN_INFO *token;
CK_ULONG i;
- *keyp = NULL;
+ if (providerp == NULL)
+ goto fail;
+ *providerp = NULL;
+
+ if (keyp != NULL)
+ *keyp = NULL;
+ if (labelsp != NULL)
+ *labelsp = NULL;
+
if (pkcs11_provider_lookup(provider_id) != NULL) {
- error("provider already registered: %s", provider_id);
+ debug("%s: provider already registered: %s",
+ __func__, provider_id);
goto fail;
}
- /* open shared pkcs11-libarary */
+ /* open shared pkcs11-library */
if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {
error("dlopen %s failed: %s", provider_id, dlerror());
goto fail;
@@ -576,23 +1528,27 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
p->handle = handle;
/* setup the pkcs11 callbacks */
if ((rv = (*getfunctionlist)(&f)) != CKR_OK) {
- error("C_GetFunctionList failed: %lu", rv);
+ error("C_GetFunctionList for provider %s failed: %lu",
+ provider_id, rv);
goto fail;
}
p->function_list = f;
if ((rv = f->C_Initialize(NULL)) != CKR_OK) {
- error("C_Initialize failed: %lu", rv);
+ error("C_Initialize for provider %s failed: %lu",
+ provider_id, rv);
goto fail;
}
need_finalize = 1;
if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) {
- error("C_GetInfo failed: %lu", rv);
+ error("C_GetInfo for provider %s failed: %lu",
+ provider_id, rv);
goto fail;
}
rmspace(p->info.manufacturerID, sizeof(p->info.manufacturerID));
rmspace(p->info.libraryDescription, sizeof(p->info.libraryDescription));
- debug("manufacturerID <%s> cryptokiVersion %d.%d"
+ debug("provider %s: manufacturerID <%s> cryptokiVersion %d.%d"
" libraryDescription <%s> libraryVersion %d.%d",
+ provider_id,
p->info.manufacturerID,
p->info.cryptokiVersion.major,
p->info.cryptokiVersion.minor,
@@ -604,13 +1560,16 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
goto fail;
}
if (p->nslots == 0) {
- error("no slots");
+ debug("%s: provider %s returned no slots", __func__,
+ provider_id);
+ ret = -SSH_PKCS11_ERR_NO_SLOTS;
goto fail;
}
p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID));
if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots))
!= CKR_OK) {
- error("C_GetSlotList failed: %lu", rv);
+ error("C_GetSlotList for provider %s failed: %lu",
+ provider_id, rv);
goto fail;
}
p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo));
@@ -620,53 +1579,295 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
token = &p->slotinfo[i].token;
if ((rv = f->C_GetTokenInfo(p->slotlist[i], token))
!= CKR_OK) {
- error("C_GetTokenInfo failed: %lu", rv);
+ error("C_GetTokenInfo for provider %s slot %lu "
+ "failed: %lu", provider_id, (unsigned long)i, rv);
+ continue;
+ }
+ if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) {
+ debug2("%s: ignoring uninitialised token in "
+ "provider %s slot %lu", __func__,
+ provider_id, (unsigned long)i);
continue;
}
rmspace(token->label, sizeof(token->label));
rmspace(token->manufacturerID, sizeof(token->manufacturerID));
rmspace(token->model, sizeof(token->model));
rmspace(token->serialNumber, sizeof(token->serialNumber));
- debug("label <%s> manufacturerID <%s> model <%s> serial <%s>"
- " flags 0x%lx",
+ debug("provider %s slot %lu: label <%s> manufacturerID <%s> "
+ "model <%s> serial <%s> flags 0x%lx",
+ provider_id, (unsigned long)i,
token->label, token->manufacturerID, token->model,
token->serialNumber, token->flags);
- /* open session, login with pin and retrieve public keys */
- if (pkcs11_open_session(p, i, pin) == 0)
- pkcs11_fetch_keys(p, i, keyp, &nkeys);
- }
- if (nkeys > 0) {
- TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
- p->refcount++; /* add to provider list */
- return (nkeys);
+ /*
+ * open session, login with pin and retrieve public
+ * keys (if keyp is provided)
+ */
+ if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 ||
+ keyp == NULL)
+ continue;
+ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
+ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
+ if (nkeys == 0 && !p->slotinfo[i].logged_in &&
+ pkcs11_interactive) {
+ /*
+ * Some tokens require login before they will
+ * expose keys.
+ */
+ if (pkcs11_login_slot(p, &p->slotinfo[i],
+ CKU_USER) < 0) {
+ error("login failed");
+ continue;
+ }
+ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
+ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
+ }
}
- error("no keys");
- /* don't add the provider, since it does not have any keys */
+
+ /* now owned by caller */
+ *providerp = p;
+
+ TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
+ p->refcount++; /* add to provider list */
+
+ return (nkeys);
fail:
if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK)
- error("C_Finalize failed: %lu", rv);
+ error("C_Finalize for provider %s failed: %lu",
+ provider_id, rv);
if (p) {
+ free(p->name);
free(p->slotlist);
free(p->slotinfo);
free(p);
}
if (handle)
dlclose(handle);
- return (-1);
+ if (ret > 0)
+ ret = -1;
+ return (ret);
+}
+
+/*
+ * register a new provider and get number of keys hold by the token,
+ * fails if provider already exists
+ */
+int
+pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
+ char ***labelsp)
+{
+ struct pkcs11_provider *p = NULL;
+ int nkeys;
+
+ nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp,
+ &p, CKU_USER);
+
+ /* no keys found or some other error, de-register provider */
+ if (nkeys <= 0 && p != NULL) {
+ TAILQ_REMOVE(&pkcs11_providers, p, next);
+ pkcs11_provider_finalize(p);
+ pkcs11_provider_unref(p);
+ }
+ if (nkeys == 0)
+ debug("%s: provider %s returned no keys", __func__,
+ provider_id);
+
+ return (nkeys);
+}
+
+#ifdef WITH_PKCS11_KEYGEN
+struct sshkey *
+pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label,
+ unsigned int type, unsigned int bits, unsigned char keyid, u_int32_t *err)
+{
+ struct pkcs11_provider *p = NULL;
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ CK_SESSION_HANDLE session;
+ struct sshkey *k = NULL;
+ int ret = -1, reset_pin = 0, reset_provider = 0;
+ CK_RV rv;
+
+ *err = 0;
+
+ if ((p = pkcs11_provider_lookup(provider_id)) != NULL)
+ debug("%s: provider \"%s\" available", __func__, provider_id);
+ else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL,
+ &p, CKU_SO)) < 0) {
+ debug("%s: could not register provider %s", __func__,
+ provider_id);
+ goto out;
+ } else
+ reset_provider = 1;
+
+ f = p->function_list;
+ si = &p->slotinfo[slotidx];
+ session = si->session;
+
+ if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
+ CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
+ debug("%s: could not supply SO pin: %lu", __func__, rv);
+ reset_pin = 0;
+ } else
+ reset_pin = 1;
+
+ switch (type) {
+ case KEY_RSA:
+ if ((k = pkcs11_rsa_generate_private_key(p, slotidx, label,
+ bits, keyid, err)) == NULL) {
+ debug("%s: failed to generate RSA key", __func__);
+ goto out;
+ }
+ break;
+ case KEY_ECDSA:
+ if ((k = pkcs11_ecdsa_generate_private_key(p, slotidx, label,
+ bits, keyid, err)) == NULL) {
+ debug("%s: failed to generate ECDSA key", __func__);
+ goto out;
+ }
+ break;
+ default:
+ *err = SSH_PKCS11_ERR_GENERIC;
+ debug("%s: unknown type %d", __func__, type);
+ goto out;
+ }
+
+out:
+ if (reset_pin)
+ f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
+ CK_INVALID_HANDLE);
+
+ if (reset_provider)
+ pkcs11_del_provider(provider_id);
+
+ return (k);
+}
+
+struct sshkey *
+pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
+ unsigned char keyid, u_int32_t *err)
+{
+ struct pkcs11_provider *p = NULL;
+ struct pkcs11_slotinfo *si;
+ struct sshkey *k = NULL;
+ int reset_pin = 0, reset_provider = 0;
+ CK_ULONG nattrs;
+ CK_FUNCTION_LIST *f;
+ CK_SESSION_HANDLE session;
+ CK_ATTRIBUTE attrs[16];
+ CK_OBJECT_CLASS key_class;
+ CK_KEY_TYPE key_type;
+ CK_OBJECT_HANDLE obj = CK_INVALID_HANDLE;
+ CK_RV rv;
+
+ *err = 0;
+
+ if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
+ debug("%s: using provider \"%s\"", __func__, provider_id);
+ } else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p,
+ CKU_SO) < 0) {
+ debug("%s: could not register provider %s", __func__,
+ provider_id);
+ goto out;
+ } else
+ reset_provider = 1;
+
+ f = p->function_list;
+ si = &p->slotinfo[slotidx];
+ session = si->session;
+
+ if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
+ CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
+ debug("%s: could not supply SO pin: %lu", __func__, rv);
+ reset_pin = 0;
+ } else
+ reset_pin = 1;
+
+ /* private key */
+ nattrs = 0;
+ key_class = CKO_PRIVATE_KEY;
+ FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class));
+ FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid));
+
+ if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
+ obj != CK_INVALID_HANDLE) {
+ if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
+ debug("%s: could not destroy private key 0x%hhx",
+ __func__, keyid);
+ *err = rv;
+ goto out;
+ }
+ }
+
+ /* public key */
+ nattrs = 0;
+ key_class = CKO_PUBLIC_KEY;
+ FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class));
+ FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid));
+
+ if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
+ obj != CK_INVALID_HANDLE) {
+
+ /* get key type */
+ nattrs = 0;
+ FILL_ATTR(attrs, nattrs, CKA_KEY_TYPE, &key_type,
+ sizeof(key_type));
+ rv = f->C_GetAttributeValue(session, obj, attrs, nattrs);
+ if (rv != CKR_OK) {
+ debug("%s: could not get key type of public key 0x%hhx",
+ __func__, keyid);
+ *err = rv;
+ key_type = -1;
+ }
+ if (key_type == CKK_RSA)
+ k = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
+ else if (key_type == CKK_ECDSA)
+ k = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
+
+ if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
+ debug("%s: could not destroy public key 0x%hhx",
+ __func__, keyid);
+ *err = rv;
+ goto out;
+ }
+ }
+
+out:
+ if (reset_pin)
+ f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
+ CK_INVALID_HANDLE);
+
+ if (reset_provider)
+ pkcs11_del_provider(provider_id);
+
+ return (k);
}
+#endif /* WITH_PKCS11_KEYGEN */
+#else /* ENABLE_PKCS11 */
-#else
+#include <sys/types.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "log.h"
+#include "sshkey.h"
int
pkcs11_init(int interactive)
{
- return (0);
+ error("%s: dlopen() not supported", __func__);
+ return (-1);
+}
+
+int
+pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
+{
+ error("%s: dlopen() not supported", __func__);
+ return (-1);
}
void
pkcs11_terminate(void)
{
- return;
+ error("%s: dlopen() not supported", __func__);
}
-
#endif /* ENABLE_PKCS11 */
diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h
index 0ced74f2..81f1d7c5 100644
--- a/ssh-pkcs11.h
+++ b/ssh-pkcs11.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-pkcs11.h,v 1.4 2015/01/15 09:40:00 djm Exp $ */
+/* $OpenBSD: ssh-pkcs11.h,v 1.6 2020/01/25 00:03:36 djm Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
*
@@ -14,10 +14,26 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+
+/* Errors for pkcs11_add_provider() */
+#define SSH_PKCS11_ERR_GENERIC 1
+#define SSH_PKCS11_ERR_LOGIN_FAIL 2
+#define SSH_PKCS11_ERR_NO_SLOTS 3
+#define SSH_PKCS11_ERR_PIN_REQUIRED 4
+#define SSH_PKCS11_ERR_PIN_LOCKED 5
+
int pkcs11_init(int);
void pkcs11_terminate(void);
-int pkcs11_add_provider(char *, char *, struct sshkey ***);
+int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***);
int pkcs11_del_provider(char *);
+#ifdef WITH_PKCS11_KEYGEN
+struct sshkey *
+ pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int,
+ unsigned int, unsigned char, u_int32_t *);
+struct sshkey *
+ pkcs11_destroy_keypair(char *, char *, unsigned long, unsigned char,
+ u_int32_t *);
+#endif
#if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11)
#undef ENABLE_PKCS11
diff --git a/ssh-rsa.c b/ssh-rsa.c
index aef798da..d8c3d95f 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-rsa.c,v 1.52 2014/06/24 01:13:21 djm Exp $ */
+/* $OpenBSD: ssh-rsa.c,v 1.67 2018/07/03 11:39:54 djm Exp $ */
/*
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
*
@@ -33,19 +33,144 @@
#define SSHKEY_INTERNAL
#include "sshkey.h"
#include "digest.h"
+#include "log.h"
+
+#include "openbsd-compat/openssl-compat.h"
static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
+static const char *
+rsa_hash_alg_ident(int hash_alg)
+{
+ switch (hash_alg) {
+ case SSH_DIGEST_SHA1:
+ return "ssh-rsa";
+ case SSH_DIGEST_SHA256:
+ return "rsa-sha2-256";
+ case SSH_DIGEST_SHA512:
+ return "rsa-sha2-512";
+ }
+ return NULL;
+}
+
+/*
+ * Returns the hash algorithm ID for a given algorithm identifier as used
+ * inside the signature blob,
+ */
+static int
+rsa_hash_id_from_ident(const char *ident)
+{
+ if (strcmp(ident, "ssh-rsa") == 0)
+ return SSH_DIGEST_SHA1;
+ if (strcmp(ident, "rsa-sha2-256") == 0)
+ return SSH_DIGEST_SHA256;
+ if (strcmp(ident, "rsa-sha2-512") == 0)
+ return SSH_DIGEST_SHA512;
+ return -1;
+}
+
+/*
+ * Return the hash algorithm ID for the specified key name. This includes
+ * all the cases of rsa_hash_id_from_ident() but also the certificate key
+ * types.
+ */
+static int
+rsa_hash_id_from_keyname(const char *alg)
+{
+ int r;
+
+ if ((r = rsa_hash_id_from_ident(alg)) != -1)
+ return r;
+ if (strcmp(alg, "ssh-rsa-cert-v01@openssh.com") == 0)
+ return SSH_DIGEST_SHA1;
+ if (strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
+ return SSH_DIGEST_SHA256;
+ if (strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
+ return SSH_DIGEST_SHA512;
+ return -1;
+}
+
+static int
+rsa_hash_alg_nid(int type)
+{
+ switch (type) {
+ case SSH_DIGEST_SHA1:
+ return NID_sha1;
+ case SSH_DIGEST_SHA256:
+ return NID_sha256;
+ case SSH_DIGEST_SHA512:
+ return NID_sha512;
+ default:
+ return -1;
+ }
+}
+
+int
+ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp)
+{
+ const BIGNUM *rsa_p, *rsa_q, *rsa_d;
+ BIGNUM *aux = NULL, *d_consttime = NULL;
+ BIGNUM *rsa_dmq1 = NULL, *rsa_dmp1 = NULL, *rsa_iqmp = NULL;
+ BN_CTX *ctx = NULL;
+ int r;
+
+ if (key == NULL || key->rsa == NULL ||
+ sshkey_type_plain(key->type) != KEY_RSA)
+ return SSH_ERR_INVALID_ARGUMENT;
+
+ RSA_get0_key(key->rsa, NULL, NULL, &rsa_d);
+ RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
+
+ if ((ctx = BN_CTX_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((aux = BN_new()) == NULL ||
+ (rsa_dmq1 = BN_new()) == NULL ||
+ (rsa_dmp1 = BN_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((d_consttime = BN_dup(rsa_d)) == NULL ||
+ (rsa_iqmp = BN_dup(iqmp)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+#if !defined(OPENSSL_IS_BORINGSSL)
+ BN_set_flags(aux, BN_FLG_CONSTTIME);
+ BN_set_flags(d_consttime, BN_FLG_CONSTTIME);
+#endif
+
+ if ((BN_sub(aux, rsa_q, BN_value_one()) == 0) ||
+ (BN_mod(rsa_dmq1, d_consttime, aux, ctx) == 0) ||
+ (BN_sub(aux, rsa_p, BN_value_one()) == 0) ||
+ (BN_mod(rsa_dmp1, d_consttime, aux, ctx) == 0)) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if (!RSA_set0_crt_params(key->rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp)) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL; /* transferred */
+ /* success */
+ r = 0;
+ out:
+ BN_clear_free(aux);
+ BN_clear_free(d_consttime);
+ BN_clear_free(rsa_dmp1);
+ BN_clear_free(rsa_dmq1);
+ BN_clear_free(rsa_iqmp);
+ BN_CTX_free(ctx);
+ return r;
+}
+
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
int
ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, u_int compat)
+ const u_char *data, size_t datalen, const char *alg_ident)
{
- int hash_alg;
+ const BIGNUM *rsa_n;
u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
- size_t slen;
+ size_t slen = 0;
u_int dlen, len;
- int nid, ret = SSH_ERR_INTERNAL_ERROR;
+ int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL;
if (lenp != NULL)
@@ -53,16 +178,22 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
if (sigp != NULL)
*sigp = NULL;
- if (key == NULL || key->rsa == NULL ||
+ if (alg_ident == NULL || strlen(alg_ident) == 0)
+ hash_alg = SSH_DIGEST_SHA1;
+ else
+ hash_alg = rsa_hash_id_from_keyname(alg_ident);
+ if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
sshkey_type_plain(key->type) != KEY_RSA)
return SSH_ERR_INVALID_ARGUMENT;
+ RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
+ if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
+ return SSH_ERR_KEY_LENGTH;
slen = RSA_size(key->rsa);
if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
return SSH_ERR_INVALID_ARGUMENT;
/* hash the data */
- hash_alg = SSH_DIGEST_SHA1;
- nid = NID_sha1;
+ nid = rsa_hash_alg_nid(hash_alg);
if ((dlen = ssh_digest_bytes(hash_alg)) == 0)
return SSH_ERR_INTERNAL_ERROR;
if ((ret = ssh_digest_memory(hash_alg, data, datalen,
@@ -91,7 +222,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((ret = sshbuf_put_cstring(b, "ssh-rsa")) != 0 ||
+ if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 ||
(ret = sshbuf_put_string(b, sig, slen)) != 0)
goto out;
len = sshbuf_len(b);
@@ -107,41 +238,55 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
ret = 0;
out:
explicit_bzero(digest, sizeof(digest));
- if (sig != NULL) {
- explicit_bzero(sig, slen);
- free(sig);
- }
- if (b != NULL)
- sshbuf_free(b);
- return 0;
+ freezero(sig, slen);
+ sshbuf_free(b);
+ return ret;
}
int
ssh_rsa_verify(const struct sshkey *key,
- const u_char *signature, size_t signaturelen,
- const u_char *data, size_t datalen, u_int compat)
+ const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
+ const char *alg)
{
- char *ktype = NULL;
- int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
- size_t len, diff, modlen, dlen;
+ const BIGNUM *rsa_n;
+ char *sigtype = NULL;
+ int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR;
+ size_t len = 0, diff, modlen, dlen;
struct sshbuf *b = NULL;
u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
if (key == NULL || key->rsa == NULL ||
sshkey_type_plain(key->type) != KEY_RSA ||
- BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
+ sig == NULL || siglen == 0)
return SSH_ERR_INVALID_ARGUMENT;
+ RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
+ if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
+ return SSH_ERR_KEY_LENGTH;
- if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+ if ((b = sshbuf_from(sig, siglen)) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
+ if (sshbuf_get_cstring(b, &sigtype, NULL) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
- if (strcmp("ssh-rsa", ktype) != 0) {
+ if ((hash_alg = rsa_hash_id_from_ident(sigtype)) == -1) {
ret = SSH_ERR_KEY_TYPE_MISMATCH;
goto out;
}
+ /*
+ * Allow ssh-rsa-cert-v01 certs to generate SHA2 signatures for
+ * legacy reasons, but otherwise the signature type should match.
+ */
+ if (alg != NULL && strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) {
+ if ((want_alg = rsa_hash_id_from_keyname(alg)) == -1) {
+ ret = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if (hash_alg != want_alg) {
+ ret = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ }
if (sshbuf_get_string(b, &sigblob, &len) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
@@ -167,7 +312,6 @@ ssh_rsa_verify(const struct sshkey *key,
explicit_bzero(sigblob, diff);
len = modlen;
}
- hash_alg = SSH_DIGEST_SHA1;
if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
ret = SSH_ERR_INTERNAL_ERROR;
goto out;
@@ -179,14 +323,9 @@ ssh_rsa_verify(const struct sshkey *key,
ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len,
key->rsa);
out:
- if (sigblob != NULL) {
- explicit_bzero(sigblob, len);
- free(sigblob);
- }
- if (ktype != NULL)
- free(ktype);
- if (b != NULL)
- sshbuf_free(b);
+ freezero(sigblob, len);
+ free(sigtype);
+ sshbuf_free(b);
explicit_bzero(digest, sizeof(digest));
return ret;
}
@@ -196,6 +335,7 @@ ssh_rsa_verify(const struct sshkey *key,
* http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
* ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
*/
+
/*
* id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
* oiw(14) secsig(3) algorithms(2) 26 }
@@ -209,25 +349,71 @@ static const u_char id_sha1[] = {
0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
};
+/*
+ * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
+ * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
+ * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
+ * id-sha256(1) }
+ */
+static const u_char id_sha256[] = {
+ 0x30, 0x31, /* type Sequence, length 0x31 (49) */
+ 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
+ 0x06, 0x09, /* type OID, length 0x09 */
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */
+ 0x05, 0x00, /* NULL */
+ 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */
+};
+
+/*
+ * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
+ * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
+ * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
+ * id-sha256(3) }
+ */
+static const u_char id_sha512[] = {
+ 0x30, 0x51, /* type Sequence, length 0x51 (81) */
+ 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
+ 0x06, 0x09, /* type OID, length 0x09 */
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */
+ 0x05, 0x00, /* NULL */
+ 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */
+};
+
+static int
+rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp)
+{
+ switch (hash_alg) {
+ case SSH_DIGEST_SHA1:
+ *oidp = id_sha1;
+ *oidlenp = sizeof(id_sha1);
+ break;
+ case SSH_DIGEST_SHA256:
+ *oidp = id_sha256;
+ *oidlenp = sizeof(id_sha256);
+ break;
+ case SSH_DIGEST_SHA512:
+ *oidp = id_sha512;
+ *oidlenp = sizeof(id_sha512);
+ break;
+ default:
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+ return 0;
+}
+
static int
openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
u_char *sigbuf, size_t siglen, RSA *rsa)
{
- size_t ret, rsasize = 0, oidlen = 0, hlen = 0;
- int len, oidmatch, hashmatch;
+ size_t rsasize = 0, oidlen = 0, hlen = 0;
+ int ret, len, oidmatch, hashmatch;
const u_char *oid = NULL;
u_char *decrypted = NULL;
+ if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0)
+ return ret;
ret = SSH_ERR_INTERNAL_ERROR;
- switch (hash_alg) {
- case SSH_DIGEST_SHA1:
- oid = id_sha1;
- oidlen = sizeof(id_sha1);
- hlen = 20;
- break;
- default:
- goto done;
- }
+ hlen = ssh_digest_bytes(hash_alg);
if (hashlen != hlen) {
ret = SSH_ERR_INVALID_ARGUMENT;
goto done;
@@ -259,10 +445,7 @@ openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
}
ret = 0;
done:
- if (decrypted) {
- explicit_bzero(decrypted, rsasize);
- free(decrypted);
- }
+ freezero(decrypted, rsasize);
return ret;
}
#endif /* WITH_OPENSSL */
diff --git a/ssh-sk-client.c b/ssh-sk-client.c
new file mode 100644
index 00000000..8d7e6c30
--- /dev/null
+++ b/ssh-sk-client.c
@@ -0,0 +1,449 @@
+/* $OpenBSD: ssh-sk-client.c,v 1.7 2020/01/23 07:10:22 dtucker Exp $ */
+/*
+ * Copyright (c) 2019 Google LLC
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "log.h"
+#include "ssherr.h"
+#include "sshbuf.h"
+#include "sshkey.h"
+#include "msg.h"
+#include "digest.h"
+#include "pathnames.h"
+#include "ssh-sk.h"
+#include "misc.h"
+
+/* #define DEBUG_SK 1 */
+
+static int
+start_helper(int *fdp, pid_t *pidp, void (**osigchldp)(int))
+{
+ void (*osigchld)(int);
+ int oerrno, pair[2], r = SSH_ERR_INTERNAL_ERROR;
+ pid_t pid;
+ char *helper, *verbosity = NULL;
+
+ *fdp = -1;
+ *pidp = 0;
+ *osigchldp = SIG_DFL;
+
+ helper = getenv("SSH_SK_HELPER");
+ if (helper == NULL || strlen(helper) == 0)
+ helper = _PATH_SSH_SK_HELPER;
+ if (access(helper, X_OK) != 0) {
+ oerrno = errno;
+ error("%s: helper \"%s\" unusable: %s", __func__, helper,
+ strerror(errno));
+ errno = oerrno;
+ return SSH_ERR_SYSTEM_ERROR;
+ }
+#ifdef DEBUG_SK
+ verbosity = "-vvv";
+#endif
+
+ /* Start helper */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
+ error("socketpair: %s", strerror(errno));
+ return SSH_ERR_SYSTEM_ERROR;
+ }
+ osigchld = ssh_signal(SIGCHLD, SIG_DFL);
+ if ((pid = fork()) == -1) {
+ oerrno = errno;
+ error("fork: %s", strerror(errno));
+ close(pair[0]);
+ close(pair[1]);
+ ssh_signal(SIGCHLD, osigchld);
+ errno = oerrno;
+ return SSH_ERR_SYSTEM_ERROR;
+ }
+ if (pid == 0) {
+ if ((dup2(pair[1], STDIN_FILENO) == -1) ||
+ (dup2(pair[1], STDOUT_FILENO) == -1)) {
+ error("%s: dup2: %s", __func__, ssh_err(r));
+ _exit(1);
+ }
+ close(pair[0]);
+ close(pair[1]);
+ closefrom(STDERR_FILENO + 1);
+ debug("%s: starting %s %s", __func__, helper,
+ verbosity == NULL ? "" : verbosity);
+ execlp(helper, helper, verbosity, (char *)NULL);
+ error("%s: execlp: %s", __func__, strerror(errno));
+ _exit(1);
+ }
+ close(pair[1]);
+
+ /* success */
+ debug3("%s: started pid=%ld", __func__, (long)pid);
+ *fdp = pair[0];
+ *pidp = pid;
+ *osigchldp = osigchld;
+ return 0;
+}
+
+static int
+reap_helper(pid_t pid)
+{
+ int status, oerrno;
+
+ debug3("%s: pid=%ld", __func__, (long)pid);
+
+ errno = 0;
+ while (waitpid(pid, &status, 0) == -1) {
+ if (errno == EINTR) {
+ errno = 0;
+ continue;
+ }
+ oerrno = errno;
+ error("%s: waitpid: %s", __func__, strerror(errno));
+ errno = oerrno;
+ return SSH_ERR_SYSTEM_ERROR;
+ }
+ if (!WIFEXITED(status)) {
+ error("%s: helper exited abnormally", __func__);
+ return SSH_ERR_AGENT_FAILURE;
+ } else if (WEXITSTATUS(status) != 0) {
+ error("%s: helper exited with non-zero exit status", __func__);
+ return SSH_ERR_AGENT_FAILURE;
+ }
+ return 0;
+}
+
+static int
+client_converse(struct sshbuf *msg, struct sshbuf **respp, u_int type)
+{
+ int oerrno, fd, r2, ll, r = SSH_ERR_INTERNAL_ERROR;
+ u_int rtype, rerr;
+ pid_t pid;
+ u_char version;
+ void (*osigchld)(int);
+ struct sshbuf *req = NULL, *resp = NULL;
+ *respp = NULL;
+
+ if ((r = start_helper(&fd, &pid, &osigchld)) != 0)
+ return r;
+
+ if ((req = sshbuf_new()) == NULL || (resp = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ /* Request preamble: type, log_on_stderr, log_level */
+ ll = log_level_get();
+ if ((r = sshbuf_put_u32(req, type)) != 0 ||
+ (r = sshbuf_put_u8(req, log_is_on_stderr() != 0)) != 0 ||
+ (r = sshbuf_put_u32(req, ll < 0 ? 0 : ll)) != 0 ||
+ (r = sshbuf_putb(req, msg)) != 0) {
+ error("%s: build: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if ((r = ssh_msg_send(fd, SSH_SK_HELPER_VERSION, req)) != 0) {
+ error("%s: send: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if ((r = ssh_msg_recv(fd, resp)) != 0) {
+ error("%s: receive: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if ((r = sshbuf_get_u8(resp, &version)) != 0) {
+ error("%s: parse version: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if (version != SSH_SK_HELPER_VERSION) {
+ error("%s: unsupported version: got %u, expected %u",
+ __func__, 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));
+ 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));
+ goto out;
+ }
+ debug("%s: helper returned error -%u", __func__, rerr);
+ /* OpenSSH error values are negative; encoded as -err on wire */
+ if (rerr == 0 || rerr >= INT_MAX)
+ r = SSH_ERR_INTERNAL_ERROR;
+ else
+ r = -(int)rerr;
+ goto out;
+ } else if (rtype != type) {
+ error("%s: helper returned incorrect message type %u, "
+ "expecting %u", __func__, rtype, type);
+ r = SSH_ERR_INTERNAL_ERROR;
+ goto out;
+ }
+ /* success */
+ r = 0;
+ out:
+ oerrno = errno;
+ close(fd);
+ if ((r2 = reap_helper(pid)) != 0) {
+ if (r == 0) {
+ r = r2;
+ oerrno = errno;
+ }
+ }
+ if (r == 0) {
+ *respp = resp;
+ resp = NULL;
+ }
+ sshbuf_free(req);
+ sshbuf_free(resp);
+ ssh_signal(SIGCHLD, osigchld);
+ errno = oerrno;
+ return r;
+
+}
+
+int
+sshsk_sign(const char *provider, struct sshkey *key,
+ u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
+ u_int compat, const char *pin)
+{
+ int oerrno, r = SSH_ERR_INTERNAL_ERROR;
+ char *fp = NULL;
+ struct sshbuf *kbuf = NULL, *req = NULL, *resp = NULL;
+
+ *sigp = NULL;
+ *lenp = 0;
+
+#ifndef ENABLE_SK
+ return SSH_ERR_KEY_TYPE_UNKNOWN;
+#endif
+
+ if ((kbuf = sshbuf_new()) == NULL ||
+ (req = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ if ((r = sshkey_private_serialize(key, kbuf)) != 0) {
+ error("%s: serialize private key: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if ((r = sshbuf_put_stringb(req, kbuf)) != 0 ||
+ (r = sshbuf_put_cstring(req, provider)) != 0 ||
+ (r = sshbuf_put_string(req, data, datalen)) != 0 ||
+ (r = sshbuf_put_cstring(req, NULL)) != 0 || /* alg */
+ (r = sshbuf_put_u32(req, compat)) != 0 ||
+ (r = sshbuf_put_cstring(req, pin)) != 0) {
+ error("%s: compose: %s", __func__, ssh_err(r));
+ goto out;
+ }
+
+ if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
+ SSH_FP_DEFAULT)) == NULL) {
+ error("%s: sshkey_fingerprint failed", __func__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = client_converse(req, &resp, SSH_SK_HELPER_SIGN)) != 0)
+ goto out;
+
+ if ((r = sshbuf_get_string(resp, sigp, lenp)) != 0) {
+ error("%s: parse signature: %s", __func__, ssh_err(r));
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (sshbuf_len(resp) != 0) {
+ error("%s: trailing data in response", __func__);
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ /* success */
+ r = 0;
+ out:
+ oerrno = errno;
+ if (r != 0) {
+ freezero(*sigp, *lenp);
+ *sigp = NULL;
+ *lenp = 0;
+ }
+ sshbuf_free(kbuf);
+ sshbuf_free(req);
+ sshbuf_free(resp);
+ errno = oerrno;
+ return r;
+}
+
+int
+sshsk_enroll(int type, const char *provider_path, const char *device,
+ const char *application, const char *userid, uint8_t flags,
+ const char *pin, struct sshbuf *challenge_buf,
+ struct sshkey **keyp, struct sshbuf *attest)
+{
+ int oerrno, r = SSH_ERR_INTERNAL_ERROR;
+ struct sshbuf *kbuf = NULL, *abuf = NULL, *req = NULL, *resp = NULL;
+ struct sshkey *key = NULL;
+
+ *keyp = NULL;
+ if (attest != NULL)
+ sshbuf_reset(attest);
+
+#ifndef ENABLE_SK
+ return SSH_ERR_KEY_TYPE_UNKNOWN;
+#endif
+
+ if (type < 0)
+ return SSH_ERR_INVALID_ARGUMENT;
+
+ if ((abuf = sshbuf_new()) == NULL ||
+ (kbuf = sshbuf_new()) == NULL ||
+ (req = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ if ((r = sshbuf_put_u32(req, (u_int)type)) != 0 ||
+ (r = sshbuf_put_cstring(req, provider_path)) != 0 ||
+ (r = sshbuf_put_cstring(req, device)) != 0 ||
+ (r = sshbuf_put_cstring(req, application)) != 0 ||
+ (r = sshbuf_put_cstring(req, userid)) != 0 ||
+ (r = sshbuf_put_u8(req, flags)) != 0 ||
+ (r = sshbuf_put_cstring(req, pin)) != 0 ||
+ (r = sshbuf_put_stringb(req, challenge_buf)) != 0) {
+ error("%s: compose: %s", __func__, ssh_err(r));
+ goto out;
+ }
+
+ if ((r = client_converse(req, &resp, SSH_SK_HELPER_ENROLL)) != 0)
+ goto out;
+
+ if ((r = sshbuf_get_stringb(resp, kbuf)) != 0 ||
+ (r = sshbuf_get_stringb(resp, abuf)) != 0) {
+ error("%s: parse signature: %s", __func__, ssh_err(r));
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (sshbuf_len(resp) != 0) {
+ error("%s: trailing data in response", __func__);
+ 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));
+ goto out;
+ }
+ if (attest != NULL && (r = sshbuf_putb(attest, abuf)) != 0) {
+ error("%s: buffer error: %s", __func__, ssh_err(r));
+ goto out;
+ }
+
+ /* success */
+ r = 0;
+ *keyp = key;
+ key = NULL;
+ out:
+ oerrno = errno;
+ sshkey_free(key);
+ sshbuf_free(kbuf);
+ sshbuf_free(abuf);
+ sshbuf_free(req);
+ sshbuf_free(resp);
+ errno = oerrno;
+ return r;
+}
+
+int
+sshsk_load_resident(const char *provider_path, const char *device,
+ const char *pin, struct sshkey ***keysp, size_t *nkeysp)
+{
+ int oerrno, r = SSH_ERR_INTERNAL_ERROR;
+ struct sshbuf *kbuf = NULL, *req = NULL, *resp = NULL;
+ struct sshkey *key = NULL, **keys = NULL, **tmp;
+ size_t i, nkeys = 0;
+
+ *keysp = NULL;
+ *nkeysp = 0;
+
+ if ((resp = sshbuf_new()) == NULL ||
+ (kbuf = sshbuf_new()) == NULL ||
+ (req = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ if ((r = sshbuf_put_cstring(req, provider_path)) != 0 ||
+ (r = sshbuf_put_cstring(req, device)) != 0 ||
+ (r = sshbuf_put_cstring(req, pin)) != 0) {
+ error("%s: compose: %s", __func__, ssh_err(r));
+ goto out;
+ }
+
+ if ((r = client_converse(req, &resp, SSH_SK_HELPER_LOAD_RESIDENT)) != 0)
+ goto out;
+
+ while (sshbuf_len(resp) != 0) {
+ /* key, comment */
+ if ((r = sshbuf_get_stringb(resp, kbuf)) != 0 ||
+ (r = sshbuf_get_cstring(resp, NULL, NULL)) != 0) {
+ error("%s: parse signature: %s", __func__, ssh_err(r));
+ 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));
+ goto out;
+ }
+ if ((tmp = recallocarray(keys, nkeys, nkeys + 1,
+ sizeof(*keys))) == NULL) {
+ error("%s: recallocarray keys failed", __func__);
+ goto out;
+ }
+ debug("%s: keys[%zu]: %s %s", __func__,
+ nkeys, sshkey_type(key), key->sk_application);
+ keys = tmp;
+ keys[nkeys++] = key;
+ key = NULL;
+ }
+
+ /* success */
+ r = 0;
+ *keysp = keys;
+ *nkeysp = nkeys;
+ keys = NULL;
+ nkeys = 0;
+ out:
+ oerrno = errno;
+ for (i = 0; i < nkeys; i++)
+ sshkey_free(keys[i]);
+ free(keys);
+ sshkey_free(key);
+ sshbuf_free(kbuf);
+ sshbuf_free(req);
+ sshbuf_free(resp);
+ errno = oerrno;
+ return r;
+}
diff --git a/ssh-sk-helper.8 b/ssh-sk-helper.8
new file mode 100644
index 00000000..3c53da1e
--- /dev/null
+++ b/ssh-sk-helper.8
@@ -0,0 +1,66 @@
+.\" $OpenBSD: ssh-sk-helper.8,v 1.3 2019/12/21 20:22:34 naddy Exp $
+.\"
+.\" Copyright (c) 2010 Markus Friedl. All rights reserved.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: December 21 2019 $
+.Dt SSH-SK-HELPER 8
+.Os
+.Sh NAME
+.Nm ssh-sk-helper
+.Nd OpenSSH helper for FIDO authenticator support
+.Sh SYNOPSIS
+.Nm
+.Op Fl v
+.Sh DESCRIPTION
+.Nm
+is used by
+.Xr ssh-agent 1
+to access keys provided by a FIDO authenticator.
+.Pp
+.Nm
+is not intended to be invoked by the user, but from
+.Xr ssh-agent 1 .
+.Pp
+A single option is supported:
+.Bl -tag -width Ds
+.It Fl v
+Verbose mode.
+Causes
+.Nm
+to print debugging messages about its progress.
+This is helpful in debugging problems.
+Multiple
+.Fl v
+options increase the verbosity.
+The maximum is 3.
+.Pp
+Note that
+.Xr ssh-agent 1
+will automatically pass the
+.Fl v
+flag to
+.Nm
+when it has itself been placed in debug mode.
+.El
+.Sh SEE ALSO
+.Xr ssh 1 ,
+.Xr ssh-add 1 ,
+.Xr ssh-agent 1
+.Sh HISTORY
+.Nm
+first appeared in
+.Ox 6.7 .
+.Sh AUTHORS
+.An Damien Miller Aq Mt djm@openbsd.org
diff --git a/ssh-sk-helper.c b/ssh-sk-helper.c
new file mode 100644
index 00000000..2f93ad71
--- /dev/null
+++ b/ssh-sk-helper.c
@@ -0,0 +1,360 @@
+/* $OpenBSD: ssh-sk-helper.c,v 1.9 2020/01/25 23:13:09 djm Exp $ */
+/*
+ * Copyright (c) 2019 Google LLC
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is a tiny program used to isolate the address space used for
+ * security key middleware signing operations from ssh-agent. It is similar
+ * to ssh-pkcs11-helper.c but considerably simpler as the operations for
+ * security keys are stateless.
+ *
+ * Please crank SSH_SK_HELPER_VERSION in sshkey.h for any incompatible
+ * protocol changes.
+ */
+
+#include "includes.h"
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "xmalloc.h"
+#include "log.h"
+#include "sshkey.h"
+#include "authfd.h"
+#include "misc.h"
+#include "sshbuf.h"
+#include "msg.h"
+#include "uidswap.h"
+#include "sshkey.h"
+#include "ssherr.h"
+#include "ssh-sk.h"
+
+#ifdef ENABLE_SK
+extern char *__progname;
+
+static struct sshbuf *reply_error(int r, char *fmt, ...)
+ __attribute__((__format__ (printf, 2, 3)));
+
+static struct sshbuf *
+reply_error(int r, char *fmt, ...)
+{
+ char *msg;
+ va_list ap;
+ struct sshbuf *resp;
+
+ va_start(ap, fmt);
+ xvasprintf(&msg, fmt, ap);
+ va_end(ap);
+ debug("%s: %s", __progname, msg);
+ free(msg);
+
+ if (r >= 0)
+ fatal("%s: invalid error code %d", __func__, r);
+
+ if ((resp = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __progname);
+ if (sshbuf_put_u32(resp, SSH_SK_HELPER_ERROR) != 0 ||
+ sshbuf_put_u32(resp, (u_int)-r) != 0)
+ fatal("%s: buffer error", __progname);
+ return resp;
+}
+
+/* If the specified string is zero length, then free it and replace with NULL */
+static void
+null_empty(char **s)
+{
+ if (s == NULL || *s == NULL || **s != '\0')
+ return;
+
+ free(*s);
+ *s = NULL;
+}
+
+static struct sshbuf *
+process_sign(struct sshbuf *req)
+{
+ int r = SSH_ERR_INTERNAL_ERROR;
+ struct sshbuf *resp, *kbuf;
+ struct sshkey *key;
+ uint32_t compat;
+ const u_char *message;
+ u_char *sig;
+ size_t msglen, siglen;
+ char *provider, *pin;
+
+ if ((r = sshbuf_froms(req, &kbuf)) != 0 ||
+ (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 ||
+ (r = sshbuf_get_string_direct(req, &message, &msglen)) != 0 ||
+ (r = sshbuf_get_cstring(req, NULL, NULL)) != 0 || /* alg */
+ (r = sshbuf_get_u32(req, &compat)) != 0 ||
+ (r = sshbuf_get_cstring(req, &pin, NULL)) != 0)
+ fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ 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));
+
+ debug("%s: ready to sign with key %s, provider %s: "
+ "msg len %zu, compat 0x%lx", __progname, sshkey_type(key),
+ provider, msglen, (u_long)compat);
+
+ null_empty(&pin);
+
+ if ((r = sshsk_sign(provider, key, &sig, &siglen,
+ message, msglen, compat, pin)) != 0) {
+ resp = reply_error(r, "Signing failed: %s", ssh_err(r));
+ goto out;
+ }
+
+ if ((resp = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __progname);
+
+ if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_SIGN)) != 0 ||
+ (r = sshbuf_put_string(resp, sig, siglen)) != 0)
+ fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ out:
+ sshbuf_free(kbuf);
+ free(provider);
+ if (pin != NULL)
+ freezero(pin, strlen(pin));
+ return resp;
+}
+
+static struct sshbuf *
+process_enroll(struct sshbuf *req)
+{
+ int r;
+ u_int type;
+ char *provider, *application, *pin, *device, *userid;
+ uint8_t flags;
+ struct sshbuf *challenge, *attest, *kbuf, *resp;
+ struct sshkey *key;
+
+ if ((attest = sshbuf_new()) == NULL ||
+ (kbuf = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __progname);
+
+ if ((r = sshbuf_get_u32(req, &type)) != 0 ||
+ (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(req, &device, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(req, &application, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(req, &userid, NULL)) != 0 ||
+ (r = sshbuf_get_u8(req, &flags)) != 0 ||
+ (r = sshbuf_get_cstring(req, &pin, NULL)) != 0 ||
+ (r = sshbuf_froms(req, &challenge)) != 0)
+ fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ if (sshbuf_len(req) != 0)
+ fatal("%s: trailing data in request", __progname);
+
+ if (type > INT_MAX)
+ fatal("%s: bad type %u", __progname, type);
+ if (sshbuf_len(challenge) == 0) {
+ sshbuf_free(challenge);
+ challenge = NULL;
+ }
+ null_empty(&device);
+ null_empty(&userid);
+ null_empty(&pin);
+
+ if ((r = sshsk_enroll((int)type, provider, device, application, userid,
+ flags, pin, challenge, &key, attest)) != 0) {
+ resp = reply_error(r, "Enrollment failed: %s", ssh_err(r));
+ goto out;
+ }
+
+ if ((resp = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __progname);
+ if ((r = sshkey_private_serialize(key, kbuf)) != 0)
+ fatal("%s: serialize private key: %s", __progname, ssh_err(r));
+ 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));
+
+ out:
+ sshkey_free(key);
+ sshbuf_free(kbuf);
+ sshbuf_free(attest);
+ sshbuf_free(challenge);
+ free(provider);
+ free(application);
+ if (pin != NULL)
+ freezero(pin, strlen(pin));
+
+ return resp;
+}
+
+static struct sshbuf *
+process_load_resident(struct sshbuf *req)
+{
+ int r;
+ char *provider, *pin, *device;
+ struct sshbuf *kbuf, *resp;
+ struct sshkey **keys = NULL;
+ size_t nkeys = 0, i;
+
+ if ((kbuf = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __progname);
+
+ if ((r = sshbuf_get_cstring(req, &provider, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(req, &device, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(req, &pin, NULL)) != 0)
+ fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ if (sshbuf_len(req) != 0)
+ fatal("%s: trailing data in request", __progname);
+
+ null_empty(&device);
+ null_empty(&pin);
+
+ if ((r = sshsk_load_resident(provider, device, pin,
+ &keys, &nkeys)) != 0) {
+ resp = reply_error(r, " sshsk_load_resident failed: %s",
+ ssh_err(r));
+ goto out;
+ }
+
+ if ((resp = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __progname);
+
+ if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_LOAD_RESIDENT)) != 0)
+ fatal("%s: buffer error: %s", __progname, ssh_err(r));
+
+ for (i = 0; i < nkeys; i++) {
+ debug("%s: key %zu %s %s", __func__, 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));
+ if ((r = sshbuf_put_stringb(resp, kbuf)) != 0 ||
+ (r = sshbuf_put_cstring(resp, "")) != 0) /* comment */
+ fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ }
+
+ out:
+ for (i = 0; i < nkeys; i++)
+ sshkey_free(keys[i]);
+ free(keys);
+ sshbuf_free(kbuf);
+ free(provider);
+ if (pin != NULL)
+ freezero(pin, strlen(pin));
+ return resp;
+}
+
+int
+main(int argc, char **argv)
+{
+ SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
+ LogLevel log_level = SYSLOG_LEVEL_ERROR;
+ struct sshbuf *req, *resp;
+ int in, out, ch, r, vflag = 0;
+ u_int rtype, ll = 0;
+ uint8_t version, log_stderr = 0;
+
+ sanitise_stdfd();
+ log_init(__progname, log_level, log_facility, log_stderr);
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ vflag = 1;
+ if (log_level == SYSLOG_LEVEL_ERROR)
+ log_level = SYSLOG_LEVEL_DEBUG1;
+ else if (log_level < SYSLOG_LEVEL_DEBUG3)
+ log_level++;
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", __progname);
+ exit(1);
+ }
+ }
+ log_init(__progname, log_level, log_facility, vflag);
+
+ /*
+ * Rearrange our file descriptors a little; we don't trust the
+ * providers not to fiddle with stdin/out.
+ */
+ closefrom(STDERR_FILENO + 1);
+ if ((in = dup(STDIN_FILENO)) == -1 || (out = dup(STDOUT_FILENO)) == -1)
+ fatal("%s: dup: %s", __progname, strerror(errno));
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ sanitise_stdfd(); /* resets to /dev/null */
+
+ if ((req = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __progname);
+ if (ssh_msg_recv(in, req) < 0)
+ fatal("ssh_msg_recv failed");
+ close(in);
+ debug("%s: received message len %zu", __progname, sshbuf_len(req));
+
+ if ((r = sshbuf_get_u8(req, &version)) != 0)
+ fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ if (version != SSH_SK_HELPER_VERSION) {
+ fatal("unsupported version: received %d, expected %d",
+ version, SSH_SK_HELPER_VERSION);
+ }
+
+ if ((r = sshbuf_get_u32(req, &rtype)) != 0 ||
+ (r = sshbuf_get_u8(req, &log_stderr)) != 0 ||
+ (r = sshbuf_get_u32(req, &ll)) != 0)
+ fatal("%s: buffer error: %s", __progname, ssh_err(r));
+
+ if (!vflag && log_level_name((LogLevel)ll) != NULL)
+ log_init(__progname, (LogLevel)ll, log_facility, log_stderr);
+
+ switch (rtype) {
+ case SSH_SK_HELPER_SIGN:
+ resp = process_sign(req);
+ break;
+ case SSH_SK_HELPER_ENROLL:
+ resp = process_enroll(req);
+ break;
+ case SSH_SK_HELPER_LOAD_RESIDENT:
+ resp = process_load_resident(req);
+ break;
+ default:
+ fatal("%s: unsupported request type %u", __progname, rtype);
+ }
+ sshbuf_free(req);
+ debug("%s: reply len %zu", __progname, sshbuf_len(resp));
+
+ if (ssh_msg_send(out, SSH_SK_HELPER_VERSION, resp) == -1)
+ fatal("ssh_msg_send failed");
+ sshbuf_free(resp);
+ close(out);
+
+ return (0);
+}
+#else /* ENABLE_SK */
+#include <stdio.h>
+
+int
+main(int argc, char **argv)
+{
+ fprintf(stderr, "ssh-sk-helper: disabled at compile time\n");
+ return -1;
+}
+#endif /* ENABLE_SK */
diff --git a/ssh-sk.c b/ssh-sk.c
new file mode 100644
index 00000000..1afb205f
--- /dev/null
+++ b/ssh-sk.c
@@ -0,0 +1,807 @@
+/* $OpenBSD: ssh-sk.c,v 1.30 2020/04/28 04:02:29 djm Exp $ */
+/*
+ * Copyright (c) 2019 Google LLC
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* #define DEBUG_SK 1 */
+
+#include "includes.h"
+
+#ifdef ENABLE_SK
+
+#include <dlfcn.h>
+#include <stddef.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+
+#ifdef WITH_OPENSSL
+#include <openssl/objects.h>
+#include <openssl/ec.h>
+#endif /* WITH_OPENSSL */
+
+#include "log.h"
+#include "misc.h"
+#include "sshbuf.h"
+#include "sshkey.h"
+#include "ssherr.h"
+#include "digest.h"
+
+#include "ssh-sk.h"
+#include "sk-api.h"
+#include "crypto_api.h"
+
+struct sshsk_provider {
+ char *path;
+ void *dlhandle;
+
+ /* Return the version of the middleware API */
+ uint32_t (*sk_api_version)(void);
+
+ /* Enroll a U2F key (private key generation) */
+ int (*sk_enroll)(int alg, const uint8_t *challenge,
+ size_t challenge_len, const char *application, uint8_t flags,
+ const char *pin, struct sk_option **opts,
+ struct sk_enroll_response **enroll_response);
+
+ /* Sign a challenge */
+ int (*sk_sign)(int alg, const uint8_t *message, size_t message_len,
+ const char *application,
+ const uint8_t *key_handle, size_t key_handle_len,
+ uint8_t flags, const char *pin, struct sk_option **opts,
+ struct sk_sign_response **sign_response);
+
+ /* Enumerate resident keys */
+ int (*sk_load_resident_keys)(const char *pin, struct sk_option **opts,
+ struct sk_resident_key ***rks, size_t *nrks);
+};
+
+/* Built-in version */
+int ssh_sk_enroll(int alg, const uint8_t *challenge,
+ size_t challenge_len, const char *application, uint8_t flags,
+ const char *pin, struct sk_option **opts,
+ struct sk_enroll_response **enroll_response);
+int ssh_sk_sign(int alg, const uint8_t *message, size_t message_len,
+ const char *application,
+ const uint8_t *key_handle, size_t key_handle_len,
+ uint8_t flags, const char *pin, struct sk_option **opts,
+ struct sk_sign_response **sign_response);
+int ssh_sk_load_resident_keys(const char *pin, struct sk_option **opts,
+ struct sk_resident_key ***rks, size_t *nrks);
+
+static void
+sshsk_free(struct sshsk_provider *p)
+{
+ if (p == NULL)
+ return;
+ free(p->path);
+ if (p->dlhandle != NULL)
+ dlclose(p->dlhandle);
+ free(p);
+}
+
+static struct sshsk_provider *
+sshsk_open(const char *path)
+{
+ struct sshsk_provider *ret = NULL;
+ uint32_t version;
+
+ if (path == NULL || *path == '\0') {
+ error("No FIDO SecurityKeyProvider specified");
+ return NULL;
+ }
+ if ((ret = calloc(1, sizeof(*ret))) == NULL) {
+ error("%s: calloc failed", __func__);
+ return NULL;
+ }
+ if ((ret->path = strdup(path)) == NULL) {
+ error("%s: strdup failed", __func__);
+ goto fail;
+ }
+ /* Skip the rest if we're using the linked in middleware */
+ if (strcasecmp(ret->path, "internal") == 0) {
+#ifdef ENABLE_SK_INTERNAL
+ ret->sk_enroll = ssh_sk_enroll;
+ ret->sk_sign = ssh_sk_sign;
+ ret->sk_load_resident_keys = ssh_sk_load_resident_keys;
+#else
+ error("internal security key support not enabled");
+#endif
+ return ret;
+ }
+ if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL) {
+ error("Provider \"%s\" dlopen failed: %s", path, dlerror());
+ goto fail;
+ }
+ if ((ret->sk_api_version = dlsym(ret->dlhandle,
+ "sk_api_version")) == NULL) {
+ error("Provider \"%s\" dlsym(sk_api_version) failed: %s",
+ path, dlerror());
+ goto fail;
+ }
+ version = ret->sk_api_version();
+ debug("%s: provider %s implements version 0x%08lx", __func__,
+ ret->path, (u_long)version);
+ if ((version & SSH_SK_VERSION_MAJOR_MASK) != SSH_SK_VERSION_MAJOR) {
+ error("Provider \"%s\" implements unsupported "
+ "version 0x%08lx (supported: 0x%08lx)",
+ path, (u_long)version, (u_long)SSH_SK_VERSION_MAJOR);
+ goto fail;
+ }
+ if ((ret->sk_enroll = dlsym(ret->dlhandle, "sk_enroll")) == NULL) {
+ error("Provider %s dlsym(sk_enroll) failed: %s",
+ path, dlerror());
+ goto fail;
+ }
+ if ((ret->sk_sign = dlsym(ret->dlhandle, "sk_sign")) == NULL) {
+ error("Provider \"%s\" dlsym(sk_sign) failed: %s",
+ path, dlerror());
+ goto fail;
+ }
+ if ((ret->sk_load_resident_keys = dlsym(ret->dlhandle,
+ "sk_load_resident_keys")) == NULL) {
+ error("Provider \"%s\" dlsym(sk_load_resident_keys) "
+ "failed: %s", path, dlerror());
+ goto fail;
+ }
+ /* success */
+ return ret;
+fail:
+ sshsk_free(ret);
+ return NULL;
+}
+
+static void
+sshsk_free_enroll_response(struct sk_enroll_response *r)
+{
+ if (r == NULL)
+ return;
+ freezero(r->key_handle, r->key_handle_len);
+ freezero(r->public_key, r->public_key_len);
+ freezero(r->signature, r->signature_len);
+ freezero(r->attestation_cert, r->attestation_cert_len);
+ freezero(r, sizeof(*r));
+}
+
+static void
+sshsk_free_sign_response(struct sk_sign_response *r)
+{
+ if (r == NULL)
+ return;
+ freezero(r->sig_r, r->sig_r_len);
+ freezero(r->sig_s, r->sig_s_len);
+ freezero(r, sizeof(*r));
+}
+
+#ifdef WITH_OPENSSL
+/* Assemble key from response */
+static int
+sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
+{
+ struct sshkey *key = NULL;
+ struct sshbuf *b = NULL;
+ EC_POINT *q = NULL;
+ int r;
+
+ *keyp = NULL;
+ if ((key = sshkey_new(KEY_ECDSA_SK)) == NULL) {
+ error("%s: sshkey_new failed", __func__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ key->ecdsa_nid = NID_X9_62_prime256v1;
+ if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL ||
+ (q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL ||
+ (b = sshbuf_new()) == NULL) {
+ error("%s: allocation failed", __func__);
+ 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));
+ 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));
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), q) != 0) {
+ error("Authenticator returned invalid ECDSA key");
+ r = SSH_ERR_KEY_INVALID_EC_VALUE;
+ goto out;
+ }
+ if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
+ /* XXX assume it is a allocation error */
+ error("%s: allocation failed", __func__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ /* success */
+ *keyp = key;
+ key = NULL; /* transferred */
+ r = 0;
+ out:
+ EC_POINT_free(q);
+ sshkey_free(key);
+ sshbuf_free(b);
+ return r;
+}
+#endif /* WITH_OPENSSL */
+
+static int
+sshsk_ed25519_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
+{
+ struct sshkey *key = NULL;
+ int r;
+
+ *keyp = NULL;
+ if (resp->public_key_len != ED25519_PK_SZ) {
+ error("%s: invalid size: %zu", __func__, 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__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((key->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
+ error("%s: malloc failed", __func__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ memcpy(key->ed25519_pk, resp->public_key, ED25519_PK_SZ);
+ /* success */
+ *keyp = key;
+ key = NULL; /* transferred */
+ r = 0;
+ out:
+ sshkey_free(key);
+ return r;
+}
+
+static int
+sshsk_key_from_response(int alg, const char *application, uint8_t flags,
+ struct sk_enroll_response *resp, struct sshkey **keyp)
+{
+ struct sshkey *key = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ *keyp = NULL;
+
+ /* Check response validity */
+ if (resp->public_key == NULL || resp->key_handle == NULL) {
+ error("%s: sk_enroll response invalid", __func__);
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ switch (alg) {
+#ifdef WITH_OPENSSL
+ case SSH_SK_ECDSA:
+ if ((r = sshsk_ecdsa_assemble(resp, &key)) != 0)
+ goto out;
+ break;
+#endif /* WITH_OPENSSL */
+ case SSH_SK_ED25519:
+ if ((r = sshsk_ed25519_assemble(resp, &key)) != 0)
+ goto out;
+ break;
+ default:
+ error("%s: unsupported algorithm %d", __func__, 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__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((key->sk_application = strdup(application)) == NULL) {
+ error("%s: strdup application failed", __func__);
+ 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));
+ goto out;
+ }
+ /* success */
+ r = 0;
+ *keyp = key;
+ key = NULL;
+ out:
+ sshkey_free(key);
+ return r;
+}
+
+static int
+skerr_to_ssherr(int skerr)
+{
+ switch (skerr) {
+ case SSH_SK_ERR_UNSUPPORTED:
+ return SSH_ERR_FEATURE_UNSUPPORTED;
+ case SSH_SK_ERR_PIN_REQUIRED:
+ return SSH_ERR_KEY_WRONG_PASSPHRASE;
+ case SSH_SK_ERR_DEVICE_NOT_FOUND:
+ return SSH_ERR_DEVICE_NOT_FOUND;
+ case SSH_SK_ERR_GENERAL:
+ default:
+ return SSH_ERR_INVALID_FORMAT;
+ }
+}
+
+static void
+sshsk_free_options(struct sk_option **opts)
+{
+ size_t i;
+
+ if (opts == NULL)
+ return;
+ for (i = 0; opts[i] != NULL; i++) {
+ free(opts[i]->name);
+ free(opts[i]->value);
+ free(opts[i]);
+ }
+ free(opts);
+}
+
+static int
+sshsk_add_option(struct sk_option ***optsp, size_t *noptsp,
+ const char *name, const char *value, uint8_t required)
+{
+ struct sk_option **opts = *optsp;
+ size_t nopts = *noptsp;
+
+ if ((opts = recallocarray(opts, nopts, nopts + 2, /* extra for NULL */
+ sizeof(*opts))) == NULL) {
+ error("%s: array alloc failed", __func__);
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ *optsp = opts;
+ *noptsp = nopts + 1;
+ if ((opts[nopts] = calloc(1, sizeof(**opts))) == NULL) {
+ error("%s: alloc failed", __func__);
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ if ((opts[nopts]->name = strdup(name)) == NULL ||
+ (opts[nopts]->value = strdup(value)) == NULL) {
+ error("%s: alloc failed", __func__);
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ opts[nopts]->required = required;
+ return 0;
+}
+
+static int
+make_options(const char *device, const char *user_id,
+ struct sk_option ***optsp)
+{
+ struct sk_option **opts = NULL;
+ size_t nopts = 0;
+ int r, ret = SSH_ERR_INTERNAL_ERROR;
+
+ if (device != NULL &&
+ (r = sshsk_add_option(&opts, &nopts, "device", device, 0)) != 0) {
+ ret = r;
+ goto out;
+ }
+ if (user_id != NULL &&
+ (r = sshsk_add_option(&opts, &nopts, "user", user_id, 0)) != 0) {
+ ret = r;
+ goto out;
+ }
+ /* success */
+ *optsp = opts;
+ opts = NULL;
+ nopts = 0;
+ ret = 0;
+ out:
+ sshsk_free_options(opts);
+ return ret;
+}
+
+int
+sshsk_enroll(int type, const char *provider_path, const char *device,
+ const char *application, const char *userid, uint8_t flags,
+ const char *pin, struct sshbuf *challenge_buf,
+ struct sshkey **keyp, struct sshbuf *attest)
+{
+ struct sshsk_provider *skp = NULL;
+ struct sshkey *key = NULL;
+ u_char randchall[32];
+ const u_char *challenge;
+ size_t challenge_len;
+ struct sk_enroll_response *resp = NULL;
+ struct sk_option **opts = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ int alg;
+
+ debug("%s: provider \"%s\", device \"%s\", application \"%s\", "
+ "userid \"%s\", flags 0x%02x, challenge len %zu%s", __func__,
+ provider_path, device, application, userid, flags,
+ challenge_buf == NULL ? 0 : sshbuf_len(challenge_buf),
+ (pin != NULL && *pin != '\0') ? " with-pin" : "");
+
+ *keyp = NULL;
+ if (attest)
+ sshbuf_reset(attest);
+
+ if ((r = make_options(device, userid, &opts)) != 0)
+ goto out;
+
+ switch (type) {
+#ifdef WITH_OPENSSL
+ case KEY_ECDSA_SK:
+ alg = SSH_SK_ECDSA;
+ break;
+#endif /* WITH_OPENSSL */
+ case KEY_ED25519_SK:
+ alg = SSH_SK_ED25519;
+ break;
+ default:
+ error("%s: unsupported key type", __func__);
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if (provider_path == NULL) {
+ error("%s: missing provider", __func__);
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if (application == NULL || *application == '\0') {
+ error("%s: missing application", __func__);
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if (challenge_buf == NULL) {
+ debug("%s: using random challenge", __func__);
+ arc4random_buf(randchall, sizeof(randchall));
+ challenge = randchall;
+ challenge_len = sizeof(randchall);
+ } else if (sshbuf_len(challenge_buf) == 0) {
+ error("Missing enrollment challenge");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ } else {
+ challenge = sshbuf_ptr(challenge_buf);
+ challenge_len = sshbuf_len(challenge_buf);
+ debug3("%s: using explicit challenge len=%zd",
+ __func__, challenge_len);
+ }
+ if ((skp = sshsk_open(provider_path)) == NULL) {
+ r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */
+ goto out;
+ }
+ /* XXX validate flags? */
+ /* enroll key */
+ if ((r = skp->sk_enroll(alg, challenge, challenge_len, application,
+ flags, pin, opts, &resp)) != 0) {
+ debug("%s: provider \"%s\" returned failure %d", __func__,
+ provider_path, r);
+ r = skerr_to_ssherr(r);
+ goto out;
+ }
+
+ if ((r = sshsk_key_from_response(alg, application, flags,
+ resp, &key)) != 0)
+ goto out;
+
+ /* Optionally fill in the attestation information */
+ if (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;
+ }
+ }
+ /* success */
+ *keyp = key;
+ key = NULL; /* transferred */
+ r = 0;
+ out:
+ sshsk_free_options(opts);
+ sshsk_free(skp);
+ sshkey_free(key);
+ sshsk_free_enroll_response(resp);
+ explicit_bzero(randchall, sizeof(randchall));
+ return r;
+}
+
+#ifdef WITH_OPENSSL
+static int
+sshsk_ecdsa_sig(struct sk_sign_response *resp, struct sshbuf *sig)
+{
+ struct sshbuf *inner_sig = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ /* Check response validity */
+ if (resp->sig_r == NULL || resp->sig_s == NULL) {
+ error("%s: sk_sign response invalid", __func__);
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if ((inner_sig = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ /* Prepare and append inner signature object */
+ if ((r = sshbuf_put_bignum2_bytes(inner_sig,
+ resp->sig_r, resp->sig_r_len)) != 0 ||
+ (r = sshbuf_put_bignum2_bytes(inner_sig,
+ resp->sig_s, resp->sig_s_len)) != 0) {
+ debug("%s: buffer error: %s", __func__, ssh_err(r));
+ 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));
+ goto out;
+ }
+#ifdef DEBUG_SK
+ fprintf(stderr, "%s: sig_r:\n", __func__);
+ sshbuf_dump_data(resp->sig_r, resp->sig_r_len, stderr);
+ fprintf(stderr, "%s: sig_s:\n", __func__);
+ sshbuf_dump_data(resp->sig_s, resp->sig_s_len, stderr);
+ fprintf(stderr, "%s: inner:\n", __func__);
+ sshbuf_dump(inner_sig, stderr);
+#endif
+ r = 0;
+ out:
+ sshbuf_free(inner_sig);
+ return r;
+}
+#endif /* WITH_OPENSSL */
+
+static int
+sshsk_ed25519_sig(struct sk_sign_response *resp, struct sshbuf *sig)
+{
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ /* Check response validity */
+ if (resp->sig_r == NULL) {
+ error("%s: sk_sign response invalid", __func__);
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if ((r = sshbuf_put_string(sig,
+ resp->sig_r, resp->sig_r_len)) != 0 ||
+ (r = sshbuf_put_u8(sig, resp->flags)) != 0 ||
+ (r = sshbuf_put_u32(sig, resp->counter)) != 0) {
+ debug("%s: buffer error: %s", __func__, ssh_err(r));
+ goto out;
+ }
+#ifdef DEBUG_SK
+ fprintf(stderr, "%s: sig_r:\n", __func__);
+ sshbuf_dump_data(resp->sig_r, resp->sig_r_len, stderr);
+#endif
+ r = 0;
+ out:
+ return r;
+}
+
+int
+sshsk_sign(const char *provider_path, struct sshkey *key,
+ u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
+ u_int compat, const char *pin)
+{
+ struct sshsk_provider *skp = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ int type, alg;
+ struct sk_sign_response *resp = NULL;
+ struct sshbuf *inner_sig = NULL, *sig = NULL;
+ struct sk_option **opts = NULL;
+
+ debug("%s: provider \"%s\", key %s, flags 0x%02x%s", __func__,
+ provider_path, sshkey_type(key), key->sk_flags,
+ (pin != NULL && *pin != '\0') ? " with-pin" : "");
+
+ if (sigp != NULL)
+ *sigp = NULL;
+ if (lenp != NULL)
+ *lenp = 0;
+ type = sshkey_type_plain(key->type);
+ switch (type) {
+#ifdef WITH_OPENSSL
+ case KEY_ECDSA_SK:
+ alg = SSH_SK_ECDSA;
+ break;
+#endif /* WITH_OPENSSL */
+ case KEY_ED25519_SK:
+ alg = SSH_SK_ED25519;
+ break;
+ default:
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+ if (provider_path == NULL ||
+ key->sk_key_handle == NULL ||
+ key->sk_application == NULL || *key->sk_application == '\0') {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if ((skp = sshsk_open(provider_path)) == NULL) {
+ r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */
+ goto out;
+ }
+
+ 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);
+ r = skerr_to_ssherr(r);
+ goto out;
+ }
+ /* Assemble signature */
+ if ((sig = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put_cstring(sig, sshkey_ssh_name_plain(key))) != 0) {
+ debug("%s: buffer error (outer): %s", __func__, ssh_err(r));
+ goto out;
+ }
+ switch (type) {
+#ifdef WITH_OPENSSL
+ case KEY_ECDSA_SK:
+ if ((r = sshsk_ecdsa_sig(resp, sig)) != 0)
+ goto out;
+ break;
+#endif /* WITH_OPENSSL */
+ case KEY_ED25519_SK:
+ if ((r = sshsk_ed25519_sig(resp, sig)) != 0)
+ goto out;
+ break;
+ }
+#ifdef DEBUG_SK
+ fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n",
+ __func__, resp->flags, resp->counter);
+ fprintf(stderr, "%s: hashed message:\n", __func__);
+ sshbuf_dump_data(message, sizeof(message), stderr);
+ fprintf(stderr, "%s: sigbuf:\n", __func__);
+ sshbuf_dump(sig, stderr);
+#endif
+ if (sigp != NULL) {
+ if ((*sigp = malloc(sshbuf_len(sig))) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ memcpy(*sigp, sshbuf_ptr(sig), sshbuf_len(sig));
+ }
+ if (lenp != NULL)
+ *lenp = sshbuf_len(sig);
+ /* success */
+ r = 0;
+ out:
+ sshsk_free_options(opts);
+ sshsk_free(skp);
+ sshsk_free_sign_response(resp);
+ sshbuf_free(sig);
+ sshbuf_free(inner_sig);
+ return r;
+}
+
+static void
+sshsk_free_sk_resident_keys(struct sk_resident_key **rks, size_t nrks)
+{
+ size_t i;
+
+ if (nrks == 0 || rks == NULL)
+ return;
+ for (i = 0; i < nrks; i++) {
+ free(rks[i]->application);
+ freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len);
+ freezero(rks[i]->key.public_key, rks[i]->key.public_key_len);
+ freezero(rks[i]->key.signature, rks[i]->key.signature_len);
+ freezero(rks[i]->key.attestation_cert,
+ rks[i]->key.attestation_cert_len);
+ freezero(rks[i], sizeof(**rks));
+ }
+ free(rks);
+}
+
+int
+sshsk_load_resident(const char *provider_path, const char *device,
+ const char *pin, struct sshkey ***keysp, size_t *nkeysp)
+{
+ struct sshsk_provider *skp = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ struct sk_resident_key **rks = NULL;
+ size_t i, nrks = 0, nkeys = 0;
+ struct sshkey *key = NULL, **keys = NULL, **tmp;
+ uint8_t flags;
+ struct sk_option **opts = NULL;
+
+ debug("%s: provider \"%s\"%s", __func__, provider_path,
+ (pin != NULL && *pin != '\0') ? ", have-pin": "");
+
+ if (keysp == NULL || nkeysp == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ *keysp = NULL;
+ *nkeysp = 0;
+
+ if ((r = make_options(device, NULL, &opts)) != 0)
+ goto out;
+ if ((skp = sshsk_open(provider_path)) == NULL) {
+ r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */
+ goto out;
+ }
+ if ((r = skp->sk_load_resident_keys(pin, opts, &rks, &nrks)) != 0) {
+ error("Provider \"%s\" returned failure %d", provider_path, r);
+ r = skerr_to_ssherr(r);
+ goto out;
+ }
+ for (i = 0; i < nrks; i++) {
+ debug3("%s: rk %zu: slot = %zu, alg = %d, application = \"%s\"",
+ __func__, i, rks[i]->slot, rks[i]->alg,
+ rks[i]->application);
+ /* XXX need better filter here */
+ if (strncmp(rks[i]->application, "ssh:", 4) != 0)
+ continue;
+ switch (rks[i]->alg) {
+ case SSH_SK_ECDSA:
+ case SSH_SK_ED25519:
+ break;
+ default:
+ continue;
+ }
+ /* XXX where to get flags? */
+ flags = SSH_SK_USER_PRESENCE_REQD|SSH_SK_RESIDENT_KEY;
+ 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__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ keys = tmp;
+ keys[nkeys++] = key;
+ key = NULL;
+ /* XXX synthesise comment */
+ }
+ /* success */
+ *keysp = keys;
+ *nkeysp = nkeys;
+ keys = NULL;
+ nkeys = 0;
+ r = 0;
+ out:
+ sshsk_free_options(opts);
+ sshsk_free(skp);
+ sshsk_free_sk_resident_keys(rks, nrks);
+ sshkey_free(key);
+ if (nkeys != 0) {
+ for (i = 0; i < nkeys; i++)
+ sshkey_free(keys[i]);
+ free(keys);
+ }
+ return r;
+}
+
+#endif /* ENABLE_SK */
diff --git a/ssh-sk.h b/ssh-sk.h
new file mode 100644
index 00000000..0f566bbc
--- /dev/null
+++ b/ssh-sk.h
@@ -0,0 +1,69 @@
+/* $OpenBSD: ssh-sk.h,v 1.10 2020/01/10 23:43:26 djm Exp $ */
+/*
+ * Copyright (c) 2019 Google LLC
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SSH_SK_H
+#define _SSH_SK_H 1
+
+struct sshbuf;
+struct sshkey;
+struct sk_option;
+
+/* Version of protocol expected from ssh-sk-helper */
+#define SSH_SK_HELPER_VERSION 5
+
+/* ssh-sk-helper messages */
+#define SSH_SK_HELPER_ERROR 0 /* Only valid H->C */
+#define SSH_SK_HELPER_SIGN 1
+#define SSH_SK_HELPER_ENROLL 2
+#define SSH_SK_HELPER_LOAD_RESIDENT 3
+
+/*
+ * Enroll (generate) a new security-key hosted private key of given type
+ * via the specified provider middleware.
+ * If challenge_buf is NULL then a random 256 bit challenge will be used.
+ *
+ * Returns 0 on success or a ssherr.h error code on failure.
+ *
+ * If successful and the attest_data buffer is not NULL then attestation
+ * information is placed there.
+ */
+int sshsk_enroll(int type, const char *provider_path, const char *device,
+ const char *application, const char *userid, uint8_t flags,
+ const char *pin, struct sshbuf *challenge_buf,
+ struct sshkey **keyp, struct sshbuf *attest);
+
+/*
+ * Calculate an ECDSA_SK or ED25519_SK signature using the specified key
+ * and provider middleware.
+ *
+ * Returns 0 on success or a ssherr.h error code on failure.
+ */
+int sshsk_sign(const char *provider_path, struct sshkey *key,
+ u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
+ u_int compat, const char *pin);
+
+/*
+ * Enumerates and loads all SSH-compatible resident keys from a security
+ * key.
+ *
+ * Returns 0 on success or a ssherr.h error code on failure.
+ */
+int sshsk_load_resident(const char *provider_path, const char *device,
+ const char *pin, struct sshkey ***keysp, size_t *nkeysp);
+
+#endif /* _SSH_SK_H */
+
diff --git a/ssh-xmss.c b/ssh-xmss.c
new file mode 100644
index 00000000..ccd4c760
--- /dev/null
+++ b/ssh-xmss.c
@@ -0,0 +1,186 @@
+/* $OpenBSD: ssh-xmss.c,v 1.2 2020/02/26 13:40:09 jsg Exp $*/
+/*
+ * Copyright (c) 2017 Stefan-Lukas Gazdag.
+ * Copyright (c) 2017 Markus Friedl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "includes.h"
+#ifdef WITH_XMSS
+
+#define SSHKEY_INTERNAL
+#include <sys/types.h>
+#include <limits.h>
+
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include "log.h"
+#include "sshbuf.h"
+#include "sshkey.h"
+#include "sshkey-xmss.h"
+#include "ssherr.h"
+#include "ssh.h"
+
+#include "xmss_fast.h"
+
+int
+ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
+ const u_char *data, size_t datalen, u_int compat)
+{
+ u_char *sig = NULL;
+ size_t slen = 0, len = 0, required_siglen;
+ unsigned long long smlen;
+ int r, ret;
+ struct sshbuf *b = NULL;
+
+ if (lenp != NULL)
+ *lenp = 0;
+ if (sigp != NULL)
+ *sigp = NULL;
+
+ if (key == NULL ||
+ sshkey_type_plain(key->type) != KEY_XMSS ||
+ key->xmss_sk == NULL ||
+ sshkey_xmss_params(key) == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0)
+ return r;
+ if (datalen >= INT_MAX - required_siglen)
+ return SSH_ERR_INVALID_ARGUMENT;
+ smlen = slen = datalen + required_siglen;
+ if ((sig = malloc(slen)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((r = sshkey_xmss_get_state(key, error)) != 0)
+ goto out;
+ if ((ret = xmss_sign(key->xmss_sk, sshkey_xmss_bds_state(key), sig, &smlen,
+ data, datalen, sshkey_xmss_params(key))) != 0 || smlen <= datalen) {
+ r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */
+ goto out;
+ }
+ /* encode signature */
+ if ((b = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put_cstring(b, "ssh-xmss@openssh.com")) != 0 ||
+ (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0)
+ goto out;
+ len = sshbuf_len(b);
+ if (sigp != NULL) {
+ if ((*sigp = malloc(len)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ memcpy(*sigp, sshbuf_ptr(b), len);
+ }
+ if (lenp != NULL)
+ *lenp = len;
+ /* success */
+ r = 0;
+ out:
+ if ((ret = sshkey_xmss_update_state(key, error)) != 0) {
+ /* discard signature since we cannot update the state */
+ if (r == 0 && sigp != NULL && *sigp != NULL) {
+ explicit_bzero(*sigp, len);
+ free(*sigp);
+ }
+ if (sigp != NULL)
+ *sigp = NULL;
+ if (lenp != NULL)
+ *lenp = 0;
+ r = ret;
+ }
+ sshbuf_free(b);
+ if (sig != NULL)
+ freezero(sig, slen);
+
+ return r;
+}
+
+int
+ssh_xmss_verify(const struct sshkey *key,
+ const u_char *signature, size_t signaturelen,
+ const u_char *data, size_t datalen, u_int compat)
+{
+ struct sshbuf *b = NULL;
+ char *ktype = NULL;
+ const u_char *sigblob;
+ u_char *sm = NULL, *m = NULL;
+ size_t len, required_siglen;
+ unsigned long long smlen = 0, mlen = 0;
+ int r, ret;
+
+ if (key == NULL ||
+ sshkey_type_plain(key->type) != KEY_XMSS ||
+ key->xmss_pk == NULL ||
+ sshkey_xmss_params(key) == NULL ||
+ signature == NULL || signaturelen == 0)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0)
+ return r;
+ if (datalen >= INT_MAX - required_siglen)
+ return SSH_ERR_INVALID_ARGUMENT;
+
+ if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 ||
+ (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0)
+ goto out;
+ if (strcmp("ssh-xmss@openssh.com", ktype) != 0) {
+ r = SSH_ERR_KEY_TYPE_MISMATCH;
+ goto out;
+ }
+ if (sshbuf_len(b) != 0) {
+ r = SSH_ERR_UNEXPECTED_TRAILING_DATA;
+ goto out;
+ }
+ if (len != required_siglen) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (datalen >= SIZE_MAX - len) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ smlen = len + datalen;
+ mlen = smlen;
+ if ((sm = malloc(smlen)) == NULL || (m = malloc(mlen)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ memcpy(sm, sigblob, len);
+ memcpy(sm+len, data, 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);
+ }
+ if (ret != 0 || mlen != datalen) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ /* XXX compare 'm' and 'data' ? */
+ /* success */
+ r = 0;
+ out:
+ if (sm != NULL)
+ freezero(sm, smlen);
+ if (m != NULL)
+ freezero(m, smlen);
+ sshbuf_free(b);
+ free(ktype);
+ return r;
+}
+#endif /* WITH_XMSS */
diff --git a/ssh.0 b/ssh.0
deleted file mode 100644
index 5e5f3b5e..00000000
--- a/ssh.0
+++ /dev/null
@@ -1,951 +0,0 @@
-SSH(1) General Commands Manual SSH(1)
-
-NAME
- ssh M-bM-^@M-^S OpenSSH SSH client (remote login program)
-
-SYNOPSIS
- ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
- [-D [bind_address:]port] [-E log_file] [-e escape_char]
- [-F configfile] [-I pkcs11] [-i identity_file]
- [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec]
- [-O ctl_cmd] [-o option] [-p port]
- [-Q cipher | cipher-auth | mac | kex | key | protocol-version]
- [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port]
- [-w local_tun[:remote_tun]] [user@]hostname [command]
-
-DESCRIPTION
- ssh (SSH client) is a program for logging into a remote machine and for
- executing commands on a remote machine. It is intended to replace rlogin
- and rsh, and provide secure encrypted communications between two
- untrusted hosts over an insecure network. X11 connections, arbitrary TCP
- ports and UNIX-domain sockets can also be forwarded over the secure
- channel.
-
- ssh connects and logs into the specified hostname (with optional user
- name). The user must prove his/her identity to the remote machine using
- one of several methods depending on the protocol version used (see
- below).
-
- If command is specified, it is executed on the remote host instead of a
- login shell.
-
- The options are as follows:
-
- -1 Forces ssh to try protocol version 1 only.
-
- -2 Forces ssh to try protocol version 2 only.
-
- -4 Forces ssh to use IPv4 addresses only.
-
- -6 Forces ssh to use IPv6 addresses only.
-
- -A Enables forwarding of the authentication agent connection. This
- can also be specified on a per-host basis in a configuration
- file.
-
- Agent forwarding should be enabled with caution. Users with the
- ability to bypass file permissions on the remote host (for the
- agent's UNIX-domain socket) can access the local agent through
- the forwarded connection. An attacker cannot obtain key material
- from the agent, however they can perform operations on the keys
- that enable them to authenticate using the identities loaded into
- the agent.
-
- -a Disables forwarding of the authentication agent connection.
-
- -b bind_address
- Use bind_address on the local machine as the source address of
- the connection. Only useful on systems with more than one
- address.
-
- -C Requests compression of all data (including stdin, stdout,
- stderr, and data for forwarded X11, TCP and UNIX-domain
- connections). The compression algorithm is the same used by
- gzip(1), and the M-bM-^@M-^\levelM-bM-^@M-^] can be controlled by the
- CompressionLevel option for protocol version 1. Compression is
- desirable on modem lines and other slow connections, but will
- only slow down things on fast networks. The default value can be
- set on a host-by-host basis in the configuration files; see the
- Compression option.
-
- -c cipher_spec
- Selects the cipher specification for encrypting the session.
-
- Protocol version 1 allows specification of a single cipher. The
- supported values are M-bM-^@M-^\3desM-bM-^@M-^], M-bM-^@M-^\blowfishM-bM-^@M-^], and M-bM-^@M-^\desM-bM-^@M-^]. For protocol
- version 2, cipher_spec is a comma-separated list of ciphers
- listed in order of preference. See the Ciphers keyword in
- ssh_config(5) for more information.
-
- -D [bind_address:]port
- Specifies a local M-bM-^@M-^\dynamicM-bM-^@M-^] application-level port forwarding.
- This works by allocating a socket to listen to port on the local
- side, optionally bound to the specified bind_address. Whenever a
- connection is made to this port, the connection is forwarded over
- the secure channel, and the application protocol is then used to
- determine where to connect to from the remote machine. Currently
- the SOCKS4 and SOCKS5 protocols are supported, and ssh will act
- as a SOCKS server. Only root can forward privileged ports.
- Dynamic port forwardings can also be specified in the
- configuration file.
-
- IPv6 addresses can be specified by enclosing the address in
- square brackets. Only the superuser can forward privileged
- ports. By default, the local port is bound in accordance with
- the GatewayPorts setting. However, an explicit bind_address may
- be used to bind the connection to a specific address. The
- bind_address of M-bM-^@M-^\localhostM-bM-^@M-^] indicates that the listening port be
- bound for local use only, while an empty address or M-bM-^@M-^X*M-bM-^@M-^Y indicates
- that the port should be available from all interfaces.
-
- -E log_file
- Append debug logs to log_file instead of standard error.
-
- -e escape_char
- Sets the escape character for sessions with a pty (default: M-bM-^@M-^X~M-bM-^@M-^Y).
- The escape character is only recognized at the beginning of a
- line. The escape character followed by a dot (M-bM-^@M-^X.M-bM-^@M-^Y) closes the
- connection; followed by control-Z suspends the connection; and
- followed by itself sends the escape character once. Setting the
- character to M-bM-^@M-^\noneM-bM-^@M-^] disables any escapes and makes the session
- fully transparent.
-
- -F configfile
- Specifies an alternative per-user configuration file. If a
- configuration file is given on the command line, the system-wide
- configuration file (/etc/ssh/ssh_config) will be ignored. The
- default for the per-user configuration file is ~/.ssh/config.
-
- -f Requests ssh to go to background just before command execution.
- This is useful if ssh is going to ask for passwords or
- passphrases, but the user wants it in the background. This
- implies -n. The recommended way to start X11 programs at a
- remote site is with something like ssh -f host xterm.
-
- If the ExitOnForwardFailure configuration option is set to M-bM-^@M-^\yesM-bM-^@M-^],
- then a client started with -f will wait for all remote port
- forwards to be successfully established before placing itself in
- the background.
-
- -G Causes ssh to print its configuration after evaluating Host and
- Match blocks and exit.
-
- -g Allows remote hosts to connect to local forwarded ports. If used
- on a multiplexed connection, then this option must be specified
- on the master process.
-
- -I pkcs11
- Specify the PKCS#11 shared library ssh should use to communicate
- with a PKCS#11 token providing the user's private RSA key.
-
- -i identity_file
- Selects a file from which the identity (private key) for public
- key authentication is read. The default is ~/.ssh/identity for
- protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa,
- ~/.ssh/id_ed25519 and ~/.ssh/id_rsa for protocol version 2.
- Identity files may also be specified on a per-host basis in the
- configuration file. It is possible to have multiple -i options
- (and multiple identities specified in configuration files). ssh
- will also try to load certificate information from the filename
- obtained by appending -cert.pub to identity filenames.
-
- -K Enables GSSAPI-based authentication and forwarding (delegation)
- of GSSAPI credentials to the server.
-
- -k Disables forwarding (delegation) of GSSAPI credentials to the
- server.
-
- -L [bind_address:]port:host:hostport
- Specifies that the given port on the local (client) host is to be
- forwarded to the given host and port on the remote side. This
- works by allocating a socket to listen to port on the local side,
- optionally bound to the specified bind_address. Whenever a
- connection is made to this port, the connection is forwarded over
- the secure channel, and a connection is made to host port
- hostport from the remote machine. Port forwardings can also be
- specified in the configuration file. IPv6 addresses can be
- specified by enclosing the address in square brackets. Only the
- superuser can forward privileged ports. By default, the local
- port is bound in accordance with the GatewayPorts setting.
- However, an explicit bind_address may be used to bind the
- connection to a specific address. The bind_address of
- M-bM-^@M-^\localhostM-bM-^@M-^] indicates that the listening port be bound for local
- use only, while an empty address or M-bM-^@M-^X*M-bM-^@M-^Y indicates that the port
- should be available from all interfaces.
-
- -l login_name
- Specifies the user to log in as on the remote machine. This also
- may be specified on a per-host basis in the configuration file.
-
- -M Places the ssh client into M-bM-^@M-^\masterM-bM-^@M-^] mode for connection sharing.
- Multiple -M options places ssh into M-bM-^@M-^\masterM-bM-^@M-^] mode with
- confirmation required before slave connections are accepted.
- Refer to the description of ControlMaster in ssh_config(5) for
- details.
-
- -m mac_spec
- Additionally, for protocol version 2 a comma-separated list of
- MAC (message authentication code) algorithms can be specified in
- order of preference. See the MACs keyword for more information.
-
- -N Do not execute a remote command. This is useful for just
- forwarding ports (protocol version 2 only).
-
- -n Redirects stdin from /dev/null (actually, prevents reading from
- stdin). This must be used when ssh is run in the background. A
- common trick is to use this to run X11 programs on a remote
- machine. For example, ssh -n shadows.cs.hut.fi emacs & will
- start an emacs on shadows.cs.hut.fi, and the X11 connection will
- be automatically forwarded over an encrypted channel. The ssh
- program will be put in the background. (This does not work if
- ssh needs to ask for a password or passphrase; see also the -f
- option.)
-
- -O ctl_cmd
- Control an active connection multiplexing master process. When
- the -O option is specified, the ctl_cmd argument is interpreted
- and passed to the master process. Valid commands are: M-bM-^@M-^\checkM-bM-^@M-^]
- (check that the master process is running), M-bM-^@M-^\forwardM-bM-^@M-^] (request
- forwardings without command execution), M-bM-^@M-^\cancelM-bM-^@M-^] (cancel
- forwardings), M-bM-^@M-^\exitM-bM-^@M-^] (request the master to exit), and M-bM-^@M-^\stopM-bM-^@M-^]
- (request the master to stop accepting further multiplexing
- requests).
-
- -o option
- Can be used to give options in the format used in the
- configuration file. This is useful for specifying options for
- which there is no separate command-line flag. For full details
- of the options listed below, and their possible values, see
- ssh_config(5).
-
- AddressFamily
- BatchMode
- BindAddress
- CanonicalDomains
- CanonicalizeFallbackLocal
- CanonicalizeHostname
- CanonicalizeMaxDots
- CanonicalizePermittedCNAMEs
- ChallengeResponseAuthentication
- CheckHostIP
- Cipher
- Ciphers
- ClearAllForwardings
- Compression
- CompressionLevel
- ConnectionAttempts
- ConnectTimeout
- ControlMaster
- ControlPath
- ControlPersist
- DynamicForward
- EscapeChar
- ExitOnForwardFailure
- FingerprintHash
- ForwardAgent
- ForwardX11
- ForwardX11Timeout
- ForwardX11Trusted
- GatewayPorts
- GlobalKnownHostsFile
- GSSAPIAuthentication
- GSSAPIDelegateCredentials
- HashKnownHosts
- Host
- HostbasedAuthentication
- HostbasedKeyTypes
- HostKeyAlgorithms
- HostKeyAlias
- HostName
- IdentityFile
- IdentitiesOnly
- IPQoS
- KbdInteractiveAuthentication
- KbdInteractiveDevices
- KexAlgorithms
- LocalCommand
- LocalForward
- LogLevel
- MACs
- Match
- NoHostAuthenticationForLocalhost
- NumberOfPasswordPrompts
- PasswordAuthentication
- PermitLocalCommand
- PKCS11Provider
- Port
- PreferredAuthentications
- Protocol
- ProxyCommand
- ProxyUseFdpass
- PubkeyAuthentication
- RekeyLimit
- RemoteForward
- RequestTTY
- RhostsRSAAuthentication
- RSAAuthentication
- SendEnv
- ServerAliveInterval
- ServerAliveCountMax
- StreamLocalBindMask
- StreamLocalBindUnlink
- StrictHostKeyChecking
- TCPKeepAlive
- Tunnel
- TunnelDevice
- UpdateHostKeys
- UsePrivilegedPort
- User
- UserKnownHostsFile
- VerifyHostKeyDNS
- VisualHostKey
- XAuthLocation
-
- -p port
- Port to connect to on the remote host. This can be specified on
- a per-host basis in the configuration file.
-
- -Q cipher | cipher-auth | mac | kex | key | protocol-version
- Queries ssh for the algorithms supported for the specified
- version 2. The available features are: cipher (supported
- symmetric ciphers), cipher-auth (supported symmetric ciphers that
- support authenticated encryption), mac (supported message
- integrity codes), kex (key exchange algorithms), key (key types)
- and protocol-version (supported SSH protocol versions).
-
- -q Quiet mode. Causes most warning and diagnostic messages to be
- suppressed.
-
- -R [bind_address:]port:host:hostport
- Specifies that the given port on the remote (server) host is to
- be forwarded to the given host and port on the local side. This
- works by allocating a socket to listen to port on the remote
- side, and whenever a connection is made to this port, the
- connection is forwarded over the secure channel, and a connection
- is made to host port hostport from the local machine.
-
- Port forwardings can also be specified in the configuration file.
- Privileged ports can be forwarded only when logging in as root on
- the remote machine. IPv6 addresses can be specified by enclosing
- the address in square brackets.
-
- By default, the listening socket on the server will be bound to
- the loopback interface only. This may be overridden by
- specifying a bind_address. An empty bind_address, or the address
- M-bM-^@M-^X*M-bM-^@M-^Y, indicates that the remote socket should listen on all
- interfaces. Specifying a remote bind_address will only succeed
- if the server's GatewayPorts option is enabled (see
- sshd_config(5)).
-
- If the port argument is M-bM-^@M-^X0M-bM-^@M-^Y, the listen port will be dynamically
- allocated on the server and reported to the client at run time.
- When used together with -O forward the allocated port will be
- printed to the standard output.
-
- -S ctl_path
- Specifies the location of a control socket for connection
- sharing, or the string M-bM-^@M-^\noneM-bM-^@M-^] to disable connection sharing.
- Refer to the description of ControlPath and ControlMaster in
- ssh_config(5) for details.
-
- -s May be used to request invocation of a subsystem on the remote
- system. Subsystems are a feature of the SSH2 protocol which
- facilitate the use of SSH as a secure transport for other
- applications (eg. sftp(1)). The subsystem is specified as the
- remote command.
-
- -T Disable pseudo-tty allocation.
-
- -t Force pseudo-tty allocation. This can be used to execute
- arbitrary screen-based programs on a remote machine, which can be
- very useful, e.g. when implementing menu services. Multiple -t
- options force tty allocation, even if ssh has no local tty.
-
- -V Display the version number and exit.
-
- -v Verbose mode. Causes ssh to print debugging messages about its
- progress. This is helpful in debugging connection,
- authentication, and configuration problems. Multiple -v options
- increase the verbosity. The maximum is 3.
-
- -W host:port
- Requests that standard input and output on the client be
- forwarded to host on port over the secure channel. Implies -N,
- -T, ExitOnForwardFailure and ClearAllForwardings. Works with
- Protocol version 2 only.
-
- -w local_tun[:remote_tun]
- Requests tunnel device forwarding with the specified tun(4)
- devices between the client (local_tun) and the server
- (remote_tun).
-
- The devices may be specified by numerical ID or the keyword
- M-bM-^@M-^\anyM-bM-^@M-^], which uses the next available tunnel device. If
- remote_tun is not specified, it defaults to M-bM-^@M-^\anyM-bM-^@M-^]. See also the
- Tunnel and TunnelDevice directives in ssh_config(5). If the
- Tunnel directive is unset, it is set to the default tunnel mode,
- which is M-bM-^@M-^\point-to-pointM-bM-^@M-^].
-
- -X Enables X11 forwarding. This can also be specified on a per-host
- basis in a configuration file.
-
- X11 forwarding should be enabled with caution. Users with the
- ability to bypass file permissions on the remote host (for the
- user's X authorization database) can access the local X11 display
- through the forwarded connection. An attacker may then be able
- to perform activities such as keystroke monitoring.
-
- For this reason, X11 forwarding is subjected to X11 SECURITY
- extension restrictions by default. Please refer to the ssh -Y
- option and the ForwardX11Trusted directive in ssh_config(5) for
- more information.
-
- -x Disables X11 forwarding.
-
- -Y Enables trusted X11 forwarding. Trusted X11 forwardings are not
- subjected to the X11 SECURITY extension controls.
-
- -y Send log information using the syslog(3) system module. By
- default this information is sent to stderr.
-
- ssh may additionally obtain configuration data from a per-user
- configuration file and a system-wide configuration file. The file format
- and configuration options are described in ssh_config(5).
-
-AUTHENTICATION
- The OpenSSH SSH client supports SSH protocols 1 and 2. The default is to
- use protocol 2 only, though this can be changed via the Protocol option
- in ssh_config(5) or the -1 and -2 options (see above). Both protocols
- support similar authentication methods, but protocol 2 is the default
- since it provides additional mechanisms for confidentiality (the traffic
- is encrypted using AES, 3DES, Blowfish, CAST128, or Arcfour) and
- integrity (hmac-md5, hmac-sha1, hmac-sha2-256, hmac-sha2-512, umac-64,
- umac-128, hmac-ripemd160). Protocol 1 lacks a strong mechanism for
- ensuring the integrity of the connection.
-
- The methods available for authentication are: GSSAPI-based
- authentication, host-based authentication, public key authentication,
- challenge-response authentication, and password authentication.
- Authentication methods are tried in the order specified above, though
- protocol 2 has a configuration option to change the default order:
- PreferredAuthentications.
-
- Host-based authentication works as follows: If the machine the user logs
- in from is listed in /etc/hosts.equiv or /etc/shosts.equiv on the remote
- machine, and the user names are the same on both sides, or if the files
- ~/.rhosts or ~/.shosts exist in the user's home directory on the remote
- machine and contain a line containing the name of the client machine and
- the name of the user on that machine, the user is considered for login.
- Additionally, the server must be able to verify the client's host key
- (see the description of /etc/ssh/ssh_known_hosts and ~/.ssh/known_hosts,
- below) for login to be permitted. This authentication method closes
- security holes due to IP spoofing, DNS spoofing, and routing spoofing.
- [Note to the administrator: /etc/hosts.equiv, ~/.rhosts, and the
- rlogin/rsh protocol in general, are inherently insecure and should be
- disabled if security is desired.]
-
- Public key authentication works as follows: The scheme is based on
- public-key cryptography, using cryptosystems where encryption and
- decryption are done using separate keys, and it is unfeasible to derive
- the decryption key from the encryption key. The idea is that each user
- creates a public/private key pair for authentication purposes. The
- server knows the public key, and only the user knows the private key.
- ssh implements public key authentication protocol automatically, using
- one of the DSA, ECDSA, Ed25519 or RSA algorithms. Protocol 1 is
- restricted to using only RSA keys, but protocol 2 may use any. The
- HISTORY section of ssl(8) contains a brief discussion of the DSA and RSA
- algorithms.
-
- The file ~/.ssh/authorized_keys lists the public keys that are permitted
- for logging in. When the user logs in, the ssh program tells the server
- which key pair it would like to use for authentication. The client
- proves that it has access to the private key and the server checks that
- the corresponding public key is authorized to accept the account.
-
- The user creates his/her key pair by running ssh-keygen(1). This stores
- the private key in ~/.ssh/identity (protocol 1), ~/.ssh/id_dsa (protocol
- 2 DSA), ~/.ssh/id_ecdsa (protocol 2 ECDSA), ~/.ssh/id_ed25519 (protocol 2
- Ed25519), or ~/.ssh/id_rsa (protocol 2 RSA) and stores the public key in
- ~/.ssh/identity.pub (protocol 1), ~/.ssh/id_dsa.pub (protocol 2 DSA),
- ~/.ssh/id_ecdsa.pub (protocol 2 ECDSA), ~/.ssh/id_ed25519.pub (protocol 2
- Ed25519), or ~/.ssh/id_rsa.pub (protocol 2 RSA) in the user's home
- directory. The user should then copy the public key to
- ~/.ssh/authorized_keys in his/her home directory on the remote machine.
- The authorized_keys file corresponds to the conventional ~/.rhosts file,
- and has one key per line, though the lines can be very long. After this,
- the user can log in without giving the password.
-
- A variation on public key authentication is available in the form of
- certificate authentication: instead of a set of public/private keys,
- signed certificates are used. This has the advantage that a single
- trusted certification authority can be used in place of many
- public/private keys. See the CERTIFICATES section of ssh-keygen(1) for
- more information.
-
- The most convenient way to use public key or certificate authentication
- may be with an authentication agent. See ssh-agent(1) for more
- information.
-
- Challenge-response authentication works as follows: The server sends an
- arbitrary "challenge" text, and prompts for a response. Protocol 2
- allows multiple challenges and responses; protocol 1 is restricted to
- just one challenge/response. Examples of challenge-response
- authentication include BSD Authentication (see login.conf(5)) and PAM
- (some non-OpenBSD systems).
-
- Finally, if other authentication methods fail, ssh prompts the user for a
- password. The password is sent to the remote host for checking; however,
- since all communications are encrypted, the password cannot be seen by
- someone listening on the network.
-
- ssh automatically maintains and checks a database containing
- identification for all hosts it has ever been used with. Host keys are
- stored in ~/.ssh/known_hosts in the user's home directory. Additionally,
- the file /etc/ssh/ssh_known_hosts is automatically checked for known
- hosts. Any new hosts are automatically added to the user's file. If a
- host's identification ever changes, ssh warns about this and disables
- password authentication to prevent server spoofing or man-in-the-middle
- attacks, which could otherwise be used to circumvent the encryption. The
- StrictHostKeyChecking option can be used to control logins to machines
- whose host key is not known or has changed.
-
- When the user's identity has been accepted by the server, the server
- either executes the given command, or logs into the machine and gives the
- user a normal shell on the remote machine. All communication with the
- remote command or shell will be automatically encrypted.
-
- If a pseudo-terminal has been allocated (normal login session), the user
- may use the escape characters noted below.
-
- If no pseudo-tty has been allocated, the session is transparent and can
- be used to reliably transfer binary data. On most systems, setting the
- escape character to M-bM-^@M-^\noneM-bM-^@M-^] will also make the session transparent even if
- a tty is used.
-
- The session terminates when the command or shell on the remote machine
- exits and all X11 and TCP connections have been closed.
-
-ESCAPE CHARACTERS
- When a pseudo-terminal has been requested, ssh supports a number of
- functions through the use of an escape character.
-
- A single tilde character can be sent as ~~ or by following the tilde by a
- character other than those described below. The escape character must
- always follow a newline to be interpreted as special. The escape
- character can be changed in configuration files using the EscapeChar
- configuration directive or on the command line by the -e option.
-
- The supported escapes (assuming the default M-bM-^@M-^X~M-bM-^@M-^Y) are:
-
- ~. Disconnect.
-
- ~^Z Background ssh.
-
- ~# List forwarded connections.
-
- ~& Background ssh at logout when waiting for forwarded connection /
- X11 sessions to terminate.
-
- ~? Display a list of escape characters.
-
- ~B Send a BREAK to the remote system (only useful for SSH protocol
- version 2 and if the peer supports it).
-
- ~C Open command line. Currently this allows the addition of port
- forwardings using the -L, -R and -D options (see above). It also
- allows the cancellation of existing port-forwardings with
- -KL[bind_address:]port for local, -KR[bind_address:]port for
- remote and -KD[bind_address:]port for dynamic port-forwardings.
- !command allows the user to execute a local command if the
- PermitLocalCommand option is enabled in ssh_config(5). Basic
- help is available, using the -h option.
-
- ~R Request rekeying of the connection (only useful for SSH protocol
- version 2 and if the peer supports it).
-
- ~V Decrease the verbosity (LogLevel) when errors are being written
- to stderr.
-
- ~v Increase the verbosity (LogLevel) when errors are being written
- to stderr.
-
-TCP FORWARDING
- Forwarding of arbitrary TCP connections over the secure channel can be
- specified either on the command line or in a configuration file. One
- possible application of TCP forwarding is a secure connection to a mail
- server; another is going through firewalls.
-
- In the example below, we look at encrypting communication between an IRC
- client and server, even though the IRC server does not directly support
- encrypted communications. This works as follows: the user connects to
- the remote host using ssh, specifying a port to be used to forward
- connections to the remote server. After that it is possible to start the
- service which is to be encrypted on the client machine, connecting to the
- same local port, and ssh will encrypt and forward the connection.
-
- The following example tunnels an IRC session from client machine
- M-bM-^@M-^\127.0.0.1M-bM-^@M-^] (localhost) to remote server M-bM-^@M-^\server.example.comM-bM-^@M-^]:
-
- $ ssh -f -L 1234:localhost:6667 server.example.com sleep 10
- $ irc -c '#users' -p 1234 pinky 127.0.0.1
-
- This tunnels a connection to IRC server M-bM-^@M-^\server.example.comM-bM-^@M-^], joining
- channel M-bM-^@M-^\#usersM-bM-^@M-^], nickname M-bM-^@M-^\pinkyM-bM-^@M-^], using port 1234. It doesn't matter
- which port is used, as long as it's greater than 1023 (remember, only
- root can open sockets on privileged ports) and doesn't conflict with any
- ports already in use. The connection is forwarded to port 6667 on the
- remote server, since that's the standard port for IRC services.
-
- The -f option backgrounds ssh and the remote command M-bM-^@M-^\sleep 10M-bM-^@M-^] is
- specified to allow an amount of time (10 seconds, in the example) to
- start the service which is to be tunnelled. If no connections are made
- within the time specified, ssh will exit.
-
-X11 FORWARDING
- If the ForwardX11 variable is set to M-bM-^@M-^\yesM-bM-^@M-^] (or see the description of the
- -X, -x, and -Y options above) and the user is using X11 (the DISPLAY
- environment variable is set), the connection to the X11 display is
- automatically forwarded to the remote side in such a way that any X11
- programs started from the shell (or command) will go through the
- encrypted channel, and the connection to the real X server will be made
- from the local machine. The user should not manually set DISPLAY.
- Forwarding of X11 connections can be configured on the command line or in
- configuration files.
-
- The DISPLAY value set by ssh will point to the server machine, but with a
- display number greater than zero. This is normal, and happens because
- ssh creates a M-bM-^@M-^\proxyM-bM-^@M-^] X server on the server machine for forwarding the
- connections over the encrypted channel.
-
- ssh will also automatically set up Xauthority data on the server machine.
- For this purpose, it will generate a random authorization cookie, store
- it in Xauthority on the server, and verify that any forwarded connections
- carry this cookie and replace it by the real cookie when the connection
- is opened. The real authentication cookie is never sent to the server
- machine (and no cookies are sent in the plain).
-
- If the ForwardAgent variable is set to M-bM-^@M-^\yesM-bM-^@M-^] (or see the description of
- the -A and -a options above) and the user is using an authentication
- agent, the connection to the agent is automatically forwarded to the
- remote side.
-
-VERIFYING HOST KEYS
- When connecting to a server for the first time, a fingerprint of the
- server's public key is presented to the user (unless the option
- StrictHostKeyChecking has been disabled). Fingerprints can be determined
- using ssh-keygen(1):
-
- $ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key
-
- If the fingerprint is already known, it can be matched and the key can be
- accepted or rejected. Because of the difficulty of comparing host keys
- just by looking at fingerprint strings, there is also support to compare
- host keys visually, using random art. By setting the VisualHostKey
- option to M-bM-^@M-^\yesM-bM-^@M-^], a small ASCII graphic gets displayed on every login to a
- server, no matter if the session itself is interactive or not. By
- learning the pattern a known server produces, a user can easily find out
- that the host key has changed when a completely different pattern is
- displayed. Because these patterns are not unambiguous however, a pattern
- that looks similar to the pattern remembered only gives a good
- probability that the host key is the same, not guaranteed proof.
-
- To get a listing of the fingerprints along with their random art for all
- known hosts, the following command line can be used:
-
- $ ssh-keygen -lv -f ~/.ssh/known_hosts
-
- If the fingerprint is unknown, an alternative method of verification is
- available: SSH fingerprints verified by DNS. An additional resource
- record (RR), SSHFP, is added to a zonefile and the connecting client is
- able to match the fingerprint with that of the key presented.
-
- In this example, we are connecting a client to a server,
- M-bM-^@M-^\host.example.comM-bM-^@M-^]. The SSHFP resource records should first be added to
- the zonefile for host.example.com:
-
- $ ssh-keygen -r host.example.com.
-
- The output lines will have to be added to the zonefile. To check that
- the zone is answering fingerprint queries:
-
- $ dig -t SSHFP host.example.com
-
- Finally the client connects:
-
- $ ssh -o "VerifyHostKeyDNS ask" host.example.com
- [...]
- Matching host key fingerprint found in DNS.
- Are you sure you want to continue connecting (yes/no)?
-
- See the VerifyHostKeyDNS option in ssh_config(5) for more information.
-
-SSH-BASED VIRTUAL PRIVATE NETWORKS
- ssh contains support for Virtual Private Network (VPN) tunnelling using
- the tun(4) network pseudo-device, allowing two networks to be joined
- securely. The sshd_config(5) configuration option PermitTunnel controls
- whether the server supports this, and at what level (layer 2 or 3
- traffic).
-
- The following example would connect client network 10.0.50.0/24 with
- remote network 10.0.99.0/24 using a point-to-point connection from
- 10.1.1.1 to 10.1.1.2, provided that the SSH server running on the gateway
- to the remote network, at 192.168.1.15, allows it.
-
- On the client:
-
- # ssh -f -w 0:1 192.168.1.15 true
- # ifconfig tun0 10.1.1.1 10.1.1.2 netmask 255.255.255.252
- # route add 10.0.99.0/24 10.1.1.2
-
- On the server:
-
- # ifconfig tun1 10.1.1.2 10.1.1.1 netmask 255.255.255.252
- # route add 10.0.50.0/24 10.1.1.1
-
- Client access may be more finely tuned via the /root/.ssh/authorized_keys
- file (see below) and the PermitRootLogin server option. The following
- entry would permit connections on tun(4) device 1 from user M-bM-^@M-^\janeM-bM-^@M-^] and on
- tun device 2 from user M-bM-^@M-^\johnM-bM-^@M-^], if PermitRootLogin is set to
- M-bM-^@M-^\forced-commands-onlyM-bM-^@M-^]:
-
- tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... jane
- tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john
-
- Since an SSH-based setup entails a fair amount of overhead, it may be
- more suited to temporary setups, such as for wireless VPNs. More
- permanent VPNs are better provided by tools such as ipsecctl(8) and
- isakmpd(8).
-
-ENVIRONMENT
- ssh will normally set the following environment variables:
-
- DISPLAY The DISPLAY variable indicates the location of the
- X11 server. It is automatically set by ssh to
- point to a value of the form M-bM-^@M-^\hostname:nM-bM-^@M-^], where
- M-bM-^@M-^\hostnameM-bM-^@M-^] indicates the host where the shell runs,
- and M-bM-^@M-^XnM-bM-^@M-^Y is an integer M-bM-^IM-% 1. ssh uses this special
- value to forward X11 connections over the secure
- channel. The user should normally not set DISPLAY
- explicitly, as that will render the X11 connection
- insecure (and will require the user to manually
- copy any required authorization cookies).
-
- HOME Set to the path of the user's home directory.
-
- LOGNAME Synonym for USER; set for compatibility with
- systems that use this variable.
-
- MAIL Set to the path of the user's mailbox.
-
- PATH Set to the default PATH, as specified when
- compiling ssh.
-
- SSH_ASKPASS If ssh needs a passphrase, it will read the
- passphrase from the current terminal if it was run
- from a terminal. If ssh does not have a terminal
- associated with it but DISPLAY and SSH_ASKPASS are
- set, it will execute the program specified by
- SSH_ASKPASS and open an X11 window to read the
- passphrase. This is particularly useful when
- calling ssh from a .xsession or related script.
- (Note that on some machines it may be necessary to
- redirect the input from /dev/null to make this
- work.)
-
- SSH_AUTH_SOCK Identifies the path of a UNIX-domain socket used to
- communicate with the agent.
-
- SSH_CONNECTION Identifies the client and server ends of the
- connection. The variable contains four space-
- separated values: client IP address, client port
- number, server IP address, and server port number.
-
- SSH_ORIGINAL_COMMAND This variable contains the original command line if
- a forced command is executed. It can be used to
- extract the original arguments.
-
- SSH_TTY This is set to the name of the tty (path to the
- device) associated with the current shell or
- command. If the current session has no tty, this
- variable is not set.
-
- TZ This variable is set to indicate the present time
- zone if it was set when the daemon was started
- (i.e. the daemon passes the value on to new
- connections).
-
- USER Set to the name of the user logging in.
-
- Additionally, ssh reads ~/.ssh/environment, and adds lines of the format
- M-bM-^@M-^\VARNAME=valueM-bM-^@M-^] to the environment if the file exists and users are
- allowed to change their environment. For more information, see the
- PermitUserEnvironment option in sshd_config(5).
-
-FILES
- ~/.rhosts
- This file is used for host-based authentication (see above). On
- some machines this file may need to be world-readable if the
- user's home directory is on an NFS partition, because sshd(8)
- reads it as root. Additionally, this file must be owned by the
- user, and must not have write permissions for anyone else. The
- recommended permission for most machines is read/write for the
- user, and not accessible by others.
-
- ~/.shosts
- This file is used in exactly the same way as .rhosts, but allows
- host-based authentication without permitting login with
- rlogin/rsh.
-
- ~/.ssh/
- This directory is the default location for all user-specific
- configuration and authentication information. There is no
- general requirement to keep the entire contents of this directory
- secret, but the recommended permissions are read/write/execute
- for the user, and not accessible by others.
-
- ~/.ssh/authorized_keys
- Lists the public keys (DSA, ECDSA, Ed25519, RSA) that can be used
- for logging in as this user. The format of this file is
- described in the sshd(8) manual page. This file is not highly
- sensitive, but the recommended permissions are read/write for the
- user, and not accessible by others.
-
- ~/.ssh/config
- This is the per-user configuration file. The file format and
- configuration options are described in ssh_config(5). Because of
- the potential for abuse, this file must have strict permissions:
- read/write for the user, and not writable by others.
-
- ~/.ssh/environment
- Contains additional definitions for environment variables; see
- ENVIRONMENT, above.
-
- ~/.ssh/identity
- ~/.ssh/id_dsa
- ~/.ssh/id_ecdsa
- ~/.ssh/id_ed25519
- ~/.ssh/id_rsa
- Contains the private key for authentication. These files contain
- sensitive data and should be readable by the user but not
- accessible by others (read/write/execute). ssh will simply
- ignore a private key file if it is accessible by others. It is
- possible to specify a passphrase when generating the key which
- will be used to encrypt the sensitive part of this file using
- 3DES.
-
- ~/.ssh/identity.pub
- ~/.ssh/id_dsa.pub
- ~/.ssh/id_ecdsa.pub
- ~/.ssh/id_ed25519.pub
- ~/.ssh/id_rsa.pub
- Contains the public key for authentication. These files are not
- sensitive and can (but need not) be readable by anyone.
-
- ~/.ssh/known_hosts
- Contains a list of host keys for all hosts the user has logged
- into that are not already in the systemwide list of known host
- keys. See sshd(8) for further details of the format of this
- file.
-
- ~/.ssh/rc
- Commands in this file are executed by ssh when the user logs in,
- just before the user's shell (or command) is started. See the
- sshd(8) manual page for more information.
-
- /etc/hosts.equiv
- This file is for host-based authentication (see above). It
- should only be writable by root.
-
- /etc/shosts.equiv
- This file is used in exactly the same way as hosts.equiv, but
- allows host-based authentication without permitting login with
- rlogin/rsh.
-
- /etc/ssh/ssh_config
- Systemwide configuration file. The file format and configuration
- options are described in ssh_config(5).
-
- /etc/ssh/ssh_host_key
- /etc/ssh/ssh_host_dsa_key
- /etc/ssh/ssh_host_ecdsa_key
- /etc/ssh/ssh_host_ed25519_key
- /etc/ssh/ssh_host_rsa_key
- These files contain the private parts of the host keys and are
- used for host-based authentication. If protocol version 1 is
- used, ssh must be setuid root, since the host key is readable
- only by root. For protocol version 2, ssh uses ssh-keysign(8) to
- access the host keys, eliminating the requirement that ssh be
- setuid root when host-based authentication is used. By default
- ssh is not setuid root.
-
- /etc/ssh/ssh_known_hosts
- Systemwide list of known host keys. This file should be prepared
- by the system administrator to contain the public host keys of
- all machines in the organization. It should be world-readable.
- See sshd(8) for further details of the format of this file.
-
- /etc/ssh/sshrc
- Commands in this file are executed by ssh when the user logs in,
- just before the user's shell (or command) is started. See the
- sshd(8) manual page for more information.
-
-EXIT STATUS
- ssh exits with the exit status of the remote command or with 255 if an
- error occurred.
-
-SEE ALSO
- scp(1), sftp(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh-keyscan(1),
- tun(4), ssh_config(5), ssh-keysign(8), sshd(8)
-
-STANDARDS
- S. Lehtinen and C. Lonvick, The Secure Shell (SSH) Protocol Assigned
- Numbers, RFC 4250, January 2006.
-
- T. Ylonen and C. Lonvick, The Secure Shell (SSH) Protocol Architecture,
- RFC 4251, January 2006.
-
- T. Ylonen and C. Lonvick, The Secure Shell (SSH) Authentication Protocol,
- RFC 4252, January 2006.
-
- T. Ylonen and C. Lonvick, The Secure Shell (SSH) Transport Layer
- Protocol, RFC 4253, January 2006.
-
- T. Ylonen and C. Lonvick, The Secure Shell (SSH) Connection Protocol, RFC
- 4254, January 2006.
-
- J. Schlyter and W. Griffin, Using DNS to Securely Publish Secure Shell
- (SSH) Key Fingerprints, RFC 4255, January 2006.
-
- F. Cusack and M. Forssen, Generic Message Exchange Authentication for the
- Secure Shell Protocol (SSH), RFC 4256, January 2006.
-
- J. Galbraith and P. Remaker, The Secure Shell (SSH) Session Channel Break
- Extension, RFC 4335, January 2006.
-
- M. Bellare, T. Kohno, and C. Namprempre, The Secure Shell (SSH) Transport
- Layer Encryption Modes, RFC 4344, January 2006.
-
- B. Harris, Improved Arcfour Modes for the Secure Shell (SSH) Transport
- Layer Protocol, RFC 4345, January 2006.
-
- M. Friedl, N. Provos, and W. Simpson, Diffie-Hellman Group Exchange for
- the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006.
-
- J. Galbraith and R. Thayer, The Secure Shell (SSH) Public Key File
- Format, RFC 4716, November 2006.
-
- D. Stebila and J. Green, Elliptic Curve Algorithm Integration in the
- Secure Shell Transport Layer, RFC 5656, December 2009.
-
- A. Perrig and D. Song, Hash Visualization: a New Technique to improve
- Real-World Security, 1999, International Workshop on Cryptographic
- Techniques and E-Commerce (CrypTEC '99).
-
-AUTHORS
- OpenSSH is a derivative of the original and free ssh 1.2.12 release by
- Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
- de Raadt and Dug Song removed many bugs, re-added newer features and
- created OpenSSH. Markus Friedl contributed the support for SSH protocol
- versions 1.5 and 2.0.
-
-OpenBSD 5.7 March 3, 2015 OpenBSD 5.7
diff --git a/ssh.1 b/ssh.1
index da64b719..dce5f404 100644
--- a/ssh.1
+++ b/ssh.1
@@ -33,17 +33,17 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh.1,v 1.356 2015/03/03 06:48:58 djm Exp $
-.Dd $Mdocdate: March 3 2015 $
+.\" $OpenBSD: ssh.1,v 1.412 2020/04/17 03:34:42 djm Exp $
+.Dd $Mdocdate: April 17 2020 $
.Dt SSH 1
.Os
.Sh NAME
.Nm ssh
-.Nd OpenSSH SSH client (remote login program)
+.Nd OpenSSH remote login client
.Sh SYNOPSIS
.Nm ssh
-.Bk -words
-.Op Fl 1246AaCfGgKkMNnqsTtVvXxYy
+.Op Fl 46AaCfGgKkMNnqsTtVvXxYy
+.Op Fl B Ar bind_interface
.Op Fl b Ar bind_address
.Op Fl c Ar cipher_spec
.Op Fl D Oo Ar bind_address : Oc Ns Ar port
@@ -52,26 +52,25 @@
.Op Fl F Ar configfile
.Op Fl I Ar pkcs11
.Op Fl i Ar identity_file
-.Op Fl L Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport
+.Op Fl J Ar destination
+.Op Fl L Ar address
.Op Fl l Ar login_name
.Op Fl m Ar mac_spec
.Op Fl O Ar ctl_cmd
.Op Fl o Ar option
.Op Fl p Ar port
-.Op Fl Q Cm cipher | cipher-auth | mac | kex | key | protocol-version
-.Op Fl R Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport
+.Op Fl Q Ar query_option
+.Op Fl R Ar address
.Op Fl S Ar ctl_path
.Op Fl W Ar host : Ns Ar port
.Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun
-.Oo Ar user Ns @ Oc Ns Ar hostname
+.Ar destination
.Op Ar command
-.Ek
.Sh DESCRIPTION
.Nm
(SSH client) is a program for logging into a remote machine and for
executing commands on a remote machine.
-It is intended to replace rlogin and rsh,
-and provide secure encrypted communications between
+It is intended to provide secure encrypted communications between
two untrusted hosts over an insecure network.
X11 connections, arbitrary TCP ports and
.Ux Ns -domain
@@ -79,39 +78,40 @@ sockets can also be forwarded over the secure channel.
.Pp
.Nm
connects and logs into the specified
-.Ar hostname
-(with optional
-.Ar user
-name).
+.Ar destination ,
+which may be specified as either
+.Sm off
+.Oo user @ Oc hostname
+.Sm on
+or a URI of the form
+.Sm off
+.No ssh:// Oo user @ Oc hostname Op : port .
+.Sm on
The user must prove
his/her identity to the remote machine using one of several methods
-depending on the protocol version used (see below).
+(see below).
.Pp
-If
+If a
.Ar command
is specified,
it is executed on the remote host instead of a login shell.
.Pp
The options are as follows:
-.Bl -tag -width Ds
-.It Fl 1
-Forces
-.Nm
-to try protocol version 1 only.
-.It Fl 2
-Forces
-.Nm
-to try protocol version 2 only.
+.Pp
+.Bl -tag -width Ds -compact
.It Fl 4
Forces
.Nm
to use IPv4 addresses only.
+.Pp
.It Fl 6
Forces
.Nm
to use IPv6 addresses only.
+.Pp
.It Fl A
-Enables forwarding of the authentication agent connection.
+Enables forwarding of connections from an authentication agent such as
+.Xr ssh-agent 1 .
This can also be specified on a per-host basis in a configuration file.
.Pp
Agent forwarding should be enabled with caution.
@@ -122,42 +122,42 @@ socket) can access the local agent through the forwarded connection.
An attacker cannot obtain key material from the agent,
however they can perform operations on the keys that enable them to
authenticate using the identities loaded into the agent.
+A safer alternative may be to use a jump host
+(see
+.Fl J ) .
+.Pp
.It Fl a
Disables forwarding of the authentication agent connection.
+.Pp
+.It Fl B Ar bind_interface
+Bind to the address of
+.Ar bind_interface
+before attempting to connect to the destination host.
+This is only useful on systems with more than one address.
+.Pp
.It Fl b Ar bind_address
Use
.Ar bind_address
on the local machine as the source address
of the connection.
Only useful on systems with more than one address.
+.Pp
.It Fl C
Requests compression of all data (including stdin, stdout, stderr, and
data for forwarded X11, TCP and
.Ux Ns -domain
connections).
The compression algorithm is the same used by
-.Xr gzip 1 ,
-and the
-.Dq level
-can be controlled by the
-.Cm CompressionLevel
-option for protocol version 1.
+.Xr gzip 1 .
Compression is desirable on modem lines and other
slow connections, but will only slow down things on fast networks.
The default value can be set on a host-by-host basis in the
configuration files; see the
.Cm Compression
option.
+.Pp
.It Fl c Ar cipher_spec
Selects the cipher specification for encrypting the session.
-.Pp
-Protocol version 1 allows specification of a single cipher.
-The supported values are
-.Dq 3des ,
-.Dq blowfish ,
-and
-.Dq des .
-For protocol version 2,
.Ar cipher_spec
is a comma-separated list of ciphers
listed in order of preference.
@@ -166,6 +166,7 @@ See the
keyword in
.Xr ssh_config 5
for more information.
+.Pp
.It Fl D Xo
.Sm off
.Oo Ar bind_address : Oc
@@ -205,10 +206,12 @@ indicates that the listening port be bound for local use only, while an
empty address or
.Sq *
indicates that the port should be available from all interfaces.
+.Pp
.It Fl E Ar log_file
Append debug logs to
.Ar log_file
instead of standard error.
+.Pp
.It Fl e Ar escape_char
Sets the escape character for sessions with a pty (default:
.Ql ~ ) .
@@ -221,6 +224,7 @@ and followed by itself sends the escape character once.
Setting the character to
.Dq none
disables any escapes and makes the session fully transparent.
+.Pp
.It Fl F Ar configfile
Specifies an alternative per-user configuration file.
If a configuration file is given on the command line,
@@ -229,6 +233,10 @@ the system-wide configuration file
will be ignored.
The default for the per-user configuration file is
.Pa ~/.ssh/config .
+If set to
+.Dq none ,
+no configuration files will be read.
+.Pp
.It Fl f
Requests
.Nm
@@ -251,6 +259,7 @@ then a client started with
.Fl f
will wait for all remote port forwards to be successfully established
before placing itself in the background.
+.Pp
.It Fl G
Causes
.Nm
@@ -259,65 +268,112 @@ to print its configuration after evaluating
and
.Cm Match
blocks and exit.
+.Pp
.It Fl g
Allows remote hosts to connect to local forwarded ports.
If used on a multiplexed connection, then this option must be specified
on the master process.
+.Pp
.It Fl I Ar pkcs11
Specify the PKCS#11 shared library
.Nm
-should use to communicate with a PKCS#11 token providing the user's
-private RSA key.
+should use to communicate with a PKCS#11 token providing keys for user
+authentication.
+.Pp
.It Fl i Ar identity_file
Selects a file from which the identity (private key) for
public key authentication is read.
The default is
-.Pa ~/.ssh/identity
-for protocol version 1, and
.Pa ~/.ssh/id_dsa ,
.Pa ~/.ssh/id_ecdsa ,
-.Pa ~/.ssh/id_ed25519
+.Pa ~/.ssh/id_ecdsa_sk ,
+.Pa ~/.ssh/id_ed25519 ,
+.Pa ~/.ssh/id_ed25519_sk
and
-.Pa ~/.ssh/id_rsa
-for protocol version 2.
+.Pa ~/.ssh/id_rsa .
Identity files may also be specified on
a per-host basis in the configuration file.
It is possible to have multiple
.Fl i
options (and multiple identities specified in
configuration files).
+If no certificates have been explicitly specified by the
+.Cm CertificateFile
+directive,
.Nm
will also try to load certificate information from the filename obtained
by appending
.Pa -cert.pub
to identity filenames.
+.Pp
+.It Fl J Ar destination
+Connect to the target host by first making a
+.Nm
+connection to the jump host described by
+.Ar destination
+and then establishing a TCP forwarding to the ultimate destination from
+there.
+Multiple jump hops may be specified separated by comma characters.
+This is a shortcut to specify a
+.Cm ProxyJump
+configuration directive.
+Note that configuration directives supplied on the command-line generally
+apply to the destination host and not any specified jump hosts.
+Use
+.Pa ~/.ssh/config
+to specify configuration for jump hosts.
+.Pp
.It Fl K
Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI
credentials to the server.
+.Pp
.It Fl k
Disables forwarding (delegation) of GSSAPI credentials to the server.
+.Pp
.It Fl L Xo
.Sm off
.Oo Ar bind_address : Oc
.Ar port : host : hostport
.Sm on
.Xc
-Specifies that the given port on the local (client) host is to be
-forwarded to the given host and port on the remote side.
-This works by allocating a socket to listen to
+.It Fl L Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port : remote_socket
+.Sm on
+.Xc
+.It Fl L Xo
+.Sm off
+.Ar local_socket : host : hostport
+.Sm on
+.Xc
+.It Fl L Xo
+.Sm off
+.Ar local_socket : remote_socket
+.Sm on
+.Xc
+Specifies that connections to the given TCP port or Unix socket on the local
+(client) host are to be forwarded to the given host and port, or Unix socket,
+on the remote side.
+This works by allocating a socket to listen to either a TCP
.Ar port
on the local side, optionally bound to the specified
-.Ar bind_address .
-Whenever a connection is made to this port, the
+.Ar bind_address ,
+or to a Unix socket.
+Whenever a connection is made to the local port or socket, the
connection is forwarded over the secure channel, and a connection is
-made to
+made to either
.Ar host
port
-.Ar hostport
+.Ar hostport ,
+or the Unix socket
+.Ar remote_socket ,
from the remote machine.
+.Pp
Port forwardings can also be specified in the configuration file.
-IPv6 addresses can be specified by enclosing the address in square brackets.
Only the superuser can forward privileged ports.
+IPv6 addresses can be specified by enclosing the address in square brackets.
+.Pp
By default, the local port is bound in accordance with the
.Cm GatewayPorts
setting.
@@ -332,9 +388,11 @@ indicates that the listening port be bound for local use only, while an
empty address or
.Sq *
indicates that the port should be available from all interfaces.
+.Pp
.It Fl l Ar login_name
Specifies the user to log in as on the remote machine.
This also may be specified on a per-host basis in the configuration file.
+.Pp
.It Fl M
Places the
.Nm
@@ -347,23 +405,27 @@ options places
.Nm
into
.Dq master
-mode with confirmation required before slave connections are accepted.
+mode but with confirmation required using
+.Xr ssh-askpass 1
+before each operation that changes the multiplexing state
+(e.g. opening a new session).
Refer to the description of
.Cm ControlMaster
in
.Xr ssh_config 5
for details.
+.Pp
.It Fl m Ar mac_spec
-Additionally, for protocol version 2 a comma-separated list of MAC
-(message authentication code) algorithms can
-be specified in order of preference.
+A comma-separated list of MAC (message authentication code) algorithms,
+specified in order of preference.
See the
.Cm MACs
keyword for more information.
+.Pp
.It Fl N
Do not execute a remote command.
-This is useful for just forwarding ports
-(protocol version 2 only).
+This is useful for just forwarding ports.
+.Pp
.It Fl n
Redirects stdin from
.Pa /dev/null
@@ -384,6 +446,7 @@ program will be put in the background.
needs to ask for a password or passphrase; see also the
.Fl f
option.)
+.Pp
.It Fl O Ar ctl_cmd
Control an active connection multiplexing master process.
When the
@@ -402,6 +465,7 @@ Valid commands are:
(request the master to exit), and
.Dq stop
(request the master to stop accepting further multiplexing requests).
+.Pp
.It Fl o Ar option
Can be used to give options in the format used in the configuration file.
This is useful for specifying options for which there is no separate
@@ -410,6 +474,7 @@ For full details of the options listed below, and their possible values, see
.Xr ssh_config 5 .
.Pp
.Bl -tag -width Ds -offset indent -compact
+.It AddKeysToAgent
.It AddressFamily
.It BatchMode
.It BindAddress
@@ -418,13 +483,13 @@ For full details of the options listed below, and their possible values, see
.It CanonicalizeHostname
.It CanonicalizeMaxDots
.It CanonicalizePermittedCNAMEs
+.It CASignatureAlgorithms
+.It CertificateFile
.It ChallengeResponseAuthentication
.It CheckHostIP
-.It Cipher
.It Ciphers
.It ClearAllForwardings
.It Compression
-.It CompressionLevel
.It ConnectionAttempts
.It ConnectTimeout
.It ControlMaster
@@ -448,9 +513,10 @@ For full details of the options listed below, and their possible values, see
.It HostbasedKeyTypes
.It HostKeyAlgorithms
.It HostKeyAlias
-.It HostName
-.It IdentityFile
+.It Hostname
.It IdentitiesOnly
+.It IdentityAgent
+.It IdentityFile
.It IPQoS
.It KbdInteractiveAuthentication
.It KbdInteractiveDevices
@@ -467,18 +533,19 @@ For full details of the options listed below, and their possible values, see
.It PKCS11Provider
.It Port
.It PreferredAuthentications
-.It Protocol
.It ProxyCommand
+.It ProxyJump
.It ProxyUseFdpass
+.It PubkeyAcceptedKeyTypes
.It PubkeyAuthentication
.It RekeyLimit
+.It RemoteCommand
.It RemoteForward
.It RequestTTY
-.It RhostsRSAAuthentication
-.It RSAAuthentication
.It SendEnv
.It ServerAliveInterval
.It ServerAliveCountMax
+.It SetEnv
.It StreamLocalBindMask
.It StreamLocalBindUnlink
.It StrictHostKeyChecking
@@ -486,18 +553,19 @@ For full details of the options listed below, and their possible values, see
.It Tunnel
.It TunnelDevice
.It UpdateHostKeys
-.It UsePrivilegedPort
.It User
.It UserKnownHostsFile
.It VerifyHostKeyDNS
.It VisualHostKey
.It XAuthLocation
.El
+.Pp
.It Fl p Ar port
Port to connect to on the remote host.
This can be specified on a
per-host basis in the configuration file.
-.It Fl Q Cm cipher | cipher-auth | mac | kex | key | protocol-version
+.Pp
+.It Fl Q Ar query_option
Queries
.Nm
for the algorithms supported for the specified version 2.
@@ -506,41 +574,90 @@ The available features are:
(supported symmetric ciphers),
.Ar cipher-auth
(supported symmetric ciphers that support authenticated encryption),
+.Ar help
+(supported query terms for use with the
+.Fl Q
+flag),
.Ar mac
(supported message integrity codes),
.Ar kex
(key exchange algorithms),
.Ar key
-(key types) and
+(key types),
+.Ar key-cert
+(certificate key types),
+.Ar key-plain
+(non-certificate key types),
+.Ar key-sig
+(all key types and signature algorithms),
.Ar protocol-version
-(supported SSH protocol versions).
+(supported SSH protocol versions), and
+.Ar sig
+(supported signature algorithms).
+Alternatively, any keyword from
+.Xr ssh_config 5
+or
+.Xr sshd_config 5
+that takes an algorithm list may be used as an alias for the corresponding
+query_option.
+.Pp
.It Fl q
Quiet mode.
Causes most warning and diagnostic messages to be suppressed.
+.Pp
.It Fl R Xo
.Sm off
.Oo Ar bind_address : Oc
.Ar port : host : hostport
.Sm on
.Xc
-Specifies that the given port on the remote (server) host is to be
-forwarded to the given host and port on the local side.
-This works by allocating a socket to listen to
+.It Fl R Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port : local_socket
+.Sm on
+.Xc
+.It Fl R Xo
+.Sm off
+.Ar remote_socket : host : hostport
+.Sm on
+.Xc
+.It Fl R Xo
+.Sm off
+.Ar remote_socket : local_socket
+.Sm on
+.Xc
+.It Fl R Xo
+.Sm off
+.Oo Ar bind_address : Oc
.Ar port
-on the remote side, and whenever a connection is made to this port, the
-connection is forwarded over the secure channel, and a connection is
-made to
+.Sm on
+.Xc
+Specifies that connections to the given TCP port or Unix socket on the remote
+(server) host are to be forwarded to the local side.
+.Pp
+This works by allocating a socket to listen to either a TCP
+.Ar port
+or to a Unix socket on the remote side.
+Whenever a connection is made to this port or Unix socket, the
+connection is forwarded over the secure channel, and a connection
+is made from the local machine to either an explicit destination specified by
.Ar host
port
-.Ar hostport
-from the local machine.
+.Ar hostport ,
+or
+.Ar local_socket ,
+or, if no explicit destination was specified,
+.Nm
+will act as a SOCKS 4/5 proxy and forward connections to the destinations
+requested by the remote SOCKS client.
.Pp
Port forwardings can also be specified in the configuration file.
Privileged ports can be forwarded only when
logging in as root on the remote machine.
IPv6 addresses can be specified by enclosing the address in square brackets.
.Pp
-By default, the listening socket on the server will be bound to the loopback
+By default, TCP listening sockets on the server will be bound to the loopback
interface only.
This may be overridden by specifying a
.Ar bind_address .
@@ -565,6 +682,7 @@ to the client at run time.
When used together with
.Ic -O forward
the allocated port will be printed to the standard output.
+.Pp
.It Fl S Ar ctl_path
Specifies the location of a control socket for connection sharing,
or the string
@@ -577,16 +695,19 @@ and
in
.Xr ssh_config 5
for details.
+.Pp
.It Fl s
May be used to request invocation of a subsystem on the remote system.
-Subsystems are a feature of the SSH2 protocol which facilitate the use
-of SSH as a secure transport for other applications (eg.\&
+Subsystems facilitate the use of SSH
+as a secure transport for other applications (e.g.\&
.Xr sftp 1 ) .
The subsystem is specified as the remote command.
+.Pp
.It Fl T
-Disable pseudo-tty allocation.
+Disable pseudo-terminal allocation.
+.Pp
.It Fl t
-Force pseudo-tty allocation.
+Force pseudo-terminal allocation.
This can be used to execute arbitrary
screen-based programs on a remote machine, which can be very useful,
e.g. when implementing menu services.
@@ -595,8 +716,10 @@ Multiple
options force tty allocation, even if
.Nm
has no local tty.
+.Pp
.It Fl V
Display the version number and exit.
+.Pp
.It Fl v
Verbose mode.
Causes
@@ -608,6 +731,7 @@ Multiple
.Fl v
options increase the verbosity.
The maximum is 3.
+.Pp
.It Fl W Ar host : Ns Ar port
Requests that standard input and output on the client be forwarded to
.Ar host
@@ -619,8 +743,11 @@ Implies
.Fl T ,
.Cm ExitOnForwardFailure
and
-.Cm ClearAllForwardings .
-Works with Protocol version 2 only.
+.Cm ClearAllForwardings ,
+though these can be overridden in the configuration file or using
+.Fl o
+command line options.
+.Pp
.It Fl w Xo
.Ar local_tun Ns Op : Ns Ar remote_tun
.Xc
@@ -646,10 +773,16 @@ and
.Cm TunnelDevice
directives in
.Xr ssh_config 5 .
+.Pp
If the
.Cm Tunnel
-directive is unset, it is set to the default tunnel mode, which is
+directive is unset, it will be set to the default tunnel mode, which is
.Dq point-to-point .
+If a different
+.Cm Tunnel
+forwarding mode it desired, then it should be specified before
+.Fl w .
+.Pp
.It Fl X
Enables X11 forwarding.
This can also be specified on a per-host basis in a configuration file.
@@ -670,12 +803,15 @@ option and the
directive in
.Xr ssh_config 5
for more information.
+.Pp
.It Fl x
Disables X11 forwarding.
+.Pp
.It Fl Y
Enables trusted X11 forwarding.
Trusted X11 forwardings are not subjected to the X11 SECURITY extension
controls.
+.Pp
.It Fl y
Send log information using the
.Xr syslog 3
@@ -689,26 +825,7 @@ a per-user configuration file and a system-wide configuration file.
The file format and configuration options are described in
.Xr ssh_config 5 .
.Sh AUTHENTICATION
-The OpenSSH SSH client supports SSH protocols 1 and 2.
-The default is to use protocol 2 only,
-though this can be changed via the
-.Cm Protocol
-option in
-.Xr ssh_config 5
-or the
-.Fl 1
-and
-.Fl 2
-options (see above).
-Both protocols support similar authentication methods,
-but protocol 2 is the default since
-it provides additional mechanisms for confidentiality
-(the traffic is encrypted using AES, 3DES, Blowfish, CAST128, or Arcfour)
-and integrity (hmac-md5, hmac-sha1,
-hmac-sha2-256, hmac-sha2-512,
-umac-64, umac-128, hmac-ripemd160).
-Protocol 1 lacks a strong mechanism for ensuring the
-integrity of the connection.
+The OpenSSH SSH client supports SSH protocol 2.
.Pp
The methods available for authentication are:
GSSAPI-based authentication,
@@ -717,15 +834,16 @@ public key authentication,
challenge-response authentication,
and password authentication.
Authentication methods are tried in the order specified above,
-though protocol 2 has a configuration option to change the default order:
-.Cm PreferredAuthentications .
+though
+.Cm PreferredAuthentications
+can be used to change the default order.
.Pp
Host-based authentication works as follows:
If the machine the user logs in from is listed in
.Pa /etc/hosts.equiv
or
.Pa /etc/shosts.equiv
-on the remote machine, and the user names are
+on the remote machine, the user is non-root and the user names are
the same on both sides, or if the files
.Pa ~/.rhosts
or
@@ -762,8 +880,6 @@ The server knows the public key, and only the user knows the private key.
.Nm
implements public key authentication protocol automatically,
using one of the DSA, ECDSA, Ed25519 or RSA algorithms.
-Protocol 1 is restricted to using only RSA keys,
-but protocol 2 may use any.
The HISTORY section of
.Xr ssl 8
contains a brief discussion of the DSA and RSA algorithms.
@@ -779,32 +895,47 @@ The client proves that it has access to the private key
and the server checks that the corresponding public key
is authorized to accept the account.
.Pp
+The server may inform the client of errors that prevented public key
+authentication from succeeding after authentication completes using a
+different method.
+These may be viewed by increasing the
+.Cm LogLevel
+to
+.Cm DEBUG
+or higher (e.g. by using the
+.Fl v
+flag).
+.Pp
The user creates his/her key pair by running
.Xr ssh-keygen 1 .
This stores the private key in
-.Pa ~/.ssh/identity
-(protocol 1),
.Pa ~/.ssh/id_dsa
-(protocol 2 DSA),
+(DSA),
.Pa ~/.ssh/id_ecdsa
-(protocol 2 ECDSA),
+(ECDSA),
+.Pa ~/.ssh/id_ecdsa_sk
+(authenticator-hosted ECDSA),
.Pa ~/.ssh/id_ed25519
-(protocol 2 Ed25519),
+(Ed25519),
+.Pa ~/.ssh/id_ed25519_sk
+(authenticator-hosted Ed25519),
or
.Pa ~/.ssh/id_rsa
-(protocol 2 RSA)
+(RSA)
and stores the public key in
-.Pa ~/.ssh/identity.pub
-(protocol 1),
.Pa ~/.ssh/id_dsa.pub
-(protocol 2 DSA),
+(DSA),
.Pa ~/.ssh/id_ecdsa.pub
-(protocol 2 ECDSA),
+(ECDSA),
+.Pa ~/.ssh/id_ecdsa_sk.pub
+(authenticator-hosted ECDSA),
.Pa ~/.ssh/id_ed25519.pub
-(protocol 2 Ed25519),
+(Ed25519),
+.Pa ~/.ssh/id_ed25519_sk.pub
+(authenticator-hosted Ed25519),
or
.Pa ~/.ssh/id_rsa.pub
-(protocol 2 RSA)
+(RSA)
in the user's home directory.
The user should then copy the public key
to
@@ -832,14 +963,16 @@ The most convenient way to use public key or certificate authentication
may be with an authentication agent.
See
.Xr ssh-agent 1
+and (optionally) the
+.Cm AddKeysToAgent
+directive in
+.Xr ssh_config 5
for more information.
.Pp
Challenge-response authentication works as follows:
The server sends an arbitrary
.Qq challenge
text, and prompts for a response.
-Protocol 2 allows multiple challenges and responses;
-protocol 1 is restricted to just one challenge/response.
Examples of challenge-response authentication include
.Bx
Authentication (see
@@ -876,15 +1009,26 @@ option can be used to control logins to machines whose
host key is not known or has changed.
.Pp
When the user's identity has been accepted by the server, the server
-either executes the given command, or logs into the machine and gives
-the user a normal shell on the remote machine.
+either executes the given command in a non-interactive session or,
+if no command has been specified, logs into the machine and gives
+the user a normal shell as an interactive session.
All communication with
the remote command or shell will be automatically encrypted.
.Pp
-If a pseudo-terminal has been allocated (normal login session), the
+If an interactive session is requested
+.Nm
+by default will only request a pseudo-terminal (pty) for interactive
+sessions when the client has one.
+The flags
+.Fl T
+and
+.Fl t
+can be used to override this behaviour.
+.Pp
+If a pseudo-terminal has been allocated the
user may use the escape characters noted below.
.Pp
-If no pseudo-tty has been allocated,
+If no pseudo-terminal has been allocated,
the session is transparent and can be used to reliably transfer binary data.
On most systems, setting the escape character to
.Dq none
@@ -927,7 +1071,7 @@ at logout when waiting for forwarded connection / X11 sessions to terminate.
Display a list of escape characters.
.It Cm ~B
Send a BREAK to the remote system
-(only useful for SSH protocol version 2 and if the peer supports it).
+(only useful if the peer supports it).
.It Cm ~C
Open command line.
Currently this allows the addition of port forwardings using the
@@ -960,7 +1104,7 @@ Basic help is available, using the
option.
.It Cm ~R
Request rekeying of the connection
-(only useful for SSH protocol version 2 and if the peer supports it).
+(only useful if the peer supports it).
.It Cm ~V
Decrease the verbosity
.Pq Ic LogLevel
@@ -971,49 +1115,35 @@ Increase the verbosity
when errors are being written to stderr.
.El
.Sh TCP FORWARDING
-Forwarding of arbitrary TCP connections over the secure channel can
-be specified either on the command line or in a configuration file.
+Forwarding of arbitrary TCP connections over a secure channel
+can be specified either on the command line or in a configuration file.
One possible application of TCP forwarding is a secure connection to a
mail server; another is going through firewalls.
.Pp
-In the example below, we look at encrypting communication between
-an IRC client and server, even though the IRC server does not directly
-support encrypted communications.
+In the example below, we look at encrypting communication for an IRC client,
+even though the IRC server it connects to does not directly
+support encrypted communication.
This works as follows:
the user connects to the remote host using
.Nm ,
-specifying a port to be used to forward connections
-to the remote server.
-After that it is possible to start the service which is to be encrypted
-on the client machine,
-connecting to the same local port,
+specifying the ports to be used to forward the connection.
+After that it is possible to start the program locally,
and
.Nm
-will encrypt and forward the connection.
+will encrypt and forward the connection to the remote server.
.Pp
-The following example tunnels an IRC session from client machine
-.Dq 127.0.0.1
-(localhost)
-to remote server
-.Dq server.example.com :
-.Bd -literal -offset 4n
-$ ssh -f -L 1234:localhost:6667 server.example.com sleep 10
-$ irc -c '#users' -p 1234 pinky 127.0.0.1
-.Ed
-.Pp
-This tunnels a connection to IRC server
+The following example tunnels an IRC session from the client
+to an IRC server at
.Dq server.example.com ,
joining channel
.Dq #users ,
nickname
.Dq pinky ,
-using port 1234.
-It doesn't matter which port is used,
-as long as it's greater than 1023
-(remember, only root can open sockets on privileged ports)
-and doesn't conflict with any ports already in use.
-The connection is forwarded to port 6667 on the remote server,
-since that's the standard port for IRC services.
+using the standard IRC port, 6667:
+.Bd -literal -offset 4n
+$ ssh -f -L 6667:localhost:6667 server.example.com sleep 10
+$ irc -c '#users' pinky IRC/127.0.0.1
+.Ed
.Pp
The
.Fl f
@@ -1023,7 +1153,7 @@ and the remote command
.Dq sleep 10
is specified to allow an amount of time
(10 seconds, in the example)
-to start the service which is to be tunnelled.
+to start the program which is going to use the tunnel.
If no connections are made within the time specified,
.Nm
will exit.
@@ -1095,6 +1225,11 @@ Fingerprints can be determined using
.Pp
If the fingerprint is already known, it can be matched
and the key can be accepted or rejected.
+If only legacy (MD5) fingerprints for the server are available, the
+.Xr ssh-keygen 1
+.Fl E
+option may be used to downgrade the fingerprint algorithm to match.
+.Pp
Because of the difficulty of comparing host keys
just by looking at fingerprint strings,
there is also support to compare host keys visually,
@@ -1292,6 +1427,17 @@ This is set to the name of the tty (path to the device) associated
with the current shell or command.
If the current session has no tty,
this variable is not set.
+.It Ev SSH_TUNNEL
+Optionally set by
+.Xr sshd 8
+to contain the interface names assigned if tunnel forwarding was
+requested by the client.
+.It Ev SSH_USER_AUTH
+Optionally set by
+.Xr sshd 8 ,
+this variable may contain a pathname to a file that lists the authentication
+methods successfully used when the session was established, including any
+public keys that were used.
.It Ev TZ
This variable is set to indicate the present time zone if it
was set when the daemon was started (i.e. the daemon passes the value
@@ -1361,10 +1507,11 @@ Contains additional definitions for environment variables; see
.Sx ENVIRONMENT ,
above.
.Pp
-.It Pa ~/.ssh/identity
.It Pa ~/.ssh/id_dsa
.It Pa ~/.ssh/id_ecdsa
+.It Pa ~/.ssh/id_ecdsa_sk
.It Pa ~/.ssh/id_ed25519
+.It Pa ~/.ssh/id_ed25519_sk
.It Pa ~/.ssh/id_rsa
Contains the private key for authentication.
These files
@@ -1374,12 +1521,13 @@ accessible by others (read/write/execute).
will simply ignore a private key file if it is accessible by others.
It is possible to specify a passphrase when
generating the key which will be used to encrypt the
-sensitive part of this file using 3DES.
+sensitive part of this file using AES-128.
.Pp
-.It Pa ~/.ssh/identity.pub
.It Pa ~/.ssh/id_dsa.pub
.It Pa ~/.ssh/id_ecdsa.pub
+.It Pa ~/.ssh/id_ecdsa_sk.pub
.It Pa ~/.ssh/id_ed25519.pub
+.It Pa ~/.ssh/id_ed25519_sk.pub
.It Pa ~/.ssh/id_rsa.pub
Contains the public key for authentication.
These files are not
@@ -1423,20 +1571,6 @@ The file format and configuration options are described in
.It Pa /etc/ssh/ssh_host_rsa_key
These files contain the private parts of the host keys
and are used for host-based authentication.
-If protocol version 1 is used,
-.Nm
-must be setuid root, since the host key is readable only by root.
-For protocol version 2,
-.Nm
-uses
-.Xr ssh-keysign 8
-to access the host keys,
-eliminating the requirement that
-.Nm
-be setuid root when host-based authentication is used.
-By default
-.Nm
-is not setuid root.
.Pp
.It Pa /etc/ssh/ssh_known_hosts
Systemwide list of known host keys.
diff --git a/ssh.c b/ssh.c
index 73854622..98b6ce78 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.416 2015/03/03 06:48:58 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.527 2020/04/10 00:52:07 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -65,8 +65,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
#include <unistd.h>
#include <limits.h>
+#include <locale.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -80,16 +82,14 @@
#include "xmalloc.h"
#include "ssh.h"
-#include "ssh1.h"
#include "ssh2.h"
#include "canohost.h"
#include "compat.h"
#include "cipher.h"
-#include "digest.h"
#include "packet.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "channels.h"
-#include "key.h"
+#include "sshkey.h"
#include "authfd.h"
#include "authfile.h"
#include "pathnames.h"
@@ -104,10 +104,10 @@
#include "sshpty.h"
#include "match.h"
#include "msg.h"
-#include "uidswap.h"
-#include "roaming.h"
#include "version.h"
#include "ssherr.h"
+#include "myproposal.h"
+#include "utf8.h"
#ifdef ENABLE_PKCS11
#include "ssh-pkcs11.h"
@@ -151,10 +151,6 @@ int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty;
*/
int fork_after_authentication_flag = 0;
-/* forward stdio to remote host and port */
-char *stdio_forward_host = NULL;
-int stdio_forward_port = 0;
-
/*
* General data structure for command line options and options configurable
* in configuration files. See readconf.h.
@@ -166,29 +162,35 @@ char *config = NULL;
/*
* Name of the host we are connecting to. This is the name given on the
- * command line, or the HostName specified for the user-supplied name in a
+ * command line, or the Hostname specified for the user-supplied name in a
* configuration file.
*/
char *host;
+/*
+ * A config can specify a path to forward, overriding SSH_AUTH_SOCK. If this is
+ * not NULL, forward the socket at this path instead.
+ */
+char *forward_agent_sock_path = NULL;
+
+/* Various strings used to to percent_expand() arguments */
+static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
+static char uidstr[32], *host_arg, *conn_hash_hex;
+
/* socket address the host resolves to */
struct sockaddr_storage hostaddr;
/* Private host keys. */
Sensitive sensitive_data;
-/* Original real UID. */
-uid_t original_real_uid;
-uid_t original_effective_uid;
-
/* command to be executed */
-Buffer command;
+struct sshbuf *command;
/* Should we execute a command or invoke a subsystem? */
int subsystem_flag = 0;
/* # of replies received for global requests */
-static int remote_forward_confirms_received = 0;
+static int forward_confirms_pending = -1;
/* mux.c */
extern int muxserver_sock;
@@ -200,27 +202,21 @@ static void
usage(void)
{
fprintf(stderr,
-"usage: ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n"
-" [-D [bind_address:]port] [-E log_file] [-e escape_char]\n"
-" [-F configfile] [-I pkcs11] [-i identity_file]\n"
-" [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec]\n"
-" [-O ctl_cmd] [-o option] [-p port]\n"
-" [-Q cipher | cipher-auth | mac | kex | key]\n"
-" [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port]\n"
-" [-w local_tun[:remote_tun]] [user@]hostname [command]\n"
+"usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]\n"
+" [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]\n"
+" [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]\n"
+" [-i identity_file] [-J [user@]host[:port]] [-L address]\n"
+" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
+" [-Q query_option] [-R address] [-S ctl_path] [-W host:port]\n"
+" [-w local_tun[:remote_tun]] destination [command]\n"
);
exit(255);
}
-static int ssh_session(void);
-static int ssh_session2(void);
-static void load_public_identity_files(void);
+static int ssh_session2(struct ssh *, struct passwd *);
+static void load_public_identity_files(struct passwd *);
static void main_sigchld_handler(int);
-/* from muxclient.c */
-void muxclient(const char *);
-void muxserver_listen(void);
-
/* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */
static void
tilde_expand_paths(char **paths, u_int num_paths)
@@ -229,12 +225,40 @@ tilde_expand_paths(char **paths, u_int num_paths)
char *cp;
for (i = 0; i < num_paths; i++) {
- cp = tilde_expand_filename(paths[i], original_real_uid);
+ cp = tilde_expand_filename(paths[i], getuid());
free(paths[i]);
paths[i] = cp;
}
}
+#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)
+{
+ return percent_expand(str,
+ /* values from statics above */
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
+ /* values from arguments */
+ "d", homedir,
+ "h", remhost,
+ "r", remuser,
+ "u", locuser,
+ (char *)NULL);
+}
+
/*
* Attempt to resolve a host name / port to a set of addresses and
* optionally return any CNAMEs encountered along the way.
@@ -246,12 +270,15 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen)
{
char strport[NI_MAXSERV];
struct addrinfo hints, *res;
- int gaierr, loglevel = SYSLOG_LEVEL_DEBUG1;
+ int gaierr;
+ LogLevel loglevel = SYSLOG_LEVEL_DEBUG1;
if (port <= 0)
port = default_ssh_port();
+ if (cname != NULL)
+ *cname = '\0';
- snprintf(strport, sizeof strport, "%u", port);
+ snprintf(strport, sizeof strport, "%d", port);
memset(&hints, 0, sizeof(hints));
hints.ai_family = options.address_family == -1 ?
AF_UNSPEC : options.address_family;
@@ -276,6 +303,40 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen)
return res;
}
+/* Returns non-zero if name can only be an address and not a hostname */
+static int
+is_addr_fast(const char *name)
+{
+ return (strchr(name, '%') != NULL || strchr(name, ':') != NULL ||
+ strspn(name, "0123456789.") == strlen(name));
+}
+
+/* Returns non-zero if name represents a valid, single address */
+static int
+is_addr(const char *name)
+{
+ char strport[NI_MAXSERV];
+ struct addrinfo hints, *res;
+
+ if (is_addr_fast(name))
+ return 1;
+
+ snprintf(strport, sizeof strport, "%u", default_ssh_port());
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = options.address_family == -1 ?
+ AF_UNSPEC : options.address_family;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV;
+ if (getaddrinfo(name, strport, &hints, &res) != 0)
+ return 0;
+ if (res == NULL || res->ai_next != NULL) {
+ freeaddrinfo(res);
+ return 0;
+ }
+ freeaddrinfo(res);
+ return 1;
+}
+
/*
* Attempt to resolve a numeric host address / port to a single address.
* Returns a canonical address string.
@@ -336,7 +397,7 @@ resolve_addr(const char *name, int port, char *caddr, size_t clen)
* NB. this function must operate with a options having undefined members.
*/
static int
-check_follow_cname(char **namep, const char *cname)
+check_follow_cname(int direct, char **namep, const char *cname)
{
int i;
struct allowed_cname *rule;
@@ -348,18 +409,16 @@ check_follow_cname(char **namep, const char *cname)
return 0;
/*
* Don't attempt to canonicalize names that will be interpreted by
- * a proxy unless the user specifically requests so.
+ * a proxy or jump host unless the user specifically requests so.
*/
- if (!option_clear_or_none(options.proxy_command) &&
+ if (!direct &&
options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
return 0;
debug3("%s: check \"%s\" CNAME \"%s\"", __func__, *namep, cname);
for (i = 0; i < options.num_permitted_cnames; i++) {
rule = options.permitted_cnames + i;
- if (match_pattern_list(*namep, rule->source_list,
- strlen(rule->source_list), 1) != 1 ||
- match_pattern_list(cname, rule->target_list,
- strlen(rule->target_list), 1) != 1)
+ if (match_pattern_list(*namep, rule->source_list, 1) != 1 ||
+ match_pattern_list(cname, rule->target_list, 1) != 1)
continue;
verbose("Canonicalized DNS aliased hostname "
"\"%s\" => \"%s\"", *namep, cname);
@@ -379,22 +438,14 @@ check_follow_cname(char **namep, const char *cname)
static struct addrinfo *
resolve_canonicalize(char **hostp, int port)
{
- int i, ndots;
+ int i, direct, ndots;
char *cp, *fullhost, newname[NI_MAXHOST];
struct addrinfo *addrs;
- if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
- return NULL;
-
/*
- * Don't attempt to canonicalize names that will be interpreted by
- * a proxy unless the user specifically requests so.
+ * Attempt to canonicalise addresses, regardless of
+ * whether hostname canonicalisation was requested
*/
- if (!option_clear_or_none(options.proxy_command) &&
- options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
- return NULL;
-
- /* Try numeric hostnames first */
if ((addrs = resolve_addr(*hostp, port,
newname, sizeof(newname))) != NULL) {
debug2("%s: hostname %.100s is address", __func__, *hostp);
@@ -407,6 +458,41 @@ resolve_canonicalize(char **hostp, int port)
return addrs;
}
+ /*
+ * If this looks like an address but didn't parse as one, it might
+ * be an address with an invalid interface scope. Skip further
+ * attempts at canonicalisation.
+ */
+ if (is_addr_fast(*hostp)) {
+ debug("%s: hostname %.100s is an unrecognised address",
+ __func__, *hostp);
+ return NULL;
+ }
+
+ if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
+ return NULL;
+
+ /*
+ * Don't attempt to canonicalize names that will be interpreted by
+ * a proxy unless the user specifically requests so.
+ */
+ direct = option_clear_or_none(options.proxy_command) &&
+ options.jump_host == NULL;
+ if (!direct &&
+ options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
+ return NULL;
+
+ /* If domain name is anchored, then resolve it now */
+ if ((*hostp)[strlen(*hostp) - 1] == '.') {
+ debug3("%s: name is fully qualified", __func__);
+ fullhost = xstrdup(*hostp);
+ if ((addrs = resolve_host(fullhost, port, 0,
+ newname, sizeof(newname))) != NULL)
+ goto found;
+ free(fullhost);
+ goto notfound;
+ }
+
/* Don't apply canonicalization to sufficiently-qualified hostnames */
ndots = 0;
for (cp = *hostp; *cp != '\0'; cp++) {
@@ -420,7 +506,6 @@ resolve_canonicalize(char **hostp, int port)
}
/* Attempt each supplied suffix */
for (i = 0; i < options.num_canonical_domains; i++) {
- *newname = '\0';
xasprintf(&fullhost, "%s.%s.", *hostp,
options.canonical_domains[i]);
debug3("%s: attempting \"%s\" => \"%s\"", __func__,
@@ -430,10 +515,11 @@ resolve_canonicalize(char **hostp, int port)
free(fullhost);
continue;
}
+ found:
/* Remove trailing '.' */
fullhost[strlen(fullhost) - 1] = '\0';
/* Follow CNAME if requested */
- if (!check_follow_cname(&fullhost, newname)) {
+ if (!check_follow_cname(direct, &fullhost, newname)) {
debug("Canonicalized hostname \"%s\" => \"%s\"",
*hostp, fullhost);
}
@@ -441,6 +527,7 @@ resolve_canonicalize(char **hostp, int port)
*hostp = fullhost;
return addrs;
}
+ notfound:
if (!options.canonicalize_fallback_local)
fatal("%s: Could not resolve host \"%s\"", __progname, *hostp);
debug2("%s: host %s not found in any suffix", __func__, *hostp);
@@ -448,33 +535,59 @@ resolve_canonicalize(char **hostp, int port)
}
/*
+ * Check the result of hostkey loading, ignoring some errors and
+ * fatal()ing for others.
+ */
+static void
+check_load(int r, const char *path, const char *message)
+{
+ switch (r) {
+ case 0:
+ break;
+ case SSH_ERR_INTERNAL_ERROR:
+ case SSH_ERR_ALLOC_FAIL:
+ fatal("load %s \"%s\": %s", message, path, ssh_err(r));
+ case SSH_ERR_SYSTEM_ERROR:
+ /* Ignore missing files */
+ if (errno == ENOENT)
+ break;
+ /* FALLTHROUGH */
+ default:
+ error("load %s \"%s\": %s", message, path, ssh_err(r));
+ break;
+ }
+}
+
+/*
* Read per-user configuration file. Ignore the system wide config
* file if the user specifies a config file on the command line.
*/
static void
-process_config_files(const char *host_arg, struct passwd *pw, int post_canon)
+process_config_files(const char *host_name, struct passwd *pw, int final_pass,
+ int *want_final_pass)
{
char buf[PATH_MAX];
int r;
if (config != NULL) {
if (strcasecmp(config, "none") != 0 &&
- !read_config_file(config, pw, host, host_arg, &options,
- SSHCONF_USERCONF | (post_canon ? SSHCONF_POSTCANON : 0)))
+ !read_config_file(config, pw, host, host_name, &options,
+ SSHCONF_USERCONF | (final_pass ? SSHCONF_FINAL : 0),
+ want_final_pass))
fatal("Can't open user config file %.100s: "
"%.100s", config, strerror(errno));
} else {
r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir,
_PATH_SSH_USER_CONFFILE);
if (r > 0 && (size_t)r < sizeof(buf))
- (void)read_config_file(buf, pw, host, host_arg,
+ (void)read_config_file(buf, pw, host, host_name,
&options, SSHCONF_CHECKPERM | SSHCONF_USERCONF |
- (post_canon ? SSHCONF_POSTCANON : 0));
+ (final_pass ? SSHCONF_FINAL : 0), want_final_pass);
/* Read systemwide configuration file after user config. */
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw,
- host, host_arg, &options,
- post_canon ? SSHCONF_POSTCANON : 0);
+ host, host_name, &options,
+ final_pass ? SSHCONF_FINAL : 0, want_final_pass);
}
}
@@ -504,20 +617,18 @@ set_addrinfo_port(struct addrinfo *addrs, int port)
int
main(int ac, char **av)
{
- int i, r, opt, exit_status, use_syslog, config_test = 0;
- char *p, *cp, *line, *argv0, buf[PATH_MAX], *host_arg, *logfile;
- char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
+ 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];
struct stat st;
struct passwd *pw;
- int timeout_ms;
extern int optind, optreset;
extern char *optarg;
struct Forward fwd;
struct addrinfo *addrs = NULL;
- struct ssh_digest_ctx *md;
- u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
- char *conn_hash_hex;
+ size_t n, len;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@@ -535,41 +646,18 @@ main(int ac, char **av)
av = saved_av;
#endif
+ seed_rng();
+
/*
* Discard other fds that are hanging around. These can cause problem
* with backgrounded ssh processes started by ControlPersist.
*/
closefrom(STDERR_FILENO + 1);
- /*
- * Save the original real uid. It will be needed later (uid-swapping
- * may clobber the real uid).
- */
- original_real_uid = getuid();
- original_effective_uid = geteuid();
-
- /*
- * Use uid-swapping to give up root privileges for the duration of
- * option processing. We will re-instantiate the rights when we are
- * ready to create the privileged port, and will permanently drop
- * them when the port has been created (actually, when the connection
- * has been made, as we may need to create the port several times).
- */
- PRIV_END;
-
-#ifdef HAVE_SETRLIMIT
- /* If we are installed setuid root be careful to not drop core. */
- if (original_real_uid != original_effective_uid) {
- struct rlimit rlim;
- rlim.rlim_cur = rlim.rlim_max = 0;
- if (setrlimit(RLIMIT_CORE, &rlim) < 0)
- fatal("setrlimit failed: %.100s", strerror(errno));
- }
-#endif
/* Get user data. */
- pw = getpwuid(original_real_uid);
+ pw = getpwuid(getuid());
if (!pw) {
- logit("No user exists for uid %lu", (u_long)original_real_uid);
+ logit("No user exists for uid %lu", (u_long)getuid());
exit(255);
}
/* Take a copy of the returned structure. */
@@ -583,12 +671,21 @@ main(int ac, char **av)
*/
umask(022);
+ msetlocale();
+
/*
* Initialize option structure to indicate that no values have been
* set.
*/
initialize_options(&options);
+ /*
+ * Prepare main ssh transport/connection structures
+ */
+ if ((ssh = ssh_alloc_session_state()) == NULL)
+ fatal("Couldn't allocate session state");
+ channel_init_channels(ssh);
+
/* Parse command-line arguments. */
host = NULL;
use_syslog = 0;
@@ -597,13 +694,13 @@ main(int ac, char **av)
again:
while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
- "ACD:E:F:GI:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
+ "AB:CD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
switch (opt) {
case '1':
- options.protocol = SSH_PROTO_1;
+ fatal("SSH protocol v.1 is no longer supported");
break;
case '2':
- options.protocol = SSH_PROTO_2;
+ /* Ignored */
break;
case '4':
options.address_family = AF_INET;
@@ -628,7 +725,7 @@ main(int ac, char **av)
use_syslog = 1;
break;
case 'E':
- logfile = xstrdup(optarg);
+ logfile = optarg;
break;
case 'G':
config_test = 1;
@@ -641,7 +738,7 @@ main(int ac, char **av)
options.fwd_opts.gateway_ports = 1;
break;
case 'O':
- if (stdio_forward_host != NULL)
+ if (options.stdio_forward_host != NULL)
fatal("Cannot specify multiplexing "
"command with -W");
else if (muxclient_command != 0)
@@ -656,34 +753,53 @@ main(int ac, char **av)
muxclient_command = SSHMUX_COMMAND_STOP;
else if (strcmp(optarg, "cancel") == 0)
muxclient_command = SSHMUX_COMMAND_CANCEL_FWD;
+ else if (strcmp(optarg, "proxy") == 0)
+ muxclient_command = SSHMUX_COMMAND_PROXY;
else
fatal("Invalid multiplex command.");
break;
case 'P': /* deprecated */
- options.use_privileged_port = 0;
break;
case 'Q':
cp = NULL;
- if (strcmp(optarg, "cipher") == 0)
+ if (strcmp(optarg, "cipher") == 0 ||
+ strcasecmp(optarg, "Ciphers") == 0)
cp = cipher_alg_list('\n', 0);
else if (strcmp(optarg, "cipher-auth") == 0)
cp = cipher_alg_list('\n', 1);
- else if (strcmp(optarg, "mac") == 0)
+ else if (strcmp(optarg, "mac") == 0 ||
+ strcasecmp(optarg, "MACs") == 0)
cp = mac_alg_list('\n');
- else if (strcmp(optarg, "kex") == 0)
+ else if (strcmp(optarg, "kex") == 0 ||
+ strcasecmp(optarg, "KexAlgorithms") == 0)
cp = kex_alg_list('\n');
else if (strcmp(optarg, "key") == 0)
- cp = key_alg_list(0, 0);
+ cp = sshkey_alg_list(0, 0, 0, '\n');
else if (strcmp(optarg, "key-cert") == 0)
- cp = key_alg_list(1, 0);
+ cp = sshkey_alg_list(1, 0, 0, '\n');
else if (strcmp(optarg, "key-plain") == 0)
- cp = key_alg_list(0, 1);
- else if (strcmp(optarg, "protocol-version") == 0) {
-#ifdef WITH_SSH1
- cp = xstrdup("1\n2");
-#else
+ cp = sshkey_alg_list(0, 1, 0, '\n');
+ else if (strcmp(optarg, "key-sig") == 0 ||
+ strcasecmp(optarg, "PubkeyAcceptedKeyTypes") == 0 ||
+ strcasecmp(optarg, "HostKeyAlgorithms") == 0 ||
+ strcasecmp(optarg, "HostbasedKeyTypes") == 0 ||
+ strcasecmp(optarg, "HostbasedAcceptedKeyTypes") == 0)
+ cp = sshkey_alg_list(0, 0, 1, '\n');
+ else if (strcmp(optarg, "sig") == 0)
+ cp = sshkey_alg_list(0, 1, 1, '\n');
+ else if (strcmp(optarg, "protocol-version") == 0)
cp = xstrdup("2");
-#endif
+ else if (strcmp(optarg, "compression") == 0) {
+ cp = xstrdup(compression_alg_list(0));
+ len = strlen(cp);
+ for (n = 0; n < len; n++)
+ if (cp[n] == ',')
+ cp[n] = '\n';
+ } else if (strcmp(optarg, "help") == 0) {
+ cp = xstrdup(
+ "cipher\ncipher-auth\ncompression\nkex\n"
+ "key\nkey-cert\nkey-plain\nkey-sig\nmac\n"
+ "protocol-version\nsig");
}
if (cp == NULL)
fatal("Unsupported query \"%s\"", optarg);
@@ -705,21 +821,35 @@ main(int ac, char **av)
options.gss_deleg_creds = 1;
break;
case 'i':
- if (stat(optarg, &st) < 0) {
+ p = tilde_expand_filename(optarg, getuid());
+ if (stat(p, &st) == -1)
fprintf(stderr, "Warning: Identity file %s "
- "not accessible: %s.\n", optarg,
+ "not accessible: %s.\n", p,
strerror(errno));
- break;
- }
- add_identity_file(&options, NULL, optarg, 1);
+ else
+ add_identity_file(&options, NULL, p, 1);
+ free(p);
break;
case 'I':
#ifdef ENABLE_PKCS11
+ free(options.pkcs11_provider);
options.pkcs11_provider = xstrdup(optarg);
#else
fprintf(stderr, "no support for PKCS#11.\n");
#endif
break;
+ case 'J':
+ if (options.jump_host != NULL) {
+ fatal("Only a single -J option is permitted "
+ "(use commas to separate multiple "
+ "jump hops)");
+ }
+ if (options.proxy_command != NULL)
+ fatal("Cannot specify -J with ProxyCommand");
+ if (parse_jump(optarg, &options, 1) == -1)
+ fatal("Invalid -J argument");
+ options.proxy_command = xstrdup("none");
+ break;
case 't':
if (options.request_tty == REQUEST_TTY_YES)
options.request_tty = REQUEST_TTY_FORCE;
@@ -731,15 +861,17 @@ main(int ac, char **av)
debug_flag = 1;
options.log_level = SYSLOG_LEVEL_DEBUG1;
} else {
- if (options.log_level < SYSLOG_LEVEL_DEBUG3)
+ if (options.log_level < SYSLOG_LEVEL_DEBUG3) {
+ debug_flag++;
options.log_level++;
+ }
}
break;
case 'V':
fprintf(stderr, "%s, %s\n",
SSH_RELEASE,
#ifdef WITH_OPENSSL
- SSLeay_version(SSLEAY_VERSION)
+ OpenSSL_version(OPENSSL_VERSION)
#else
"without OpenSSL"
#endif
@@ -758,13 +890,13 @@ main(int ac, char **av)
}
break;
case 'W':
- if (stdio_forward_host != NULL)
+ if (options.stdio_forward_host != NULL)
fatal("stdio forward already specified");
if (muxclient_command != 0)
fatal("Cannot specify stdio forward with -O");
if (parse_forward(&fwd, optarg, 1, 0)) {
- stdio_forward_host = fwd.listen_host;
- stdio_forward_port = fwd.listen_port;
+ options.stdio_forward_host = fwd.listen_host;
+ options.stdio_forward_port = fwd.listen_port;
free(fwd.connect_host);
} else {
fprintf(stderr,
@@ -774,8 +906,6 @@ main(int ac, char **av)
}
options.request_tty = REQUEST_TTY_NO;
no_shell_flag = 1;
- options.clear_forwardings = 1;
- options.exit_on_forward_failure = 1;
break;
case 'q':
options.log_level = SYSLOG_LEVEL_QUIET;
@@ -796,31 +926,20 @@ main(int ac, char **av)
}
break;
case 'c':
- if (ciphers_valid(optarg)) {
- /* SSH2 only */
- options.ciphers = xstrdup(optarg);
- options.cipher = SSH_CIPHER_INVALID;
- } else {
- /* SSH1 only */
- options.cipher = cipher_number(optarg);
- if (options.cipher == -1) {
- fprintf(stderr,
- "Unknown cipher type '%s'\n",
- optarg);
- exit(255);
- }
- if (options.cipher == SSH_CIPHER_3DES)
- options.ciphers = "3des-cbc";
- else if (options.cipher == SSH_CIPHER_BLOWFISH)
- options.ciphers = "blowfish-cbc";
- else
- options.ciphers = (char *)-1;
+ if (!ciphers_valid(*optarg == '+' || *optarg == '^' ?
+ optarg + 1 : optarg)) {
+ fprintf(stderr, "Unknown cipher type '%s'\n",
+ optarg);
+ exit(255);
}
+ free(options.ciphers);
+ options.ciphers = xstrdup(optarg);
break;
case 'm':
- if (mac_valid(optarg))
+ if (mac_valid(optarg)) {
+ free(options.macs);
options.macs = xstrdup(optarg);
- else {
+ } else {
fprintf(stderr, "Unknown mac type '%s'\n",
optarg);
exit(255);
@@ -833,14 +952,18 @@ main(int ac, char **av)
options.control_master = SSHCTL_MASTER_YES;
break;
case 'p':
- options.port = a2port(optarg);
- if (options.port <= 0) {
- fprintf(stderr, "Bad port '%s'\n", optarg);
- exit(255);
+ if (options.port == -1) {
+ options.port = a2port(optarg);
+ if (options.port <= 0) {
+ fprintf(stderr, "Bad port '%s'\n",
+ optarg);
+ exit(255);
+ }
}
break;
case 'l':
- options.user = optarg;
+ if (options.user == NULL)
+ options.user = optarg;
break;
case 'L':
@@ -855,7 +978,8 @@ main(int ac, char **av)
break;
case 'R':
- if (parse_forward(&fwd, optarg, 0, 1)) {
+ if (parse_forward(&fwd, optarg, 0, 1) ||
+ parse_forward(&fwd, optarg, 1, 1)) {
add_remote_forward(&options, &fwd);
} else {
fprintf(stderr,
@@ -877,7 +1001,11 @@ main(int ac, char **av)
break;
case 'C':
+#ifdef WITH_ZLIB
options.compression = 1;
+#else
+ error("Compression not supported, disabling.");
+#endif
break;
case 'N':
no_shell_flag = 1;
@@ -898,13 +1026,15 @@ main(int ac, char **av)
subsystem_flag = 1;
break;
case 'S':
- if (options.control_path != NULL)
- free(options.control_path);
+ free(options.control_path);
options.control_path = xstrdup(optarg);
break;
case 'b':
options.bind_address = optarg;
break;
+ case 'B':
+ options.bind_interface = optarg;
+ break;
case 'F':
config = optarg;
break;
@@ -913,21 +1043,46 @@ main(int ac, char **av)
}
}
+ if (optind > 1 && strcmp(av[optind - 1], "--") == 0)
+ opt_terminated = 1;
+
ac -= optind;
av += optind;
if (ac > 0 && !host) {
- if (strrchr(*av, '@')) {
+ int tport;
+ char *tuser;
+ switch (parse_ssh_uri(*av, &tuser, &host, &tport)) {
+ case -1:
+ usage();
+ break;
+ case 0:
+ if (options.user == NULL) {
+ options.user = tuser;
+ tuser = NULL;
+ }
+ free(tuser);
+ if (options.port == -1 && tport != -1)
+ options.port = tport;
+ break;
+ default:
p = xstrdup(*av);
cp = strrchr(p, '@');
- if (cp == NULL || cp == p)
- usage();
- options.user = p;
- *cp = '\0';
- host = xstrdup(++cp);
- } else
- host = xstrdup(*av);
- if (ac > 1) {
+ if (cp != NULL) {
+ if (cp == p)
+ usage();
+ if (options.user == NULL) {
+ options.user = p;
+ p = NULL;
+ }
+ *cp++ = '\0';
+ host = xstrdup(cp);
+ free(p);
+ } else
+ host = p;
+ break;
+ }
+ if (ac > 1 && !opt_terminated) {
optind = optreset = 1;
goto again;
}
@@ -940,13 +1095,9 @@ main(int ac, char **av)
host_arg = xstrdup(host);
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
- ERR_load_crypto_strings();
-#endif
-
/* Initialize the command to execute on remote host. */
- buffer_init(&command);
+ if ((command = sshbuf_new()) == NULL)
+ fatal("sshbuf_new failed");
/*
* Save the command to execute on the remote host in a buffer. There
@@ -963,43 +1114,41 @@ main(int ac, char **av)
} else {
/* A command has been specified. Store it into the buffer. */
for (i = 0; i < ac; i++) {
- if (i)
- buffer_append(&command, " ", 1);
- buffer_append(&command, av[i], strlen(av[i]));
+ if ((r = sshbuf_putf(command, "%s%s",
+ i ? " " : "", av[i])) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
}
}
- /* Cannot fork to background if no command. */
- if (fork_after_authentication_flag && buffer_len(&command) == 0 &&
- !no_shell_flag)
- fatal("Cannot fork into background without a command "
- "to execute.");
-
/*
* Initialize "log" output. Since we are the client all output
* goes to stderr unless otherwise specified by -y or -E.
*/
if (use_syslog && logfile != NULL)
fatal("Can't specify both -y and -E");
- if (logfile != NULL) {
+ if (logfile != NULL)
log_redirect_stderr_to(logfile);
- free(logfile);
- }
log_init(argv0,
- options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
- SYSLOG_FACILITY_USER, !use_syslog);
+ options.log_level == SYSLOG_LEVEL_NOT_SET ?
+ SYSLOG_LEVEL_INFO : options.log_level,
+ options.log_facility == SYSLOG_FACILITY_NOT_SET ?
+ SYSLOG_FACILITY_USER : options.log_facility,
+ !use_syslog);
if (debug_flag)
logit("%s, %s", SSH_RELEASE,
#ifdef WITH_OPENSSL
- SSLeay_version(SSLEAY_VERSION)
+ OpenSSL_version(OPENSSL_VERSION)
#else
"without OpenSSL"
#endif
);
/* Parse the configuration files */
- process_config_files(host_arg, pw, 0);
+ process_config_files(host_arg, pw, 0, &want_final_pass);
+ if (want_final_pass)
+ debug("configuration requests final Match pass");
/* Hostname canonicalisation needs a few options filled. */
fill_default_options_for_canonicalization(&options);
@@ -1015,16 +1164,22 @@ main(int ac, char **av)
options.hostname = xstrdup(host);
}
- /* If canonicalization requested then try to apply it */
- lowercase(host);
- if (options.canonicalize_hostname != SSH_CANONICALISE_NO)
+ /* Don't lowercase addresses, they will be explicitly canonicalised */
+ if ((was_addr = is_addr(host)) == 0)
+ lowercase(host);
+
+ /*
+ * Try to canonicalize if requested by configuration or the
+ * hostname is an address.
+ */
+ if (options.canonicalize_hostname != SSH_CANONICALISE_NO || was_addr)
addrs = resolve_canonicalize(&host, options.port);
/*
* If CanonicalizePermittedCNAMEs have been specified but
* other canonicalization did not happen (by not being requested
* or by failing with fallback) then the hostname may still be changed
- * as a result of CNAME following.
+ * as a result of CNAME following.
*
* Try to resolve the bare hostname name using the system resolver's
* usual search rules and then apply the CNAME follow rules.
@@ -1033,29 +1188,34 @@ main(int ac, char **av)
* has specifically requested canonicalisation for this case via
* CanonicalizeHostname=always
*/
- if (addrs == NULL && options.num_permitted_cnames != 0 &&
- (option_clear_or_none(options.proxy_command) ||
- options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) {
+ direct = option_clear_or_none(options.proxy_command) &&
+ options.jump_host == NULL;
+ if (addrs == NULL && options.num_permitted_cnames != 0 && (direct ||
+ options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) {
if ((addrs = resolve_host(host, options.port,
- option_clear_or_none(options.proxy_command),
- cname, sizeof(cname))) == NULL) {
+ direct, cname, sizeof(cname))) == NULL) {
/* Don't fatal proxied host names not in the DNS */
- if (option_clear_or_none(options.proxy_command))
+ if (direct)
cleanup_exit(255); /* logged in resolve_host */
} else
- check_follow_cname(&host, cname);
+ check_follow_cname(direct, &host, cname);
}
/*
* If canonicalisation is enabled then re-parse the configuration
* files as new stanzas may match.
*/
- if (options.canonicalize_hostname != 0) {
- debug("Re-reading configuration after hostname "
- "canonicalisation");
+ if (options.canonicalize_hostname != 0 && !want_final_pass) {
+ debug("hostname canonicalisation enabled, "
+ "will re-parse configuration");
+ want_final_pass = 1;
+ }
+
+ if (want_final_pass) {
+ debug("re-parsing configuration");
free(options.hostname);
options.hostname = xstrdup(host);
- process_config_files(host_arg, pw, 1);
+ process_config_files(host_arg, pw, 1, NULL);
/*
* Address resolution happens early with canonicalisation
* enabled and the port number may have changed since, so
@@ -1068,9 +1228,61 @@ main(int ac, char **av)
/* Fill configuration defaults. */
fill_default_options(&options);
+ /*
+ * If ProxyJump option specified, then construct a ProxyCommand now.
+ */
+ if (options.jump_host != NULL) {
+ char port_s[8];
+ const char *sshbin = argv0;
+ 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)
+ fatal("jumphost loop via %s", options.jump_host);
+
+ /*
+ * Try to use SSH indicated by argv[0], but fall back to
+ * "ssh" if it appears unavailable.
+ */
+ if (strchr(argv0, '/') != NULL && access(argv0, X_OK) != 0)
+ sshbin = "ssh";
+
+ /* Consistency check */
+ if (options.proxy_command != NULL)
+ fatal("inconsistent options: ProxyCommand+ProxyJump");
+ /* Never use FD passing for ProxyJump */
+ options.proxy_use_fdpass = 0;
+ snprintf(port_s, sizeof(port_s), "%d", options.jump_port);
+ xasprintf(&options.proxy_command,
+ "%s%s%s%s%s%s%s%s%s%s%.*s -W '[%%h]:%%p' %s",
+ sshbin,
+ /* Optional "-l user" argument if jump_user set */
+ options.jump_user == NULL ? "" : " -l ",
+ options.jump_user == NULL ? "" : options.jump_user,
+ /* Optional "-p port" argument if jump_port set */
+ options.jump_port <= 0 ? "" : " -p ",
+ options.jump_port <= 0 ? "" : port_s,
+ /* Optional additional jump hosts ",..." */
+ options.jump_extra == NULL ? "" : " -J ",
+ options.jump_extra == NULL ? "" : options.jump_extra,
+ /* Optional "-F" argumment if -F specified */
+ config == NULL ? "" : " -F ",
+ config == NULL ? "" : config,
+ /* Optional "-v" arguments if -v set */
+ debug_flag ? " -" : "",
+ debug_flag, "vvv",
+ /* Mandatory hostname */
+ options.jump_host);
+ debug("Setting implicit ProxyCommand from ProxyJump: %s",
+ options.proxy_command);
+ }
+
if (options.port == 0)
options.port = default_ssh_port();
- channel_set_af(options.address_family);
+ channel_set_af(ssh, options.address_family);
/* Tidy and check options */
if (options.host_key_alias != NULL)
@@ -1079,30 +1291,48 @@ main(int ac, char **av)
strcmp(options.proxy_command, "-") == 0 &&
options.proxy_use_fdpass)
fatal("ProxyCommand=- and ProxyUseFDPass are incompatible");
- if (options.control_persist &&
- options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) {
- debug("UpdateHostKeys=ask is incompatible with ControlPersist; "
- "disabling");
- options.update_hostkeys = 0;
- }
-#ifndef HAVE_CYGWIN
- if (original_effective_uid != 0)
- options.use_privileged_port = 0;
-#endif
+ if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) {
+ if (options.control_persist && options.control_path != NULL) {
+ debug("UpdateHostKeys=ask is incompatible with "
+ "ControlPersist; disabling");
+ options.update_hostkeys = 0;
+ } else if (sshbuf_len(command) != 0 ||
+ options.remote_command != NULL ||
+ options.request_tty == REQUEST_TTY_NO) {
+ debug("UpdateHostKeys=ask is incompatible with "
+ "remote command execution; disabling");
+ options.update_hostkeys = 0;
+ } else if (options.log_level < SYSLOG_LEVEL_INFO) {
+ /* no point logging anything; user won't see it */
+ options.update_hostkeys = 0;
+ }
+ }
+ if (options.connection_attempts <= 0)
+ fatal("Invalid number of ConnectionAttempts");
+
+ if (sshbuf_len(command) != 0 && options.remote_command != NULL)
+ fatal("Cannot execute command-line and remote command.");
+
+ /* Cannot fork to background if no command. */
+ if (fork_after_authentication_flag && sshbuf_len(command) == 0 &&
+ options.remote_command == NULL && !no_shell_flag)
+ fatal("Cannot fork into background without a command "
+ "to execute.");
/* reinit */
- log_init(argv0, options.log_level, SYSLOG_FACILITY_USER, !use_syslog);
+ log_init(argv0, options.log_level, options.log_facility, !use_syslog);
if (options.request_tty == REQUEST_TTY_YES ||
options.request_tty == REQUEST_TTY_FORCE)
tty_flag = 1;
/* Allocate a tty by default if no command specified. */
- if (buffer_len(&command) == 0)
+ if (sshbuf_len(command) == 0 && options.remote_command == NULL)
tty_flag = options.request_tty != REQUEST_TTY_NO;
/* Force no tty */
- if (options.request_tty == REQUEST_TTY_NO || muxclient_command != 0)
+ if (options.request_tty == REQUEST_TTY_NO ||
+ (muxclient_command && muxclient_command != SSHMUX_COMMAND_PROXY))
tty_flag = 0;
/* Do not allocate a tty if stdin is not a tty. */
if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
@@ -1113,78 +1343,149 @@ main(int ac, char **av)
tty_flag = 0;
}
- seed_rng();
-
if (options.user == NULL)
options.user = xstrdup(pw->pw_name);
+ /* Set up strings used to percent_expand() arguments */
if (gethostname(thishost, sizeof(thishost)) == -1)
fatal("gethostname: %s", strerror(errno));
strlcpy(shorthost, thishost, sizeof(shorthost));
shorthost[strcspn(thishost, ".")] = '\0';
snprintf(portstr, sizeof(portstr), "%d", options.port);
+ snprintf(uidstr, sizeof(uidstr), "%llu",
+ (unsigned long long)pw->pw_uid);
- if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
- ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
- ssh_digest_update(md, host, strlen(host)) < 0 ||
- ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
- ssh_digest_update(md, options.user, strlen(options.user)) < 0 ||
- ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
- fatal("%s: mux digest failed", __func__);
- ssh_digest_free(md);
- conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
+ conn_hash_hex = ssh_connection_hash(thishost, host, portstr,
+ options.user);
- if (options.local_command != NULL) {
- debug3("expanding LocalCommand: %s", options.local_command);
- cp = options.local_command;
- options.local_command = percent_expand(cp,
- "C", conn_hash_hex,
- "L", shorthost,
- "d", pw->pw_dir,
- "h", host,
- "l", thishost,
- "n", host_arg,
- "p", portstr,
- "r", options.user,
- "u", pw->pw_name,
- (char *)NULL);
- debug3("expanded LocalCommand: %s", options.local_command);
+ /*
+ * Expand tokens in arguments. NB. LocalCommand is expanded later,
+ * after port-forwarding is set up, so it may pick up any local
+ * tunnel interface name allocated.
+ */
+ if (options.remote_command != NULL) {
+ debug3("expanding RemoteCommand: %s", options.remote_command);
+ cp = options.remote_command;
+ options.remote_command = default_client_percent_expand(cp,
+ pw->pw_dir, host, options.user, pw->pw_name);
+ debug3("expanded RemoteCommand: %s", options.remote_command);
free(cp);
+ if ((r = sshbuf_put(command, options.remote_command,
+ strlen(options.remote_command))) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
if (options.control_path != NULL) {
- cp = tilde_expand_filename(options.control_path,
- original_real_uid);
+ cp = tilde_expand_filename(options.control_path, getuid());
free(options.control_path);
- options.control_path = percent_expand(cp,
- "C", conn_hash_hex,
- "L", shorthost,
- "h", host,
- "l", thishost,
- "n", host_arg,
- "p", portstr,
- "r", options.user,
- "u", pw->pw_name,
- (char *)NULL);
+ options.control_path = default_client_percent_expand(cp,
+ pw->pw_dir, host, options.user, pw->pw_name);
free(cp);
}
- free(conn_hash_hex);
+
+ 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);
+ free(p);
+ free(options.identity_agent);
+ options.identity_agent = cp;
+ }
+
+ if (options.forward_agent_sock_path != NULL) {
+ p = tilde_expand_filename(options.forward_agent_sock_path,
+ getuid());
+ cp = default_client_percent_expand(p,
+ pw->pw_dir, host, options.user, pw->pw_name);
+ free(p);
+ free(options.forward_agent_sock_path);
+ options.forward_agent_sock_path = cp;
+ }
+
+ 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);
+ if (strcmp(cp, p) != 0)
+ debug3("expanded LocalForward listen path "
+ "'%s' -> '%s'", cp, p);
+ free(cp);
+ }
+ if (options.local_forwards[i].connect_path != NULL) {
+ cp = options.local_forwards[i].connect_path;
+ p = options.local_forwards[i].connect_path =
+ default_client_percent_expand(cp,
+ pw->pw_dir, host, options.user, pw->pw_name);
+ if (strcmp(cp, p) != 0)
+ debug3("expanded LocalForward connect path "
+ "'%s' -> '%s'", cp, p);
+ free(cp);
+ }
+ }
+
+ for (i = 0; i < options.num_remote_forwards; i++) {
+ if (options.remote_forwards[i].listen_path != NULL) {
+ cp = options.remote_forwards[i].listen_path;
+ p = options.remote_forwards[i].listen_path =
+ default_client_percent_expand(cp,
+ pw->pw_dir, host, options.user, pw->pw_name);
+ if (strcmp(cp, p) != 0)
+ debug3("expanded RemoteForward listen path "
+ "'%s' -> '%s'", cp, p);
+ free(cp);
+ }
+ if (options.remote_forwards[i].connect_path != NULL) {
+ cp = options.remote_forwards[i].connect_path;
+ p = options.remote_forwards[i].connect_path =
+ default_client_percent_expand(cp,
+ pw->pw_dir, host, options.user, pw->pw_name);
+ if (strcmp(cp, p) != 0)
+ debug3("expanded RemoteForward connect path "
+ "'%s' -> '%s'", cp, p);
+ free(cp);
+ }
+ }
if (config_test) {
dump_client_config(&options, host);
exit(0);
}
+ /* Expand SecurityKeyProvider if it refers to an environment variable */
+ if (options.sk_provider != NULL && *options.sk_provider == '$' &&
+ strlen(options.sk_provider) > 1) {
+ if ((cp = getenv(options.sk_provider + 1)) == NULL) {
+ debug("Authenticator provider %s did not resolve; "
+ "disabling", options.sk_provider);
+ free(options.sk_provider);
+ options.sk_provider = NULL;
+ } else {
+ debug2("resolved SecurityKeyProvider %s => %s",
+ options.sk_provider, cp);
+ free(options.sk_provider);
+ options.sk_provider = xstrdup(cp);
+ }
+ }
+
if (muxclient_command != 0 && options.control_path == NULL)
fatal("No ControlPath specified for \"-O\" command");
- if (options.control_path != NULL)
- muxclient(options.control_path);
+ if (options.control_path != NULL) {
+ int sock;
+ if ((sock = muxclient(options.control_path)) >= 0) {
+ ssh_packet_set_connection(ssh, sock, sock);
+ ssh_packet_set_mux(ssh);
+ goto skip_connect;
+ }
+ }
/*
* If hostname canonicalisation was not enabled, then we may not
* have yet resolved the hostname. Do so now.
*/
if (addrs == NULL && options.proxy_command == NULL) {
+ debug2("resolving \"%s\" port %d", host, options.port);
if ((addrs = resolve_host(host, options.port, 1,
cname, sizeof(cname))) == NULL)
cleanup_exit(255); /* resolve_host logs the error */
@@ -1193,114 +1494,64 @@ main(int ac, char **av)
timeout_ms = options.connection_timeout * 1000;
/* Open a connection to the remote host. */
- if (ssh_connect(host, addrs, &hostaddr, options.port,
+ if (ssh_connect(ssh, host, host_arg, addrs, &hostaddr, options.port,
options.address_family, options.connection_attempts,
- &timeout_ms, options.tcp_keep_alive,
- options.use_privileged_port) != 0)
+ &timeout_ms, options.tcp_keep_alive) != 0)
exit(255);
if (addrs != NULL)
freeaddrinfo(addrs);
- packet_set_timeout(options.server_alive_interval,
+ ssh_packet_set_timeout(ssh, options.server_alive_interval,
options.server_alive_count_max);
if (timeout_ms > 0)
debug3("timeout: %d ms remain after connect", timeout_ms);
/*
- * If we successfully made the connection, load the host private key
- * in case we will need it later for combined rsa-rhosts
- * authentication. This must be done before releasing extra
- * privileges, because the file is only readable by root.
- * If we cannot access the private keys, load the public keys
- * instead and try to execute the ssh-keysign helper instead.
+ * If we successfully made the connection and we have hostbased auth
+ * enabled, load the public keys so we can later use the ssh-keysign
+ * helper to sign challenges.
*/
sensitive_data.nkeys = 0;
sensitive_data.keys = NULL;
- sensitive_data.external_keysign = 0;
- if (options.rhosts_rsa_authentication ||
- options.hostbased_authentication) {
- sensitive_data.nkeys = 9;
+ if (options.hostbased_authentication) {
+ sensitive_data.nkeys = 10;
sensitive_data.keys = xcalloc(sensitive_data.nkeys,
- sizeof(Key));
- for (i = 0; i < sensitive_data.nkeys; i++)
- sensitive_data.keys[i] = NULL;
-
- PRIV_START;
- sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
- _PATH_HOST_KEY_FILE, "", NULL, NULL);
-#ifdef OPENSSL_HAS_ECC
- sensitive_data.keys[1] = key_load_private_cert(KEY_ECDSA,
- _PATH_HOST_ECDSA_KEY_FILE, "", NULL);
-#endif
- sensitive_data.keys[2] = key_load_private_cert(KEY_ED25519,
- _PATH_HOST_ED25519_KEY_FILE, "", NULL);
- sensitive_data.keys[3] = key_load_private_cert(KEY_RSA,
- _PATH_HOST_RSA_KEY_FILE, "", NULL);
- sensitive_data.keys[4] = key_load_private_cert(KEY_DSA,
- _PATH_HOST_DSA_KEY_FILE, "", NULL);
-#ifdef OPENSSL_HAS_ECC
- sensitive_data.keys[5] = key_load_private_type(KEY_ECDSA,
- _PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL);
-#endif
- sensitive_data.keys[6] = key_load_private_type(KEY_ED25519,
- _PATH_HOST_ED25519_KEY_FILE, "", NULL, NULL);
- sensitive_data.keys[7] = key_load_private_type(KEY_RSA,
- _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL);
- sensitive_data.keys[8] = key_load_private_type(KEY_DSA,
- _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL);
- PRIV_END;
-
- if (options.hostbased_authentication == 1 &&
- sensitive_data.keys[0] == NULL &&
- sensitive_data.keys[5] == NULL &&
- sensitive_data.keys[6] == NULL &&
- sensitive_data.keys[7] == NULL &&
- sensitive_data.keys[8] == NULL) {
-#ifdef OPENSSL_HAS_ECC
- sensitive_data.keys[1] = key_load_cert(
- _PATH_HOST_ECDSA_KEY_FILE);
-#endif
- sensitive_data.keys[2] = key_load_cert(
- _PATH_HOST_ED25519_KEY_FILE);
- sensitive_data.keys[3] = key_load_cert(
- _PATH_HOST_RSA_KEY_FILE);
- sensitive_data.keys[4] = key_load_cert(
- _PATH_HOST_DSA_KEY_FILE);
-#ifdef OPENSSL_HAS_ECC
- sensitive_data.keys[5] = key_load_public(
- _PATH_HOST_ECDSA_KEY_FILE, NULL);
-#endif
- sensitive_data.keys[6] = key_load_public(
- _PATH_HOST_ED25519_KEY_FILE, NULL);
- sensitive_data.keys[7] = key_load_public(
- _PATH_HOST_RSA_KEY_FILE, NULL);
- sensitive_data.keys[8] = key_load_public(
- _PATH_HOST_DSA_KEY_FILE, NULL);
- sensitive_data.external_keysign = 1;
+ sizeof(struct sshkey));
+
+ /* XXX check errors? */
+#define L_PUBKEY(p,o) do { \
+ if ((o) >= sensitive_data.nkeys) \
+ fatal("%s pubkey out of array bounds", __func__); \
+ check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \
+ p, "pubkey"); \
+} while (0)
+#define L_CERT(p,o) do { \
+ if ((o) >= sensitive_data.nkeys) \
+ fatal("%s cert out of array bounds", __func__); \
+ check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), p, "cert"); \
+} while (0)
+
+ if (options.hostbased_authentication == 1) {
+ L_CERT(_PATH_HOST_ECDSA_KEY_FILE, 0);
+ L_CERT(_PATH_HOST_ED25519_KEY_FILE, 1);
+ L_CERT(_PATH_HOST_RSA_KEY_FILE, 2);
+ L_CERT(_PATH_HOST_DSA_KEY_FILE, 3);
+ L_PUBKEY(_PATH_HOST_ECDSA_KEY_FILE, 4);
+ L_PUBKEY(_PATH_HOST_ED25519_KEY_FILE, 5);
+ L_PUBKEY(_PATH_HOST_RSA_KEY_FILE, 6);
+ L_PUBKEY(_PATH_HOST_DSA_KEY_FILE, 7);
+ L_CERT(_PATH_HOST_XMSS_KEY_FILE, 8);
+ L_PUBKEY(_PATH_HOST_XMSS_KEY_FILE, 9);
}
}
- /*
- * Get rid of any extra privileges that we may have. We will no
- * longer need them. Also, extra privileges could make it very hard
- * to read identity files and other non-world-readable files from the
- * user's home directory if it happens to be on a NFS volume where
- * root is mapped to nobody.
- */
- if (original_effective_uid == 0) {
- PRIV_START;
- permanently_set_uid(pw);
- }
- /*
- * Now that we are back to our own permissions, create ~/.ssh
- * directory if it doesn't already exist.
- */
+ /* Create ~/.ssh * directory if it doesn't already exist. */
if (config == NULL) {
r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir,
strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
- if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) {
+ if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) == -1) {
#ifdef WITH_SELINUX
ssh_selinux_setfscreatecon(buf);
#endif
@@ -1313,23 +1564,62 @@ main(int ac, char **av)
}
}
/* load options.identity_files */
- load_public_identity_files();
+ load_public_identity_files(pw);
+
+ /* optionally set the SSH_AUTHSOCKET_ENV_NAME variable */
+ if (options.identity_agent &&
+ strcmp(options.identity_agent, SSH_AUTHSOCKET_ENV_NAME) != 0) {
+ if (strcmp(options.identity_agent, "none") == 0) {
+ unsetenv(SSH_AUTHSOCKET_ENV_NAME);
+ } else {
+ cp = options.identity_agent;
+ if (cp[0] == '$') {
+ if (!valid_env_name(cp + 1)) {
+ fatal("Invalid IdentityAgent "
+ "environment variable name %s", cp);
+ }
+ if ((p = getenv(cp + 1)) == NULL)
+ unsetenv(SSH_AUTHSOCKET_ENV_NAME);
+ else
+ setenv(SSH_AUTHSOCKET_ENV_NAME, p, 1);
+ } else {
+ /* identity_agent specifies a path directly */
+ setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1);
+ }
+ }
+ }
+
+ if (options.forward_agent && options.forward_agent_sock_path != NULL) {
+ cp = options.forward_agent_sock_path;
+ if (cp[0] == '$') {
+ if (!valid_env_name(cp + 1)) {
+ fatal("Invalid ForwardAgent environment variable name %s", cp);
+ }
+ if ((p = getenv(cp + 1)) != NULL)
+ forward_agent_sock_path = p;
+ else
+ options.forward_agent = 0;
+ free(cp);
+ } else {
+ forward_agent_sock_path = cp;
+ }
+ }
/* Expand ~ in known host file names. */
tilde_expand_paths(options.system_hostfiles,
options.num_system_hostfiles);
tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles);
- signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
- signal(SIGCHLD, main_sigchld_handler);
+ ssh_signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
+ ssh_signal(SIGCHLD, main_sigchld_handler);
/* Log into the remote system. Never returns if the login fails. */
- ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr,
+ ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr,
options.port, pw, timeout_ms);
- if (packet_connection_is_on_socket()) {
+ if (ssh_packet_connection_is_on_socket(ssh)) {
verbose("Authenticated to %s ([%s]:%d).", host,
- get_remote_ipaddr(), get_remote_port());
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
} else {
verbose("Authenticated to %s (via proxy).", host);
}
@@ -1340,7 +1630,7 @@ main(int ac, char **av)
if (sensitive_data.keys[i] != NULL) {
/* Destroys contents safely */
debug3("clear hostkey %d", i);
- key_free(sensitive_data.keys[i]);
+ sshkey_free(sensitive_data.keys[i]);
sensitive_data.keys[i] = NULL;
}
}
@@ -1350,13 +1640,18 @@ main(int ac, char **av)
free(options.identity_files[i]);
options.identity_files[i] = NULL;
if (options.identity_keys[i]) {
- key_free(options.identity_keys[i]);
+ sshkey_free(options.identity_keys[i]);
options.identity_keys[i] = NULL;
}
}
+ for (i = 0; i < options.num_certificate_files; i++) {
+ free(options.certificate_files[i]);
+ options.certificate_files[i] = NULL;
+ }
- exit_status = compat20 ? ssh_session2() : ssh_session();
- packet_close();
+ skip_connect:
+ exit_status = ssh_session2(ssh, pw);
+ ssh_packet_close(ssh);
if (options.control_path != NULL && muxserver_sock != -1)
unlink(options.control_path);
@@ -1371,39 +1666,41 @@ static void
control_persist_detach(void)
{
pid_t pid;
- int devnull;
+ int devnull, keep_stderr;
debug("%s: backgrounding master process", __func__);
- /*
- * master (current process) into the background, and make the
- * foreground process a client of the backgrounded master.
- */
+ /*
+ * master (current process) into the background, and make the
+ * foreground process a client of the backgrounded master.
+ */
switch ((pid = fork())) {
case -1:
fatal("%s: fork: %s", __func__, strerror(errno));
case 0:
/* Child: master process continues mainloop */
- break;
- default:
+ break;
+ default:
/* Parent: set up mux slave to connect to backgrounded master */
debug2("%s: background process is %ld", __func__, (long)pid);
stdin_null_flag = ostdin_null_flag;
options.request_tty = orequest_tty;
tty_flag = otty_flag;
- close(muxserver_sock);
- muxserver_sock = -1;
+ close(muxserver_sock);
+ muxserver_sock = -1;
options.control_master = SSHCTL_MASTER_NO;
- muxclient(options.control_path);
+ muxclient(options.control_path);
/* muxclient() doesn't return on success. */
- fatal("Failed to connect to new control master");
- }
+ 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)
+ 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);
@@ -1420,15 +1717,32 @@ fork_postauth(void)
control_persist_detach();
debug("forking to background");
fork_after_authentication_flag = 0;
- if (daemon(1, 1) < 0)
+ if (daemon(1, 1) == -1)
fatal("daemon() failed: %.200s", strerror(errno));
}
+static void
+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)
+ fork_postauth();
+ } else {
+ debug2("%s: %d expected forwarding replies remaining",
+ __func__, forward_confirms_pending);
+ }
+}
+
/* Callback for remote forward global requests */
static void
-ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
+ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
{
struct Forward *rfwd = (struct Forward *)ctxt;
+ u_int port;
+ int r;
/* XXX verbose() on failure? */
debug("remote forward %s for: listen %s%s%d, connect %s:%d",
@@ -1440,17 +1754,30 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
rfwd->connect_host, rfwd->connect_port);
if (rfwd->listen_path == NULL && rfwd->listen_port == 0) {
if (type == SSH2_MSG_REQUEST_SUCCESS) {
- rfwd->allocated_port = packet_get_int();
- logit("Allocated port %u for remote forward to %s:%d",
- rfwd->allocated_port,
- rfwd->connect_host, rfwd->connect_port);
- channel_update_permitted_opens(rfwd->handle,
- rfwd->allocated_port);
+ if ((r = sshpkt_get_u32(ssh, &port)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+ if (port > 65535) {
+ error("Invalid allocated port %u for remote "
+ "forward to %s:%d", port,
+ rfwd->connect_host, rfwd->connect_port);
+ /* Ensure failure processing runs below */
+ type = SSH2_MSG_REQUEST_FAILURE;
+ channel_update_permission(ssh,
+ rfwd->handle, -1);
+ } else {
+ rfwd->allocated_port = (int)port;
+ logit("Allocated port %u for remote "
+ "forward to %s:%d",
+ rfwd->allocated_port, rfwd->connect_host,
+ rfwd->connect_port);
+ channel_update_permission(ssh,
+ rfwd->handle, rfwd->allocated_port);
+ }
} else {
- channel_update_permitted_opens(rfwd->handle, -1);
+ channel_update_permission(ssh, rfwd->handle, -1);
}
}
-
+
if (type == SSH2_MSG_REQUEST_FAILURE) {
if (options.exit_on_forward_failure) {
if (rfwd->listen_path != NULL)
@@ -1468,56 +1795,66 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
"for listen port %d", rfwd->listen_port);
}
}
- if (++remote_forward_confirms_received == options.num_remote_forwards) {
- debug("All remote forwarding requests processed");
- if (fork_after_authentication_flag)
- fork_postauth();
- }
+ forwarding_success();
}
static void
-client_cleanup_stdio_fwd(int id, void *arg)
+client_cleanup_stdio_fwd(struct ssh *ssh, int id, void *arg)
{
debug("stdio forwarding: done");
cleanup_exit(0);
}
static void
-ssh_stdio_confirm(int id, int success, void *arg)
+ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
{
if (!success)
fatal("stdio forwarding failed");
}
static void
-ssh_init_stdio_forwarding(void)
+ssh_tun_confirm(struct ssh *ssh, int id, int success, void *arg)
+{
+ if (!success) {
+ error("Tunnel forwarding failed");
+ if (options.exit_on_forward_failure)
+ cleanup_exit(255);
+ }
+
+ debug("%s: tunnel forward established, id=%d", __func__, id);
+ forwarding_success();
+}
+
+static void
+ssh_init_stdio_forwarding(struct ssh *ssh)
{
Channel *c;
int in, out;
- if (stdio_forward_host == NULL)
+ if (options.stdio_forward_host == NULL)
return;
- if (!compat20)
- fatal("stdio forwarding require Protocol 2");
- debug3("%s: %s:%d", __func__, stdio_forward_host, stdio_forward_port);
+ debug3("%s: %s:%d", __func__, options.stdio_forward_host,
+ options.stdio_forward_port);
- if ((in = dup(STDIN_FILENO)) < 0 ||
- (out = dup(STDOUT_FILENO)) < 0)
+ if ((in = dup(STDIN_FILENO)) == -1 ||
+ (out = dup(STDOUT_FILENO)) == -1)
fatal("channel_connect_stdio_fwd: dup() in/out failed");
- if ((c = channel_connect_stdio_fwd(stdio_forward_host,
- stdio_forward_port, in, out)) == NULL)
+ if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host,
+ options.stdio_forward_port, in, out)) == NULL)
fatal("%s: channel_connect_stdio_fwd failed", __func__);
- channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0);
- channel_register_open_confirm(c->self, ssh_stdio_confirm, NULL);
+ channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0);
+ channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL);
}
static void
-ssh_init_forwarding(void)
+ssh_init_forwarding(struct ssh *ssh, char **ifname)
{
int success = 0;
int i;
+ if (options.exit_on_forward_failure)
+ forward_confirms_pending = 0; /* track pending requests */
/* Initiate local TCP/IP port forwardings. */
for (i = 0; i < options.num_local_forwards; i++) {
debug("Local connections to %.200s:%d forwarded to remote "
@@ -1532,7 +1869,7 @@ ssh_init_forwarding(void)
options.local_forwards[i].connect_path :
options.local_forwards[i].connect_host,
options.local_forwards[i].connect_port);
- success += channel_setup_local_fwd_listener(
+ success += channel_setup_local_fwd_listener(ssh,
&options.local_forwards[i], &options.fwd_opts);
}
if (i > 0 && success != i && options.exit_on_forward_failure)
@@ -1553,31 +1890,34 @@ ssh_init_forwarding(void)
options.remote_forwards[i].connect_path :
options.remote_forwards[i].connect_host,
options.remote_forwards[i].connect_port);
- options.remote_forwards[i].handle =
- channel_request_remote_forwarding(
- &options.remote_forwards[i]);
- if (options.remote_forwards[i].handle < 0) {
- if (options.exit_on_forward_failure)
- fatal("Could not request remote forwarding.");
- else
- logit("Warning: Could not request remote "
- "forwarding.");
- } else {
- client_register_global_confirm(ssh_confirm_remote_forward,
+ if ((options.remote_forwards[i].handle =
+ channel_request_remote_forwarding(ssh,
+ &options.remote_forwards[i])) >= 0) {
+ client_register_global_confirm(
+ ssh_confirm_remote_forward,
&options.remote_forwards[i]);
- }
+ forward_confirms_pending++;
+ } else if (options.exit_on_forward_failure)
+ fatal("Could not request remote forwarding.");
+ else
+ logit("Warning: Could not request remote forwarding.");
}
/* Initiate tunnel forwarding. */
if (options.tun_open != SSH_TUNMODE_NO) {
- if (client_request_tun_fwd(options.tun_open,
- options.tun_local, options.tun_remote) == -1) {
- if (options.exit_on_forward_failure)
- fatal("Could not request tunnel forwarding.");
- else
- error("Could not request tunnel forwarding.");
- }
- }
+ if ((*ifname = client_request_tun_fwd(ssh,
+ options.tun_open, options.tun_local,
+ options.tun_remote, ssh_tun_confirm, NULL)) != NULL)
+ forward_confirms_pending++;
+ else if (options.exit_on_forward_failure)
+ fatal("Could not request tunnel forwarding.");
+ else
+ error("Could not request tunnel forwarding.");
+ }
+ if (forward_confirms_pending > 0) {
+ debug("%s: expecting replies for %d forwards", __func__,
+ forward_confirms_pending);
+ }
}
static void
@@ -1596,196 +1936,29 @@ check_agent_present(void)
}
}
-static int
-ssh_session(void)
-{
- int type;
- int interactive = 0;
- int have_tty = 0;
- struct winsize ws;
- char *cp;
- const char *display;
-
- /* Enable compression if requested. */
- if (options.compression) {
- debug("Requesting compression at level %d.",
- options.compression_level);
-
- if (options.compression_level < 1 ||
- options.compression_level > 9)
- fatal("Compression level must be from 1 (fast) to "
- "9 (slow, best).");
-
- /* Send the request. */
- packet_start(SSH_CMSG_REQUEST_COMPRESSION);
- packet_put_int(options.compression_level);
- packet_send();
- packet_write_wait();
- type = packet_read();
- if (type == SSH_SMSG_SUCCESS)
- packet_start_compression(options.compression_level);
- else if (type == SSH_SMSG_FAILURE)
- logit("Warning: Remote host refused compression.");
- else
- packet_disconnect("Protocol error waiting for "
- "compression response.");
- }
- /* Allocate a pseudo tty if appropriate. */
- if (tty_flag) {
- debug("Requesting pty.");
-
- /* Start the packet. */
- packet_start(SSH_CMSG_REQUEST_PTY);
-
- /* Store TERM in the packet. There is no limit on the
- length of the string. */
- cp = getenv("TERM");
- if (!cp)
- cp = "";
- packet_put_cstring(cp);
-
- /* Store window size in the packet. */
- if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
- memset(&ws, 0, sizeof(ws));
- packet_put_int((u_int)ws.ws_row);
- packet_put_int((u_int)ws.ws_col);
- packet_put_int((u_int)ws.ws_xpixel);
- packet_put_int((u_int)ws.ws_ypixel);
-
- /* Store tty modes in the packet. */
- tty_make_modes(fileno(stdin), NULL);
-
- /* Send the packet, and wait for it to leave. */
- packet_send();
- packet_write_wait();
-
- /* Read response from the server. */
- type = packet_read();
- if (type == SSH_SMSG_SUCCESS) {
- interactive = 1;
- have_tty = 1;
- } else if (type == SSH_SMSG_FAILURE)
- logit("Warning: Remote host failed or refused to "
- "allocate a pseudo tty.");
- else
- packet_disconnect("Protocol error waiting for pty "
- "request response.");
- }
- /* Request X11 forwarding if enabled and DISPLAY is set. */
- display = getenv("DISPLAY");
- if (options.forward_x11 && display != NULL) {
- char *proto, *data;
- /* Get reasonable local authentication information. */
- client_x11_get_proto(display, options.xauth_location,
- options.forward_x11_trusted,
- options.forward_x11_timeout,
- &proto, &data);
- /* Request forwarding with authentication spoofing. */
- debug("Requesting X11 forwarding with authentication "
- "spoofing.");
- x11_request_forwarding_with_spoofing(0, display, proto,
- data, 0);
- /* Read response from the server. */
- type = packet_read();
- if (type == SSH_SMSG_SUCCESS) {
- interactive = 1;
- } else if (type == SSH_SMSG_FAILURE) {
- logit("Warning: Remote host denied X11 forwarding.");
- } else {
- packet_disconnect("Protocol error waiting for X11 "
- "forwarding");
- }
- }
- /* Tell the packet module whether this is an interactive session. */
- packet_set_interactive(interactive,
- options.ip_qos_interactive, options.ip_qos_bulk);
-
- /* Request authentication agent forwarding if appropriate. */
- check_agent_present();
-
- if (options.forward_agent) {
- debug("Requesting authentication agent forwarding.");
- auth_request_forwarding();
-
- /* Read response from the server. */
- type = packet_read();
- packet_check_eom();
- if (type != SSH_SMSG_SUCCESS)
- logit("Warning: Remote host denied authentication agent forwarding.");
- }
-
- /* Initiate port forwardings. */
- ssh_init_stdio_forwarding();
- ssh_init_forwarding();
-
- /* Execute a local command */
- if (options.local_command != NULL &&
- options.permit_local_command)
- ssh_local_cmd(options.local_command);
-
- /*
- * If requested and we are not interested in replies to remote
- * forwarding requests, then let ssh continue in the background.
- */
- if (fork_after_authentication_flag) {
- if (options.exit_on_forward_failure &&
- options.num_remote_forwards > 0) {
- debug("deferring postauth fork until remote forward "
- "confirmation received");
- } else
- fork_postauth();
- }
-
- /*
- * If a command was specified on the command line, execute the
- * command now. Otherwise request the server to start a shell.
- */
- if (buffer_len(&command) > 0) {
- int len = buffer_len(&command);
- if (len > 900)
- len = 900;
- debug("Sending command: %.*s", len,
- (u_char *)buffer_ptr(&command));
- packet_start(SSH_CMSG_EXEC_CMD);
- packet_put_string(buffer_ptr(&command), buffer_len(&command));
- packet_send();
- packet_write_wait();
- } else {
- debug("Requesting shell.");
- packet_start(SSH_CMSG_EXEC_SHELL);
- packet_send();
- packet_write_wait();
- }
-
- /* Enter the interactive session. */
- return client_loop(have_tty, tty_flag ?
- options.escape_char : SSH_ESCAPECHAR_NONE, 0);
-}
-
-/* request pty/x11/agent/tcpfwd/shell for channel */
static void
-ssh_session2_setup(int id, int success, void *arg)
+ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg)
{
extern char **environ;
const char *display;
- int interactive = tty_flag;
+ int r, interactive = tty_flag;
+ char *proto = NULL, *data = NULL;
if (!success)
return; /* No need for error message, channels code sens one */
display = getenv("DISPLAY");
- if (options.forward_x11 && display != NULL) {
- char *proto, *data;
- /* Get reasonable local authentication information. */
- client_x11_get_proto(display, options.xauth_location,
- options.forward_x11_trusted,
- options.forward_x11_timeout, &proto, &data);
+ if (display == NULL && options.forward_x11)
+ debug("X11 forwarding requested but DISPLAY not set");
+ if (options.forward_x11 && client_x11_get_proto(ssh, display,
+ options.xauth_location, options.forward_x11_trusted,
+ options.forward_x11_timeout, &proto, &data) == 0) {
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication "
"spoofing.");
- x11_request_forwarding_with_spoofing(id, display, proto,
+ x11_request_forwarding_with_spoofing(ssh, id, display, proto,
data, 1);
- client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN);
+ client_expect_confirm(ssh, id, "X11 forwarding", CONFIRM_WARN);
/* XXX exit_on_forward_failure */
interactive = 1;
}
@@ -1793,21 +1966,22 @@ ssh_session2_setup(int id, int success, void *arg)
check_agent_present();
if (options.forward_agent) {
debug("Requesting authentication agent forwarding.");
- channel_request_start(id, "auth-agent-req@openssh.com", 0);
- packet_send();
+ channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0);
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
}
/* Tell the packet module whether this is an interactive session. */
- packet_set_interactive(interactive,
+ ssh_packet_set_interactive(ssh, interactive,
options.ip_qos_interactive, options.ip_qos_bulk);
- client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"),
- NULL, fileno(stdin), &command, environ);
+ client_session2_setup(ssh, id, tty_flag, subsystem_flag, getenv("TERM"),
+ NULL, fileno(stdin), command, environ);
}
/* open new channel for a session */
static int
-ssh_session2_open(void)
+ssh_session2_open(struct ssh *ssh)
{
Channel *c;
int window, packetmax, in, out, err;
@@ -1820,7 +1994,7 @@ ssh_session2_open(void)
out = dup(STDOUT_FILENO);
err = dup(STDERR_FILENO);
- if (in < 0 || out < 0 || err < 0)
+ if (in == -1 || out == -1 || err == -1)
fatal("dup() in/out/err failed");
/* enable nonblocking unless tty */
@@ -1837,35 +2011,53 @@ ssh_session2_open(void)
window >>= 1;
packetmax >>= 1;
}
- c = channel_new(
+ c = channel_new(ssh,
"session", SSH_CHANNEL_OPENING, in, out, err,
window, packetmax, CHAN_EXTENDED_WRITE,
"client-session", /*nonblock*/0);
- debug3("ssh_session2_open: channel_new: %d", c->self);
+ debug3("%s: channel_new: %d", __func__, c->self);
- channel_send_open(c->self);
+ channel_send_open(ssh, c->self);
if (!no_shell_flag)
- channel_register_open_confirm(c->self,
+ channel_register_open_confirm(ssh, c->self,
ssh_session2_setup, NULL);
return c->self;
}
static int
-ssh_session2(void)
+ssh_session2(struct ssh *ssh, struct passwd *pw)
{
- int id = -1;
+ int r, devnull, id = -1;
+ char *cp, *tun_fwd_ifname = NULL;
/* XXX should be pre-session */
if (!options.control_persist)
- ssh_init_stdio_forwarding();
- ssh_init_forwarding();
+ ssh_init_stdio_forwarding(ssh);
+
+ ssh_init_forwarding(ssh, &tun_fwd_ifname);
+
+ if (options.local_command != NULL) {
+ debug3("expanding LocalCommand: %s", options.local_command);
+ cp = options.local_command;
+ options.local_command = percent_expand(cp,
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
+ "d", pw->pw_dir,
+ "h", host,
+ "r", options.user,
+ "u", pw->pw_name,
+ "T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname,
+ (char *)NULL);
+ debug3("expanded LocalCommand: %s", options.local_command);
+ free(cp);
+ }
/* Start listening for multiplex clients */
- muxserver_listen();
+ if (!ssh_packet_get_mux(ssh))
+ muxserver_listen(ssh);
- /*
+ /*
* If we are in control persist mode and have a working mux listen
* socket, then prepare to background ourselves and have a foreground
* client attach as a control slave.
@@ -1874,29 +2066,29 @@ ssh_session2(void)
* after the connection is fully established (in particular,
* async rfwd replies have been received for ExitOnForwardFailure).
*/
- if (options.control_persist && muxserver_sock != -1) {
+ if (options.control_persist && muxserver_sock != -1) {
ostdin_null_flag = stdin_null_flag;
ono_shell_flag = no_shell_flag;
orequest_tty = options.request_tty;
otty_flag = tty_flag;
- stdin_null_flag = 1;
- no_shell_flag = 1;
- tty_flag = 0;
+ stdin_null_flag = 1;
+ no_shell_flag = 1;
+ tty_flag = 0;
if (!fork_after_authentication_flag)
need_controlpersist_detach = 1;
fork_after_authentication_flag = 1;
- }
+ }
/*
* ControlPersist mux listen socket setup failed, attempt the
* stdio forward setup that we skipped earlier.
*/
if (options.control_persist && muxserver_sock == -1)
- ssh_init_stdio_forwarding();
+ ssh_init_stdio_forwarding(ssh);
- if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
- id = ssh_session2_open();
+ if (!no_shell_flag)
+ id = ssh_session2_open(ssh);
else {
- packet_set_interactive(
+ ssh_packet_set_interactive(ssh,
options.control_master == SSHCTL_MASTER_NO,
options.ip_qos_interactive, options.ip_qos_bulk);
}
@@ -1905,10 +2097,12 @@ ssh_session2(void)
if (options.control_master == SSHCTL_MASTER_NO &&
(datafellows & SSH_NEW_OPENSSH)) {
debug("Requesting no-more-sessions@openssh.com");
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring("no-more-sessions@openssh.com");
- packet_put_char(0);
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh,
+ "no-more-sessions@openssh.com")) != 0 ||
+ (r = sshpkt_put_u8(ssh, 0)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
}
/* Execute a local command */
@@ -1917,6 +2111,22 @@ ssh_session2(void)
ssh_local_cmd(options.local_command);
/*
+ * stdout is now owned by the session channel; clobber it here
+ * so future channel closes are propagated to the local fd.
+ * NB. this can only happen after LocalCommand has completed,
+ * as it may want to write to stdout.
+ */
+ if (!need_controlpersist_detach) {
+ if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1)
+ error("%s: open %s: %s", __func__,
+ _PATH_DEVNULL, strerror(errno));
+ if (dup2(devnull, STDOUT_FILENO) == -1)
+ fatal("%s: dup2() stdout failed", __func__);
+ if (devnull > STDERR_FILENO)
+ close(devnull);
+ }
+
+ /*
* If requested and we are not interested in replies to remote
* forwarding requests, then let ssh continue in the background.
*/
@@ -1929,107 +2139,159 @@ ssh_session2(void)
fork_postauth();
}
- return client_loop(tty_flag, tty_flag ?
+ return client_loop(ssh, tty_flag, tty_flag ?
options.escape_char : SSH_ESCAPECHAR_NONE, id);
}
+/* Loads all IdentityFile and CertificateFile keys */
static void
-load_public_identity_files(void)
+load_public_identity_files(struct passwd *pw)
{
- char *filename, *cp, thishost[NI_MAXHOST];
- char *pwdir = NULL, *pwname = NULL;
- int i = 0;
- Key *public;
- struct passwd *pw;
- u_int n_ids;
+ char *filename, *cp;
+ struct sshkey *public;
+ int i;
+ u_int n_ids, n_certs;
char *identity_files[SSH_MAX_IDENTITY_FILES];
- Key *identity_keys[SSH_MAX_IDENTITY_FILES];
+ struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES];
+ int identity_file_userprovided[SSH_MAX_IDENTITY_FILES];
+ char *certificate_files[SSH_MAX_CERTIFICATE_FILES];
+ struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
+ int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES];
#ifdef ENABLE_PKCS11
- Key **keys;
+ struct sshkey **keys = NULL;
+ char **comments = NULL;
int nkeys;
#endif /* PKCS11 */
- n_ids = 0;
+ n_ids = n_certs = 0;
memset(identity_files, 0, sizeof(identity_files));
memset(identity_keys, 0, sizeof(identity_keys));
+ memset(identity_file_userprovided, 0,
+ sizeof(identity_file_userprovided));
+ memset(certificate_files, 0, sizeof(certificate_files));
+ memset(certificates, 0, sizeof(certificates));
+ memset(certificate_file_userprovided, 0,
+ sizeof(certificate_file_userprovided));
#ifdef ENABLE_PKCS11
if (options.pkcs11_provider != NULL &&
options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
(pkcs11_init(!options.batch_mode) == 0) &&
(nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,
- &keys)) > 0) {
+ &keys, &comments)) > 0) {
for (i = 0; i < nkeys; i++) {
if (n_ids >= SSH_MAX_IDENTITY_FILES) {
- key_free(keys[i]);
+ sshkey_free(keys[i]);
+ free(comments[i]);
continue;
}
identity_keys[n_ids] = keys[i];
- identity_files[n_ids] =
- xstrdup(options.pkcs11_provider); /* XXX */
+ identity_files[n_ids] = comments[i]; /* transferred */
n_ids++;
}
free(keys);
+ free(comments);
}
#endif /* ENABLE_PKCS11 */
- if ((pw = getpwuid(original_real_uid)) == NULL)
- fatal("load_public_identity_files: getpwuid failed");
- pwname = xstrdup(pw->pw_name);
- pwdir = xstrdup(pw->pw_dir);
- if (gethostname(thishost, sizeof(thishost)) == -1)
- fatal("load_public_identity_files: gethostname: %s",
- strerror(errno));
for (i = 0; i < options.num_identity_files; i++) {
if (n_ids >= SSH_MAX_IDENTITY_FILES ||
strcasecmp(options.identity_files[i], "none") == 0) {
free(options.identity_files[i]);
+ options.identity_files[i] = NULL;
continue;
}
- cp = tilde_expand_filename(options.identity_files[i],
- original_real_uid);
- filename = percent_expand(cp, "d", pwdir,
- "u", pwname, "l", thishost, "h", host,
- "r", options.user, (char *)NULL);
+ cp = tilde_expand_filename(options.identity_files[i], getuid());
+ filename = default_client_percent_expand(cp,
+ pw->pw_dir, host, options.user, pw->pw_name);
free(cp);
- public = key_load_public(filename, NULL);
+ check_load(sshkey_load_public(filename, &public, NULL),
+ filename, "pubkey");
debug("identity file %s type %d", filename,
public ? public->type : -1);
free(options.identity_files[i]);
identity_files[n_ids] = filename;
identity_keys[n_ids] = public;
-
+ identity_file_userprovided[n_ids] =
+ options.identity_file_userprovided[i];
if (++n_ids >= SSH_MAX_IDENTITY_FILES)
continue;
- /* Try to add the certificate variant too */
+ /*
+ * If no certificates have been explicitly listed then try
+ * to add the default certificate variant too.
+ */
+ if (options.num_certificate_files != 0)
+ continue;
xasprintf(&cp, "%s-cert", filename);
- public = key_load_public(cp, NULL);
+ check_load(sshkey_load_public(cp, &public, NULL),
+ filename, "pubkey");
debug("identity file %s type %d", cp,
public ? public->type : -1);
if (public == NULL) {
free(cp);
continue;
}
- if (!key_is_cert(public)) {
+ if (!sshkey_is_cert(public)) {
debug("%s: key %s type %s is not a certificate",
- __func__, cp, key_type(public));
- key_free(public);
+ __func__, cp, sshkey_type(public));
+ sshkey_free(public);
free(cp);
continue;
}
- identity_keys[n_ids] = public;
- /* point to the original path, most likely the private key */
+ /* NB. leave filename pointing to private key */
identity_files[n_ids] = xstrdup(filename);
+ identity_keys[n_ids] = public;
+ identity_file_userprovided[n_ids] =
+ options.identity_file_userprovided[i];
n_ids++;
}
+
+ if (options.num_certificate_files > SSH_MAX_CERTIFICATE_FILES)
+ fatal("%s: too many certificates", __func__);
+ for (i = 0; i < options.num_certificate_files; i++) {
+ cp = tilde_expand_filename(options.certificate_files[i],
+ getuid());
+ filename = default_client_percent_expand(cp,
+ pw->pw_dir, host, options.user, pw->pw_name);
+ free(cp);
+
+ check_load(sshkey_load_public(filename, &public, NULL),
+ filename, "certificate");
+ debug("certificate file %s type %d", filename,
+ public ? public->type : -1);
+ free(options.certificate_files[i]);
+ options.certificate_files[i] = NULL;
+ if (public == NULL) {
+ free(filename);
+ continue;
+ }
+ if (!sshkey_is_cert(public)) {
+ debug("%s: key %s type %s is not a certificate",
+ __func__, filename, sshkey_type(public));
+ sshkey_free(public);
+ free(filename);
+ continue;
+ }
+ certificate_files[n_certs] = filename;
+ certificates[n_certs] = public;
+ certificate_file_userprovided[n_certs] =
+ options.certificate_file_userprovided[i];
+ ++n_certs;
+ }
+
options.num_identity_files = n_ids;
memcpy(options.identity_files, identity_files, sizeof(identity_files));
memcpy(options.identity_keys, identity_keys, sizeof(identity_keys));
-
- explicit_bzero(pwname, strlen(pwname));
- free(pwname);
- explicit_bzero(pwdir, strlen(pwdir));
- free(pwdir);
+ memcpy(options.identity_file_userprovided,
+ identity_file_userprovided, sizeof(identity_file_userprovided));
+
+ options.num_certificate_files = n_certs;
+ memcpy(options.certificate_files,
+ certificate_files, sizeof(certificate_files));
+ memcpy(options.certificates, certificates, sizeof(certificates));
+ memcpy(options.certificate_file_userprovided,
+ certificate_file_userprovided,
+ sizeof(certificate_file_userprovided));
}
static void
@@ -2040,9 +2302,7 @@ main_sigchld_handler(int sig)
int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
- (pid < 0 && errno == EINTR))
+ (pid == -1 && errno == EINTR))
;
-
- signal(sig, main_sigchld_handler);
errno = save_errno;
}
diff --git a/ssh.h b/ssh.h
index c94633bd..dda6f617 100644
--- a/ssh.h
+++ b/ssh.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.h,v 1.79 2010/06/25 07:14:46 djm Exp $ */
+/* $OpenBSD: ssh.h,v 1.89 2018/12/27 03:25:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -19,17 +19,16 @@
#define SSH_DEFAULT_PORT 22
/*
- * Maximum number of RSA authentication identity files that can be specified
+ * Maximum number of certificate files that can be specified
* in configuration files or on the command line.
*/
-#define SSH_MAX_IDENTITY_FILES 100
+#define SSH_MAX_CERTIFICATE_FILES 100
/*
- * Maximum length of lines in authorized_keys file.
- * Current value permits 16kbit RSA and RSA1 keys and 8kbit DSA keys, with
- * some room for options and comments.
+ * Maximum number of RSA authentication identity files that can be specified
+ * in configuration files or on the command line.
*/
-#define SSH_MAX_PUBKEY_BYTES 8192
+#define SSH_MAX_IDENTITY_FILES 100
/*
* Major protocol version. Different version indicates major incompatibility
@@ -41,7 +40,7 @@
#define PROTOCOL_MAJOR_1 1
#define PROTOCOL_MINOR_1 5
-/* We support both SSH1 and SSH2 */
+/* We support only SSH2 */
#define PROTOCOL_MAJOR_2 2
#define PROTOCOL_MINOR_2 0
@@ -92,8 +91,9 @@
#define SSH_PRIVSEP_USER "sshd"
#endif
-/* Minimum modulus size (n) for RSA keys. */
-#define SSH_RSA_MINIMUM_MODULUS_SIZE 768
-
/* Listen backlog for sshd, ssh-agent and forwarding sockets */
#define SSH_LISTEN_BACKLOG 128
+
+/* Limits for banner exchange */
+#define SSH_MAX_BANNER_LEN 8192
+#define SSH_MAX_PRE_BANNER_LINES 1024
diff --git a/ssh1.h b/ssh1.h
deleted file mode 100644
index 353d9304..00000000
--- a/ssh1.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* $OpenBSD: ssh1.h,v 1.6 2006/03/25 22:22:43 djm Exp $ */
-
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-
-/*
- * Definition of message types. New values can be added, but old values
- * should not be removed or without careful consideration of the consequences
- * for compatibility. The maximum value is 254; value 255 is reserved for
- * future extension.
- */
-/* Ranges */
-#define SSH_MSG_MIN 1
-#define SSH_MSG_MAX 254
-/* Message name */ /* msg code */ /* arguments */
-#define SSH_MSG_NONE 0 /* no message */
-#define SSH_MSG_DISCONNECT 1 /* cause (string) */
-#define SSH_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
-#define SSH_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
-#define SSH_CMSG_USER 4 /* user (string) */
-#define SSH_CMSG_AUTH_RHOSTS 5 /* user (string) */
-#define SSH_CMSG_AUTH_RSA 6 /* modulus (BIGNUM) */
-#define SSH_SMSG_AUTH_RSA_CHALLENGE 7 /* int (BIGNUM) */
-#define SSH_CMSG_AUTH_RSA_RESPONSE 8 /* int (BIGNUM) */
-#define SSH_CMSG_AUTH_PASSWORD 9 /* pass (string) */
-#define SSH_CMSG_REQUEST_PTY 10 /* TERM, tty modes */
-#define SSH_CMSG_WINDOW_SIZE 11 /* row,col,xpix,ypix */
-#define SSH_CMSG_EXEC_SHELL 12 /* */
-#define SSH_CMSG_EXEC_CMD 13 /* cmd (string) */
-#define SSH_SMSG_SUCCESS 14 /* */
-#define SSH_SMSG_FAILURE 15 /* */
-#define SSH_CMSG_STDIN_DATA 16 /* data (string) */
-#define SSH_SMSG_STDOUT_DATA 17 /* data (string) */
-#define SSH_SMSG_STDERR_DATA 18 /* data (string) */
-#define SSH_CMSG_EOF 19 /* */
-#define SSH_SMSG_EXITSTATUS 20 /* status (int) */
-#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21 /* channel (int) */
-#define SSH_MSG_CHANNEL_OPEN_FAILURE 22 /* channel (int) */
-#define SSH_MSG_CHANNEL_DATA 23 /* ch,data (int,str) */
-#define SSH_MSG_CHANNEL_CLOSE 24 /* channel (int) */
-#define SSH_MSG_CHANNEL_CLOSE_CONFIRMATION 25 /* channel (int) */
-/* SSH_CMSG_X11_REQUEST_FORWARDING 26 OBSOLETE */
-#define SSH_SMSG_X11_OPEN 27 /* channel (int) */
-#define SSH_CMSG_PORT_FORWARD_REQUEST 28 /* p,host,hp (i,s,i) */
-#define SSH_MSG_PORT_OPEN 29 /* ch,h,p (i,s,i) */
-#define SSH_CMSG_AGENT_REQUEST_FORWARDING 30 /* */
-#define SSH_SMSG_AGENT_OPEN 31 /* port (int) */
-#define SSH_MSG_IGNORE 32 /* string */
-#define SSH_CMSG_EXIT_CONFIRMATION 33 /* */
-#define SSH_CMSG_X11_REQUEST_FORWARDING 34 /* proto,data (s,s) */
-#define SSH_CMSG_AUTH_RHOSTS_RSA 35 /* user,mod (s,mpi) */
-#define SSH_MSG_DEBUG 36 /* string */
-#define SSH_CMSG_REQUEST_COMPRESSION 37 /* level 1-9 (int) */
-#define SSH_CMSG_MAX_PACKET_SIZE 38 /* size 4k-1024k (int) */
-#define SSH_CMSG_AUTH_TIS 39 /* we use this for s/key */
-#define SSH_SMSG_AUTH_TIS_CHALLENGE 40 /* challenge (string) */
-#define SSH_CMSG_AUTH_TIS_RESPONSE 41 /* response (string) */
-#define SSH_CMSG_AUTH_KERBEROS 42 /* (KTEXT) */
-#define SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 /* (KTEXT) */
-#define SSH_CMSG_HAVE_KERBEROS_TGT 44 /* credentials (s) */
-#define SSH_CMSG_HAVE_AFS_TOKEN 65 /* token (s) */
-
-/* protocol version 1.5 overloads some version 1.3 message types */
-#define SSH_MSG_CHANNEL_INPUT_EOF SSH_MSG_CHANNEL_CLOSE
-#define SSH_MSG_CHANNEL_OUTPUT_CLOSE SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
-
-/*
- * Authentication methods. New types can be added, but old types should not
- * be removed for compatibility. The maximum allowed value is 31.
- */
-#define SSH_AUTH_RHOSTS 1
-#define SSH_AUTH_RSA 2
-#define SSH_AUTH_PASSWORD 3
-#define SSH_AUTH_RHOSTS_RSA 4
-#define SSH_AUTH_TIS 5
-#define SSH_AUTH_KERBEROS 6
-#define SSH_PASS_KERBEROS_TGT 7
- /* 8 to 15 are reserved */
-#define SSH_PASS_AFS_TOKEN 21
-
-/* Protocol flags. These are bit masks. */
-#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes screen */
-#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain host */
diff --git a/ssh2.h b/ssh2.h
index 59417e61..f2e37c96 100644
--- a/ssh2.h
+++ b/ssh2.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh2.h,v 1.15 2014/01/29 06:18:35 djm Exp $ */
+/* $OpenBSD: ssh2.h,v 1.18 2016/05/04 14:22:33 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -55,6 +55,10 @@
* 192-255 Local extensions
*/
+/* special marker for no message */
+
+#define SSH_MSG_NONE 0
+
/* ranges */
#define SSH2_MSG_TRANSPORT_MIN 1
@@ -80,6 +84,7 @@
#define SSH2_MSG_DEBUG 4
#define SSH2_MSG_SERVICE_REQUEST 5
#define SSH2_MSG_SERVICE_ACCEPT 6
+#define SSH2_MSG_EXT_INFO 7
/* transport layer: alg negotiation */
@@ -164,13 +169,6 @@
#define SSH2_EXTENDED_DATA_STDERR 1
-/* kex messages for resume@appgate.com */
-#define SSH2_MSG_KEX_ROAMING_RESUME 30
-#define SSH2_MSG_KEX_ROAMING_AUTH_REQUIRED 31
-#define SSH2_MSG_KEX_ROAMING_AUTH 32
-#define SSH2_MSG_KEX_ROAMING_AUTH_OK 33
-#define SSH2_MSG_KEX_ROAMING_AUTH_FAIL 34
-
/* Certificate types for OpenSSH certificate keys extension */
#define SSH2_CERT_TYPE_USER 1
#define SSH2_CERT_TYPE_HOST 2
diff --git a/ssh_api.c b/ssh_api.c
index 6c712584..e0b19552 100644
--- a/ssh_api.c
+++ b/ssh_api.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh_api.c,v 1.4 2015/02/16 22:13:32 djm Exp $ */
+/* $OpenBSD: ssh_api.c,v 1.19 2019/10/31 21:23:19 djm Exp $ */
/*
* Copyright (c) 2012 Markus Friedl. All rights reserved.
*
@@ -17,31 +17,36 @@
#include "includes.h"
-#include "ssh1.h" /* For SSH_MSG_NONE */
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
#include "ssh_api.h"
#include "compat.h"
#include "log.h"
#include "authfile.h"
#include "sshkey.h"
#include "misc.h"
-#include "ssh1.h"
#include "ssh2.h"
#include "version.h"
#include "myproposal.h"
#include "ssherr.h"
#include "sshbuf.h"
+#include "openbsd-compat/openssl-compat.h"
+
#include <string.h>
int _ssh_exchange_banner(struct ssh *);
-int _ssh_send_banner(struct ssh *, char **);
-int _ssh_read_banner(struct ssh *, char **);
+int _ssh_send_banner(struct ssh *, struct sshbuf *);
+int _ssh_read_banner(struct ssh *, struct sshbuf *);
int _ssh_order_hostkeyalgs(struct ssh *);
int _ssh_verify_host_key(struct sshkey *, struct ssh *);
struct sshkey *_ssh_host_public_key(int, int, struct ssh *);
struct sshkey *_ssh_host_private_key(int, int, struct ssh *);
-int _ssh_host_key_sign(struct sshkey *, struct sshkey *, u_char **,
- size_t *, const u_char *, size_t, u_int);
+int _ssh_host_key_sign(struct ssh *, struct sshkey *, struct sshkey *,
+ u_char **, size_t *, const u_char *, size_t, const char *);
/*
* stubs for the server side implementation of kex.
@@ -49,8 +54,11 @@ int _ssh_host_key_sign(struct sshkey *, struct sshkey *, u_char **,
*/
int use_privsep = 0;
int mm_sshkey_sign(struct sshkey *, u_char **, u_int *,
- u_char *, u_int, u_int);
+ const u_char *, u_int, 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;
@@ -58,16 +66,19 @@ u_int session_id2_len = 0;
int
mm_sshkey_sign(struct sshkey *key, u_char **sigp, u_int *lenp,
- u_char *data, u_int datalen, u_int compat)
+ const u_char *data, u_int datalen, const char *alg, const char *sk_provider,
+ u_int compat)
{
return (-1);
}
+#ifdef WITH_OPENSSL
DH *
mm_choose_dh(int min, int nbits, int max)
{
return (NULL);
}
+#endif
/* API */
@@ -81,9 +92,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
int r;
if (!called) {
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
-#endif /* WITH_OPENSSL */
+ seed_rng();
called = 1;
}
@@ -94,36 +103,44 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
/* Initialize key exchange */
proposal = kex_params ? kex_params->proposal : myproposal;
- if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) {
+ if ((r = kex_ready(ssh, proposal)) != 0) {
ssh_free(ssh);
return r;
}
ssh->kex->server = is_server;
if (is_server) {
#ifdef WITH_OPENSSL
- ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
- ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
+ ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
+ ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
+ ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
+ ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
+ ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
# ifdef OPENSSL_HAS_ECC
- ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+ ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
# endif
#endif /* WITH_OPENSSL */
- ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_server;
+ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_server;
+ ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
ssh->kex->load_host_public_key=&_ssh_host_public_key;
ssh->kex->load_host_private_key=&_ssh_host_private_key;
ssh->kex->sign=&_ssh_host_key_sign;
} else {
#ifdef WITH_OPENSSL
- ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
- ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
+ ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client;
ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
# ifdef OPENSSL_HAS_ECC
- ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
+ ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client;
# endif
#endif /* WITH_OPENSSL */
- ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client;
+ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
+ ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
ssh->kex->verify_host_key =&_ssh_verify_host_key;
}
*sshp = ssh;
@@ -232,8 +249,8 @@ ssh_packet_next(struct ssh *ssh, u_char *typep)
* enough data.
*/
*typep = SSH_MSG_NONE;
- if (ssh->kex->client_version_string == NULL ||
- ssh->kex->server_version_string == NULL)
+ if (sshbuf_len(ssh->kex->client_version) == 0 ||
+ sshbuf_len(ssh->kex->server_version) == 0)
return _ssh_exchange_banner(ssh);
/*
* If we enough data and a dispatch function then
@@ -308,39 +325,44 @@ ssh_input_space(struct ssh *ssh, size_t len)
/* Read other side's version identification. */
int
-_ssh_read_banner(struct ssh *ssh, char **bannerp)
+_ssh_read_banner(struct ssh *ssh, struct sshbuf *banner)
{
- struct sshbuf *input;
- const char *s;
- char buf[256], remote_version[256]; /* must be same size! */
+ struct sshbuf *input = ssh_packet_get_input(ssh);
const char *mismatch = "Protocol mismatch.\r\n";
- int r, remote_major, remote_minor;
- size_t i, n, j, len;
+ const u_char *s = sshbuf_ptr(input);
+ u_char c;
+ char *cp = NULL, *remote_version = NULL;
+ int r = 0, remote_major, remote_minor, expect_nl;
+ size_t n, j;
- *bannerp = NULL;
- input = ssh_packet_get_input(ssh);
- len = sshbuf_len(input);
- s = (const char *)sshbuf_ptr(input);
for (j = n = 0;;) {
- for (i = 0; i < sizeof(buf) - 1; i++) {
- if (j >= len)
- return (0);
- buf[i] = s[j++];
- if (buf[i] == '\r') {
- buf[i] = '\n';
- buf[i + 1] = 0;
- continue; /**XXX wait for \n */
+ sshbuf_reset(banner);
+ expect_nl = 0;
+ for (;;) {
+ if (j >= sshbuf_len(input))
+ return 0; /* insufficient data in input buf */
+ c = s[j++];
+ if (c == '\r') {
+ expect_nl = 1;
+ continue;
}
- if (buf[i] == '\n') {
- buf[i + 1] = 0;
+ if (c == '\n')
break;
- }
+ if (expect_nl)
+ goto bad;
+ if ((r = sshbuf_put_u8(banner, c)) != 0)
+ return r;
+ if (sshbuf_len(banner) > SSH_MAX_BANNER_LEN)
+ goto bad;
}
- buf[sizeof(buf) - 1] = 0;
- if (strncmp(buf, "SSH-", 4) == 0)
+ if (sshbuf_len(banner) >= 4 &&
+ memcmp(sshbuf_ptr(banner), "SSH-", 4) == 0)
break;
- debug("ssh_exchange_identification: %s", buf);
- if (ssh->kex->server || ++n > 65536) {
+ debug("%s: %.*s", __func__, (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)
return r;
@@ -350,13 +372,22 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp)
if ((r = sshbuf_consume(input, j)) != 0)
return r;
+ /* XXX remote version must be the same size as banner for sscanf */
+ if ((cp = sshbuf_dup_string(banner)) == NULL ||
+ (remote_version = calloc(1, sshbuf_len(banner))) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
/*
* Check that the versions match. In future this might accept
* several versions and set appropriate flags to handle them.
*/
- if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
- &remote_major, &remote_minor, remote_version) != 3)
- return SSH_ERR_INVALID_FORMAT;
+ if (sscanf(cp, "SSH-%d.%d-%[^\n]\n",
+ &remote_major, &remote_minor, remote_version) != 3) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
debug("Remote protocol version %d.%d, remote software version %.100s",
remote_major, remote_minor, remote_version);
@@ -366,29 +397,33 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp)
remote_minor = 0;
}
if (remote_major != 2)
- return SSH_ERR_PROTOCOL_MISMATCH;
- enable_compat20();
- chop(buf);
- debug("Remote version string %.100s", buf);
- if ((*bannerp = strdup(buf)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- return 0;
+ r = SSH_ERR_PROTOCOL_MISMATCH;
+
+ debug("Remote version string %.100s", cp);
+ out:
+ free(cp);
+ free(remote_version);
+ return r;
}
/* Send our own protocol version identification. */
int
-_ssh_send_banner(struct ssh *ssh, char **bannerp)
+_ssh_send_banner(struct ssh *ssh, struct sshbuf *banner)
{
- char buf[256];
+ char *cp;
int r;
- snprintf(buf, sizeof buf, "SSH-2.0-%.100s\r\n", SSH_VERSION);
- if ((r = sshbuf_put(ssh_packet_get_output(ssh), buf, strlen(buf))) != 0)
+ if ((r = sshbuf_putf(banner, "SSH-2.0-%.100s\r\n", SSH_VERSION)) != 0)
+ return r;
+ if ((r = sshbuf_putb(ssh_packet_get_output(ssh), banner)) != 0)
+ return r;
+ /* Remove trailing \r\n */
+ if ((r = sshbuf_consume_end(banner, 2)) != 0)
return r;
- chop(buf);
- debug("Local version string %.100s", buf);
- if ((*bannerp = strdup(buf)) == NULL)
+ if ((cp = sshbuf_dup_string(banner)) == NULL)
return SSH_ERR_ALLOC_FAIL;
+ debug("Local version string %.100s", cp);
+ free(cp);
return 0;
}
@@ -405,25 +440,25 @@ _ssh_exchange_banner(struct ssh *ssh)
r = 0;
if (kex->server) {
- if (kex->server_version_string == NULL)
- r = _ssh_send_banner(ssh, &kex->server_version_string);
+ if (sshbuf_len(ssh->kex->server_version) == 0)
+ r = _ssh_send_banner(ssh, ssh->kex->server_version);
if (r == 0 &&
- kex->server_version_string != NULL &&
- kex->client_version_string == NULL)
- r = _ssh_read_banner(ssh, &kex->client_version_string);
+ sshbuf_len(ssh->kex->server_version) != 0 &&
+ sshbuf_len(ssh->kex->client_version) == 0)
+ r = _ssh_read_banner(ssh, ssh->kex->client_version);
} else {
- if (kex->server_version_string == NULL)
- r = _ssh_read_banner(ssh, &kex->server_version_string);
+ if (sshbuf_len(ssh->kex->server_version) == 0)
+ r = _ssh_read_banner(ssh, ssh->kex->server_version);
if (r == 0 &&
- kex->server_version_string != NULL &&
- kex->client_version_string == NULL)
- r = _ssh_send_banner(ssh, &kex->client_version_string);
+ sshbuf_len(ssh->kex->server_version) != 0 &&
+ sshbuf_len(ssh->kex->client_version) == 0)
+ r = _ssh_send_banner(ssh, ssh->kex->client_version);
}
if (r != 0)
return r;
/* start initial kex as soon as we have exchanged the banners */
- if (kex->server_version_string != NULL &&
- kex->client_version_string != NULL) {
+ if (sshbuf_len(ssh->kex->server_version) != 0 &&
+ sshbuf_len(ssh->kex->client_version) != 0) {
if ((r = _ssh_order_hostkeyalgs(ssh)) != 0 ||
(r = kex_send_kexinit(ssh)) != 0)
return r;
@@ -529,9 +564,10 @@ _ssh_order_hostkeyalgs(struct ssh *ssh)
}
int
-_ssh_host_key_sign(struct sshkey *privkey, struct sshkey *pubkey,
- u_char **signature, size_t *slen,
- const u_char *data, size_t dlen, u_int compat)
+_ssh_host_key_sign(struct ssh *ssh, struct sshkey *privkey,
+ struct sshkey *pubkey, u_char **signature, size_t *slen,
+ const u_char *data, size_t dlen, const char *alg)
{
- return sshkey_sign(privkey, signature, slen, data, dlen, compat);
+ return sshkey_sign(privkey, signature, slen, data, dlen,
+ alg, NULL, ssh->compat);
}
diff --git a/ssh_api.h b/ssh_api.h
index 642acd5b..584f896a 100644
--- a/ssh_api.h
+++ b/ssh_api.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh_api.h,v 1.1 2015/01/19 20:30:23 markus Exp $ */
+/* $OpenBSD: ssh_api.h,v 1.2 2018/04/10 00:10:49 djm Exp $ */
/*
* Copyright (c) 2012 Markus Friedl. All rights reserved.
*
@@ -81,7 +81,7 @@ int ssh_set_verify_host_key_callback(struct ssh *ssh,
* ssh_packet_next() sets typep if there is no new packet available.
* in this case the caller must fill the input byte-stream by passing
* the data received over network to ssh_input_append().
- * additinally, the caller needs to send the resulting output
+ * additionally, the caller needs to send the resulting output
* byte-stream back over the network. otherwise the key exchange
* would not proceed. the output byte-stream is accessed through
* ssh_output_ptr().
diff --git a/ssh_config b/ssh_config
index 03a228fb..5e8ef548 100644
--- a/ssh_config
+++ b/ssh_config
@@ -1,4 +1,4 @@
-# $OpenBSD: ssh_config,v 1.28 2013/09/16 11:35:43 sthen Exp $
+# $OpenBSD: ssh_config,v 1.34 2019/02/04 02:39:42 dtucker Exp $
# This is the ssh client system-wide configuration file. See
# ssh_config(5) for more information. This file provides defaults for
@@ -20,8 +20,6 @@
# Host *
# ForwardAgent no
# ForwardX11 no
-# RhostsRSAAuthentication no
-# RSAAuthentication yes
# PasswordAuthentication yes
# HostbasedAuthentication no
# GSSAPIAuthentication no
@@ -31,14 +29,13 @@
# AddressFamily any
# ConnectTimeout 0
# StrictHostKeyChecking ask
-# IdentityFile ~/.ssh/identity
# IdentityFile ~/.ssh/id_rsa
# IdentityFile ~/.ssh/id_dsa
+# IdentityFile ~/.ssh/id_ecdsa
+# IdentityFile ~/.ssh/id_ed25519
# Port 22
-# Protocol 2,1
-# Cipher 3des
-# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc
-# MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160
+# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
+# MACs hmac-md5,hmac-sha1,umac-64@openssh.com
# EscapeChar ~
# Tunnel no
# TunnelDevice any:any
diff --git a/ssh_config.0 b/ssh_config.0
deleted file mode 100644
index 3bdd7523..00000000
--- a/ssh_config.0
+++ /dev/null
@@ -1,981 +0,0 @@
-SSH_CONFIG(5) File Formats Manual SSH_CONFIG(5)
-
-NAME
- ssh_config M-bM-^@M-^S OpenSSH SSH client configuration files
-
-SYNOPSIS
- ~/.ssh/config
- /etc/ssh/ssh_config
-
-DESCRIPTION
- ssh(1) obtains configuration data from the following sources in the
- following order:
-
- 1. command-line options
- 2. user's configuration file (~/.ssh/config)
- 3. system-wide configuration file (/etc/ssh/ssh_config)
-
- For each parameter, the first obtained value will be used. The
- configuration files contain sections separated by M-bM-^@M-^\HostM-bM-^@M-^] specifications,
- and that section is only applied for hosts that match one of the patterns
- given in the specification. The matched host name is usually the one
- given on the command line (see the CanonicalizeHostname option for
- exceptions.)
-
- Since the first obtained value for each parameter is used, more host-
- specific declarations should be given near the beginning of the file, and
- general defaults at the end.
-
- The configuration file has the following format:
-
- Empty lines and lines starting with M-bM-^@M-^X#M-bM-^@M-^Y are comments. Otherwise a line
- is of the format M-bM-^@M-^\keyword argumentsM-bM-^@M-^]. Configuration options may be
- separated by whitespace or optional whitespace and exactly one M-bM-^@M-^X=M-bM-^@M-^Y; the
- latter format is useful to avoid the need to quote whitespace when
- specifying configuration options using the ssh, scp, and sftp -o option.
- Arguments may optionally be enclosed in double quotes (") in order to
- represent arguments containing spaces.
-
- The possible keywords and their meanings are as follows (note that
- keywords are case-insensitive and arguments are case-sensitive):
-
- Host Restricts the following declarations (up to the next Host or
- Match keyword) to be only for those hosts that match one of the
- patterns given after the keyword. If more than one pattern is
- provided, they should be separated by whitespace. A single M-bM-^@M-^X*M-bM-^@M-^Y
- as a pattern can be used to provide global defaults for all
- hosts. The host is usually the hostname argument given on the
- command line (see the CanonicalizeHostname option for
- exceptions.)
-
- A pattern entry may be negated by prefixing it with an
- exclamation mark (M-bM-^@M-^X!M-bM-^@M-^Y). If a negated entry is matched, then the
- Host entry is ignored, regardless of whether any other patterns
- on the line match. Negated matches are therefore useful to
- provide exceptions for wildcard matches.
-
- See PATTERNS for more information on patterns.
-
- Match Restricts the following declarations (up to the next Host or
- Match keyword) to be used only when the conditions following the
- Match keyword are satisfied. Match conditions are specified
- using one or more critera or the single token all which always
- matches. The available criteria keywords are: canonical, exec,
- host, originalhost, user, and localuser. The all criteria must
- appear alone or immediately after canonical. Other criteria may
- be combined arbitrarily. All criteria but all and canonical
- require an argument. Criteria may be negated by prepending an
- exclamation mark (M-bM-^@M-^X!M-bM-^@M-^Y).
-
- The canonical keywork matches only when the configuration file is
- being re-parsed after hostname canonicalization (see the
- CanonicalizeHostname option.) This may be useful to specify
- conditions that work with canonical host names only. The exec
- keyword executes the specified command under the user's shell.
- If the command returns a zero exit status then the condition is
- considered true. Commands containing whitespace characters must
- be quoted. The following character sequences in the command will
- be expanded prior to execution: M-bM-^@M-^X%LM-bM-^@M-^Y will be substituted by the
- first component of the local host name, M-bM-^@M-^X%lM-bM-^@M-^Y will be substituted
- by the local host name (including any domain name), M-bM-^@M-^X%hM-bM-^@M-^Y will be
- substituted by the target host name, M-bM-^@M-^X%nM-bM-^@M-^Y will be substituted by
- the original target host name specified on the command-line, M-bM-^@M-^X%pM-bM-^@M-^Y
- the destination port, M-bM-^@M-^X%rM-bM-^@M-^Y by the remote login username, and M-bM-^@M-^X%uM-bM-^@M-^Y
- by the username of the user running ssh(1).
-
- The other keywords' criteria must be single entries or comma-
- separated lists and may use the wildcard and negation operators
- described in the PATTERNS section. The criteria for the host
- keyword are matched against the target hostname, after any
- substitution by the Hostname or CanonicalizeHostname options.
- The originalhost keyword matches against the hostname as it was
- specified on the command-line. The user keyword matches against
- the target username on the remote host. The localuser keyword
- matches against the name of the local user running ssh(1) (this
- keyword may be useful in system-wide ssh_config files).
-
- AddressFamily
- Specifies which address family to use when connecting. Valid
- arguments are M-bM-^@M-^\anyM-bM-^@M-^], M-bM-^@M-^\inetM-bM-^@M-^] (use IPv4 only), or M-bM-^@M-^\inet6M-bM-^@M-^] (use IPv6
- only).
-
- BatchMode
- If set to M-bM-^@M-^\yesM-bM-^@M-^], passphrase/password querying will be disabled.
- This option is useful in scripts and other batch jobs where no
- user is present to supply the password. The argument must be
- M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- BindAddress
- Use the specified address on the local machine as the source
- address of the connection. Only useful on systems with more than
- one address. Note that this option does not work if
- UsePrivilegedPort is set to M-bM-^@M-^\yesM-bM-^@M-^].
-
- CanonicalDomains
- When CanonicalizeHostname is enabled, this option specifies the
- list of domain suffixes in which to search for the specified
- destination host.
-
- CanonicalizeFallbackLocal
- Specifies whether to fail with an error when hostname
- canonicalization fails. The default, M-bM-^@M-^\yesM-bM-^@M-^], will attempt to look
- up the unqualified hostname using the system resolver's search
- rules. A value of M-bM-^@M-^\noM-bM-^@M-^] will cause ssh(1) to fail instantly if
- CanonicalizeHostname is enabled and the target hostname cannot be
- found in any of the domains specified by CanonicalDomains.
-
- CanonicalizeHostname
- Controls whether explicit hostname canonicalization is performed.
- The default, M-bM-^@M-^\noM-bM-^@M-^], is not to perform any name rewriting and let
- the system resolver handle all hostname lookups. If set to M-bM-^@M-^\yesM-bM-^@M-^]
- then, for connections that do not use a ProxyCommand, ssh(1) will
- attempt to canonicalize the hostname specified on the command
- line using the CanonicalDomains suffixes and
- CanonicalizePermittedCNAMEs rules. If CanonicalizeHostname is
- set to M-bM-^@M-^\alwaysM-bM-^@M-^], then canonicalization is applied to proxied
- connections too.
-
- If this option is enabled, then the configuration files are
- processed again using the new target name to pick up any new
- configuration in matching Host and Match stanzas.
-
- CanonicalizeMaxDots
- Specifies the maximum number of dot characters in a hostname
- before canonicalization is disabled. The default, M-bM-^@M-^\1M-bM-^@M-^], allows a
- single dot (i.e. hostname.subdomain).
-
- CanonicalizePermittedCNAMEs
- Specifies rules to determine whether CNAMEs should be followed
- when canonicalizing hostnames. The rules consist of one or more
- arguments of source_domain_list:target_domain_list, where
- source_domain_list is a pattern-list of domains that may follow
- CNAMEs in canonicalization, and target_domain_list is a pattern-
- list of domains that they may resolve to.
-
- For example, M-bM-^@M-^\*.a.example.com:*.b.example.com,*.c.example.comM-bM-^@M-^]
- will allow hostnames matching M-bM-^@M-^\*.a.example.comM-bM-^@M-^] to be
- canonicalized to names in the M-bM-^@M-^\*.b.example.comM-bM-^@M-^] or
- M-bM-^@M-^\*.c.example.comM-bM-^@M-^] domains.
-
- ChallengeResponseAuthentication
- Specifies whether to use challenge-response authentication. The
- argument to this keyword must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is
- M-bM-^@M-^\yesM-bM-^@M-^].
-
- CheckHostIP
- If this flag is set to M-bM-^@M-^\yesM-bM-^@M-^], ssh(1) will additionally check the
- host IP address in the known_hosts file. This allows ssh to
- detect if a host key changed due to DNS spoofing. If the option
- is set to M-bM-^@M-^\noM-bM-^@M-^], the check will not be executed. The default is
- M-bM-^@M-^\yesM-bM-^@M-^].
-
- Cipher Specifies the cipher to use for encrypting the session in
- protocol version 1. Currently, M-bM-^@M-^\blowfishM-bM-^@M-^], M-bM-^@M-^\3desM-bM-^@M-^], and M-bM-^@M-^\desM-bM-^@M-^] are
- supported. des is only supported in the ssh(1) client for
- interoperability with legacy protocol 1 implementations that do
- not support the 3des cipher. Its use is strongly discouraged due
- to cryptographic weaknesses. The default is M-bM-^@M-^\3desM-bM-^@M-^].
-
- Ciphers
- Specifies the ciphers allowed for protocol version 2 in order of
- preference. Multiple ciphers must be comma-separated. The
- supported ciphers are:
-
- 3des-cbc
- aes128-cbc
- aes192-cbc
- aes256-cbc
- aes128-ctr
- aes192-ctr
- aes256-ctr
- aes128-gcm@openssh.com
- aes256-gcm@openssh.com
- arcfour
- arcfour128
- arcfour256
- blowfish-cbc
- cast128-cbc
- chacha20-poly1305@openssh.com
-
- The default is:
-
- aes128-ctr,aes192-ctr,aes256-ctr,
- aes128-gcm@openssh.com,aes256-gcm@openssh.com,
- chacha20-poly1305@openssh.com,
- arcfour256,arcfour128,
- aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,
- aes192-cbc,aes256-cbc,arcfour
-
- The list of available ciphers may also be obtained using the -Q
- option of ssh(1) with an argument of M-bM-^@M-^\cipherM-bM-^@M-^].
-
- ClearAllForwardings
- Specifies that all local, remote, and dynamic port forwardings
- specified in the configuration files or on the command line be
- cleared. This option is primarily useful when used from the
- ssh(1) command line to clear port forwardings set in
- configuration files, and is automatically set by scp(1) and
- sftp(1). The argument must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is
- M-bM-^@M-^\noM-bM-^@M-^].
-
- Compression
- Specifies whether to use compression. The argument must be M-bM-^@M-^\yesM-bM-^@M-^]
- or M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- CompressionLevel
- Specifies the compression level to use if compression is enabled.
- The argument must be an integer from 1 (fast) to 9 (slow, best).
- The default level is 6, which is good for most applications. The
- meaning of the values is the same as in gzip(1). Note that this
- option applies to protocol version 1 only.
-
- ConnectionAttempts
- Specifies the number of tries (one per second) to make before
- exiting. The argument must be an integer. This may be useful in
- scripts if the connection sometimes fails. The default is 1.
-
- ConnectTimeout
- Specifies the timeout (in seconds) used when connecting to the
- SSH server, instead of using the default system TCP timeout.
- This value is used only when the target is down or really
- unreachable, not when it refuses the connection.
-
- ControlMaster
- Enables the sharing of multiple sessions over a single network
- connection. When set to M-bM-^@M-^\yesM-bM-^@M-^], ssh(1) will listen for
- connections on a control socket specified using the ControlPath
- argument. Additional sessions can connect to this socket using
- the same ControlPath with ControlMaster set to M-bM-^@M-^\noM-bM-^@M-^] (the
- default). These sessions will try to reuse the master instance's
- network connection rather than initiating new ones, but will fall
- back to connecting normally if the control socket does not exist,
- or is not listening.
-
- Setting this to M-bM-^@M-^\askM-bM-^@M-^] will cause ssh to listen for control
- connections, but require confirmation using the SSH_ASKPASS
- program before they are accepted (see ssh-add(1) for details).
- If the ControlPath cannot be opened, ssh will continue without
- connecting to a master instance.
-
- X11 and ssh-agent(1) forwarding is supported over these
- multiplexed connections, however the display and agent forwarded
- will be the one belonging to the master connection i.e. it is not
- possible to forward multiple displays or agents.
-
- Two additional options allow for opportunistic multiplexing: try
- to use a master connection but fall back to creating a new one if
- one does not already exist. These options are: M-bM-^@M-^\autoM-bM-^@M-^] and
- M-bM-^@M-^\autoaskM-bM-^@M-^]. The latter requires confirmation like the M-bM-^@M-^\askM-bM-^@M-^]
- option.
-
- ControlPath
- Specify the path to the control socket used for connection
- sharing as described in the ControlMaster section above or the
- string M-bM-^@M-^\noneM-bM-^@M-^] to disable connection sharing. In the path, M-bM-^@M-^X%LM-bM-^@M-^Y
- will be substituted by the first component of the local host
- name, M-bM-^@M-^X%lM-bM-^@M-^Y will be substituted by the local host name (including
- any domain name), M-bM-^@M-^X%hM-bM-^@M-^Y will be substituted by the target host
- name, M-bM-^@M-^X%nM-bM-^@M-^Y will be substituted by the original target host name
- specified on the command line, M-bM-^@M-^X%pM-bM-^@M-^Y the destination port, M-bM-^@M-^X%rM-bM-^@M-^Y by
- the remote login username, M-bM-^@M-^X%uM-bM-^@M-^Y by the username of the user
- running ssh(1), and M-bM-^@M-^X%CM-bM-^@M-^Y by a hash of the concatenation:
- %l%h%p%r. It is recommended that any ControlPath used for
- opportunistic connection sharing include at least %h, %p, and %r
- (or alternatively %C) and be placed in a directory that is not
- writable by other users. This ensures that shared connections
- are uniquely identified.
-
- ControlPersist
- When used in conjunction with ControlMaster, specifies that the
- master connection should remain open in the background (waiting
- for future client connections) after the initial client
- connection has been closed. If set to M-bM-^@M-^\noM-bM-^@M-^], then the master
- connection will not be placed into the background, and will close
- as soon as the initial client connection is closed. If set to
- M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\0M-bM-^@M-^], then the master connection will remain in the
- background indefinitely (until killed or closed via a mechanism
- such as the ssh(1) M-bM-^@M-^\-O exitM-bM-^@M-^] option). If set to a time in
- seconds, or a time in any of the formats documented in
- sshd_config(5), then the backgrounded master connection will
- automatically terminate after it has remained idle (with no
- client connections) for the specified time.
-
- DynamicForward
- Specifies that a TCP port on the local machine be forwarded over
- the secure channel, and the application protocol is then used to
- determine where to connect to from the remote machine.
-
- The argument must be [bind_address:]port. IPv6 addresses can be
- specified by enclosing addresses in square brackets. By default,
- the local port is bound in accordance with the GatewayPorts
- setting. However, an explicit bind_address may be used to bind
- the connection to a specific address. The bind_address of
- M-bM-^@M-^\localhostM-bM-^@M-^] indicates that the listening port be bound for local
- use only, while an empty address or M-bM-^@M-^X*M-bM-^@M-^Y indicates that the port
- should be available from all interfaces.
-
- Currently the SOCKS4 and SOCKS5 protocols are supported, and
- ssh(1) will act as a SOCKS server. Multiple forwardings may be
- specified, and additional forwardings can be given on the command
- line. Only the superuser can forward privileged ports.
-
- EnableSSHKeysign
- Setting this option to M-bM-^@M-^\yesM-bM-^@M-^] in the global client configuration
- file /etc/ssh/ssh_config enables the use of the helper program
- ssh-keysign(8) during HostbasedAuthentication. The argument must
- be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\noM-bM-^@M-^]. This option should be
- placed in the non-hostspecific section. See ssh-keysign(8) for
- more information.
-
- EscapeChar
- Sets the escape character (default: M-bM-^@M-^X~M-bM-^@M-^Y). The escape character
- can also be set on the command line. The argument should be a
- single character, M-bM-^@M-^X^M-bM-^@M-^Y followed by a letter, or M-bM-^@M-^\noneM-bM-^@M-^] to disable
- the escape character entirely (making the connection transparent
- for binary data).
-
- ExitOnForwardFailure
- Specifies whether ssh(1) should terminate the connection if it
- cannot set up all requested dynamic, tunnel, local, and remote
- port forwardings. The argument must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The
- default is M-bM-^@M-^\noM-bM-^@M-^].
-
- FingerprintHash
- Specifies the hash algorithm used when displaying key
- fingerprints. Valid options are: M-bM-^@M-^\md5M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The
- default is M-bM-^@M-^\sha256M-bM-^@M-^].
-
- ForwardAgent
- Specifies whether the connection to the authentication agent (if
- any) will be forwarded to the remote machine. The argument must
- be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- Agent forwarding should be enabled with caution. Users with the
- ability to bypass file permissions on the remote host (for the
- agent's Unix-domain socket) can access the local agent through
- the forwarded connection. An attacker cannot obtain key material
- from the agent, however they can perform operations on the keys
- that enable them to authenticate using the identities loaded into
- the agent.
-
- ForwardX11
- Specifies whether X11 connections will be automatically
- redirected over the secure channel and DISPLAY set. The argument
- must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- X11 forwarding should be enabled with caution. Users with the
- ability to bypass file permissions on the remote host (for the
- user's X11 authorization database) can access the local X11
- display through the forwarded connection. An attacker may then
- be able to perform activities such as keystroke monitoring if the
- ForwardX11Trusted option is also enabled.
-
- ForwardX11Timeout
- Specify a timeout for untrusted X11 forwarding using the format
- described in the TIME FORMATS section of sshd_config(5). X11
- connections received by ssh(1) after this time will be refused.
- The default is to disable untrusted X11 forwarding after twenty
- minutes has elapsed.
-
- ForwardX11Trusted
- If this option is set to M-bM-^@M-^\yesM-bM-^@M-^], remote X11 clients will have full
- access to the original X11 display.
-
- If this option is set to M-bM-^@M-^\noM-bM-^@M-^], remote X11 clients will be
- considered untrusted and prevented from stealing or tampering
- with data belonging to trusted X11 clients. Furthermore, the
- xauth(1) token used for the session will be set to expire after
- 20 minutes. Remote clients will be refused access after this
- time.
-
- The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- See the X11 SECURITY extension specification for full details on
- the restrictions imposed on untrusted clients.
-
- GatewayPorts
- Specifies whether remote hosts are allowed to connect to local
- forwarded ports. By default, ssh(1) binds local port forwardings
- to the loopback address. This prevents other remote hosts from
- connecting to forwarded ports. GatewayPorts can be used to
- specify that ssh should bind local port forwardings to the
- wildcard address, thus allowing remote hosts to connect to
- forwarded ports. The argument must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The
- default is M-bM-^@M-^\noM-bM-^@M-^].
-
- GlobalKnownHostsFile
- Specifies one or more files to use for the global host key
- database, separated by whitespace. The default is
- /etc/ssh/ssh_known_hosts, /etc/ssh/ssh_known_hosts2.
-
- GSSAPIAuthentication
- Specifies whether user authentication based on GSSAPI is allowed.
- The default is M-bM-^@M-^\noM-bM-^@M-^]. Note that this option applies to protocol
- version 2 only.
-
- GSSAPIDelegateCredentials
- Forward (delegate) credentials to the server. The default is
- M-bM-^@M-^\noM-bM-^@M-^]. Note that this option applies to protocol version 2 only.
-
- HashKnownHosts
- Indicates that ssh(1) should hash host names and addresses when
- they are added to ~/.ssh/known_hosts. These hashed names may be
- used normally by ssh(1) and sshd(8), but they do not reveal
- identifying information should the file's contents be disclosed.
- The default is M-bM-^@M-^\noM-bM-^@M-^]. Note that existing names and addresses in
- known hosts files will not be converted automatically, but may be
- manually hashed using ssh-keygen(1).
-
- HostbasedAuthentication
- Specifies whether to try rhosts based authentication with public
- key authentication. The argument must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The
- default is M-bM-^@M-^\noM-bM-^@M-^]. This option applies to protocol version 2 only
- and is similar to RhostsRSAAuthentication.
-
- HostbasedKeyTypes
- Specifies the key types that will be used for hostbased
- authentication as a comma-separated pattern list. The default
- M-bM-^@M-^\*M-bM-^@M-^] will allow all key types. The -Q option of ssh(1) may be
- used to list supported key types.
-
- HostKeyAlgorithms
- Specifies the protocol version 2 host key algorithms that the
- client wants to use in order of preference. The default for this
- option is:
-
- ecdsa-sha2-nistp256-cert-v01@openssh.com,
- ecdsa-sha2-nistp384-cert-v01@openssh.com,
- ecdsa-sha2-nistp521-cert-v01@openssh.com,
- ssh-ed25519-cert-v01@openssh.com,
- ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,
- ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,
- ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
- ssh-ed25519,ssh-rsa,ssh-dss
-
- If hostkeys are known for the destination host then this default
- is modified to prefer their algorithms.
-
- The list of available key types may also be obtained using the -Q
- option of ssh(1) with an argument of M-bM-^@M-^\keyM-bM-^@M-^].
-
- HostKeyAlias
- Specifies an alias that should be used instead of the real host
- name when looking up or saving the host key in the host key
- database files. This option is useful for tunneling SSH
- connections or for multiple servers running on a single host.
-
- HostName
- Specifies the real host name to log into. This can be used to
- specify nicknames or abbreviations for hosts. If the hostname
- contains the character sequence M-bM-^@M-^X%hM-bM-^@M-^Y, then this will be replaced
- with the host name specified on the command line (this is useful
- for manipulating unqualified names). The character sequence M-bM-^@M-^X%%M-bM-^@M-^Y
- will be replaced by a single M-bM-^@M-^X%M-bM-^@M-^Y character, which may be used
- when specifying IPv6 link-local addresses.
-
- The default is the name given on the command line. Numeric IP
- addresses are also permitted (both on the command line and in
- HostName specifications).
-
- IdentitiesOnly
- Specifies that ssh(1) should only use the authentication identity
- files configured in the ssh_config files, even if ssh-agent(1) or
- a PKCS11Provider offers more identities. The argument to this
- keyword must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. This option is intended for
- situations where ssh-agent offers many different identities. The
- default is M-bM-^@M-^\noM-bM-^@M-^].
-
- IdentityFile
- Specifies a file from which the user's DSA, ECDSA, Ed25519 or RSA
- authentication identity is read. The default is ~/.ssh/identity
- for protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa,
- ~/.ssh/id_ed25519 and ~/.ssh/id_rsa for protocol version 2.
- Additionally, any identities represented by the authentication
- agent will be used for authentication unless IdentitiesOnly is
- set. ssh(1) will try to load certificate information from the
- filename obtained by appending -cert.pub to the path of a
- specified IdentityFile.
-
- The file name may use the tilde syntax to refer to a user's home
- directory or one of the following escape characters: M-bM-^@M-^X%dM-bM-^@M-^Y (local
- user's home directory), M-bM-^@M-^X%uM-bM-^@M-^Y (local user name), M-bM-^@M-^X%lM-bM-^@M-^Y (local host
- name), M-bM-^@M-^X%hM-bM-^@M-^Y (remote host name) or M-bM-^@M-^X%rM-bM-^@M-^Y (remote user name).
-
- It is possible to have multiple identity files specified in
- configuration files; all these identities will be tried in
- sequence. Multiple IdentityFile directives will add to the list
- of identities tried (this behaviour differs from that of other
- configuration directives).
-
- IdentityFile may be used in conjunction with IdentitiesOnly to
- select which identities in an agent are offered during
- authentication.
-
- IgnoreUnknown
- Specifies a pattern-list of unknown options to be ignored if they
- are encountered in configuration parsing. This may be used to
- suppress errors if ssh_config contains options that are
- unrecognised by ssh(1). It is recommended that IgnoreUnknown be
- listed early in the configuration file as it will not be applied
- to unknown options that appear before it.
-
- IPQoS Specifies the IPv4 type-of-service or DSCP class for connections.
- Accepted values are M-bM-^@M-^\af11M-bM-^@M-^], M-bM-^@M-^\af12M-bM-^@M-^], M-bM-^@M-^\af13M-bM-^@M-^], M-bM-^@M-^\af21M-bM-^@M-^], M-bM-^@M-^\af22M-bM-^@M-^],
- M-bM-^@M-^\af23M-bM-^@M-^], M-bM-^@M-^\af31M-bM-^@M-^], M-bM-^@M-^\af32M-bM-^@M-^], M-bM-^@M-^\af33M-bM-^@M-^], M-bM-^@M-^\af41M-bM-^@M-^], M-bM-^@M-^\af42M-bM-^@M-^], M-bM-^@M-^\af43M-bM-^@M-^], M-bM-^@M-^\cs0M-bM-^@M-^],
- M-bM-^@M-^\cs1M-bM-^@M-^], M-bM-^@M-^\cs2M-bM-^@M-^], M-bM-^@M-^\cs3M-bM-^@M-^], M-bM-^@M-^\cs4M-bM-^@M-^], M-bM-^@M-^\cs5M-bM-^@M-^], M-bM-^@M-^\cs6M-bM-^@M-^], M-bM-^@M-^\cs7M-bM-^@M-^], M-bM-^@M-^\efM-bM-^@M-^],
- M-bM-^@M-^\lowdelayM-bM-^@M-^], M-bM-^@M-^\throughputM-bM-^@M-^], M-bM-^@M-^\reliabilityM-bM-^@M-^], or a numeric value.
- This option may take one or two arguments, separated by
- whitespace. If one argument is specified, it is used as the
- packet class unconditionally. If two values are specified, the
- first is automatically selected for interactive sessions and the
- second for non-interactive sessions. The default is M-bM-^@M-^\lowdelayM-bM-^@M-^]
- for interactive sessions and M-bM-^@M-^\throughputM-bM-^@M-^] for non-interactive
- sessions.
-
- KbdInteractiveAuthentication
- Specifies whether to use keyboard-interactive authentication.
- The argument to this keyword must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default
- is M-bM-^@M-^\yesM-bM-^@M-^].
-
- KbdInteractiveDevices
- Specifies the list of methods to use in keyboard-interactive
- authentication. Multiple method names must be comma-separated.
- The default is to use the server specified list. The methods
- available vary depending on what the server supports. For an
- OpenSSH server, it may be zero or more of: M-bM-^@M-^\bsdauthM-bM-^@M-^], M-bM-^@M-^\pamM-bM-^@M-^], and
- M-bM-^@M-^\skeyM-bM-^@M-^].
-
- KexAlgorithms
- Specifies the available KEX (Key Exchange) algorithms. Multiple
- algorithms must be comma-separated. The default is:
-
- curve25519-sha256@libssh.org,
- ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
- diffie-hellman-group-exchange-sha256,
- diffie-hellman-group14-sha1,
- diffie-hellman-group-exchange-sha1,
- diffie-hellman-group1-sha1
-
- The list of available key exchange algorithms may also be
- obtained using the -Q option of ssh(1) with an argument of M-bM-^@M-^\kexM-bM-^@M-^].
-
- LocalCommand
- Specifies a command to execute on the local machine after
- successfully connecting to the server. The command string
- extends to the end of the line, and is executed with the user's
- shell. The following escape character substitutions will be
- performed: M-bM-^@M-^X%dM-bM-^@M-^Y (local user's home directory), M-bM-^@M-^X%hM-bM-^@M-^Y (remote host
- name), M-bM-^@M-^X%lM-bM-^@M-^Y (local host name), M-bM-^@M-^X%nM-bM-^@M-^Y (host name as provided on the
- command line), M-bM-^@M-^X%pM-bM-^@M-^Y (remote port), M-bM-^@M-^X%rM-bM-^@M-^Y (remote user name) or
- M-bM-^@M-^X%uM-bM-^@M-^Y (local user name) or M-bM-^@M-^X%CM-bM-^@M-^Y by a hash of the concatenation:
- %l%h%p%r.
-
- The command is run synchronously and does not have access to the
- session of the ssh(1) that spawned it. It should not be used for
- interactive commands.
-
- This directive is ignored unless PermitLocalCommand has been
- enabled.
-
- LocalForward
- Specifies that a TCP port on the local machine be forwarded over
- the secure channel to the specified host and port from the remote
- machine. The first argument must be [bind_address:]port and the
- second argument must be host:hostport. IPv6 addresses can be
- specified by enclosing addresses in square brackets. Multiple
- forwardings may be specified, and additional forwardings can be
- given on the command line. Only the superuser can forward
- privileged ports. By default, the local port is bound in
- accordance with the GatewayPorts setting. However, an explicit
- bind_address may be used to bind the connection to a specific
- address. The bind_address of M-bM-^@M-^\localhostM-bM-^@M-^] indicates that the
- listening port be bound for local use only, while an empty
- address or M-bM-^@M-^X*M-bM-^@M-^Y indicates that the port should be available from
- all interfaces.
-
- LogLevel
- Gives the verbosity level that is used when logging messages from
- ssh(1). The possible values are: QUIET, FATAL, ERROR, INFO,
- VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO.
- DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify
- higher levels of verbose output.
-
- MACs Specifies the MAC (message authentication code) algorithms in
- order of preference. The MAC algorithm is used in protocol
- version 2 for data integrity protection. Multiple algorithms
- must be comma-separated. The algorithms that contain M-bM-^@M-^\-etmM-bM-^@M-^]
- calculate the MAC after encryption (encrypt-then-mac). These are
- considered safer and their use recommended. The default is:
-
- umac-64-etm@openssh.com,umac-128-etm@openssh.com,
- hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
- umac-64@openssh.com,umac-128@openssh.com,
- hmac-sha2-256,hmac-sha2-512,
- hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
- hmac-ripemd160-etm@openssh.com,
- hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,
- hmac-md5,hmac-sha1,hmac-ripemd160,
- hmac-sha1-96,hmac-md5-96
-
- The list of available MAC algorithms may also be obtained using
- the -Q option of ssh(1) with an argument of M-bM-^@M-^\macM-bM-^@M-^].
-
- NoHostAuthenticationForLocalhost
- This option can be used if the home directory is shared across
- machines. In this case localhost will refer to a different
- machine on each of the machines and the user will get many
- warnings about changed host keys. However, this option disables
- host authentication for localhost. The argument to this keyword
- must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is to check the host key for
- localhost.
-
- NumberOfPasswordPrompts
- Specifies the number of password prompts before giving up. The
- argument to this keyword must be an integer. The default is 3.
-
- PasswordAuthentication
- Specifies whether to use password authentication. The argument
- to this keyword must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\yesM-bM-^@M-^].
-
- PermitLocalCommand
- Allow local command execution via the LocalCommand option or
- using the !command escape sequence in ssh(1). The argument must
- be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- PKCS11Provider
- Specifies which PKCS#11 provider to use. The argument to this
- keyword is the PKCS#11 shared library ssh(1) should use to
- communicate with a PKCS#11 token providing the user's private RSA
- key.
-
- Port Specifies the port number to connect on the remote host. The
- default is 22.
-
- PreferredAuthentications
- Specifies the order in which the client should try protocol 2
- authentication methods. This allows a client to prefer one
- method (e.g. keyboard-interactive) over another method (e.g.
- password). The default is:
-
- gssapi-with-mic,hostbased,publickey,
- keyboard-interactive,password
-
- Protocol
- Specifies the protocol versions ssh(1) should support in order of
- preference. The possible values are M-bM-^@M-^X1M-bM-^@M-^Y and M-bM-^@M-^X2M-bM-^@M-^Y. Multiple
- versions must be comma-separated. When this option is set to
- M-bM-^@M-^\2,1M-bM-^@M-^] ssh will try version 2 and fall back to version 1 if
- version 2 is not available. The default is M-bM-^@M-^X2M-bM-^@M-^Y.
-
- ProxyCommand
- Specifies the command to use to connect to the server. The
- command string extends to the end of the line, and is executed
- using the user's shell M-bM-^@M-^XexecM-bM-^@M-^Y directive to avoid a lingering
- shell process.
-
- In the command string, any occurrence of M-bM-^@M-^X%hM-bM-^@M-^Y will be substituted
- by the host name to connect, M-bM-^@M-^X%pM-bM-^@M-^Y by the port, and M-bM-^@M-^X%rM-bM-^@M-^Y by the
- remote user name. The command can be basically anything, and
- should read from its standard input and write to its standard
- output. It should eventually connect an sshd(8) server running
- on some machine, or execute sshd -i somewhere. Host key
- management will be done using the HostName of the host being
- connected (defaulting to the name typed by the user). Setting
- the command to M-bM-^@M-^\noneM-bM-^@M-^] disables this option entirely. Note that
- CheckHostIP is not available for connects with a proxy command.
-
- This directive is useful in conjunction with nc(1) and its proxy
- support. For example, the following directive would connect via
- an HTTP proxy at 192.0.2.0:
-
- ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
-
- ProxyUseFdpass
- Specifies that ProxyCommand will pass a connected file descriptor
- back to ssh(1) instead of continuing to execute and pass data.
- The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- PubkeyAuthentication
- Specifies whether to try public key authentication. The argument
- to this keyword must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\yesM-bM-^@M-^].
- This option applies to protocol version 2 only.
-
- RekeyLimit
- Specifies the maximum amount of data that may be transmitted
- before the session key is renegotiated, optionally followed a
- maximum amount of time that may pass before the session key is
- renegotiated. The first argument is specified in bytes and may
- have a suffix of M-bM-^@M-^XKM-bM-^@M-^Y, M-bM-^@M-^XMM-bM-^@M-^Y, or M-bM-^@M-^XGM-bM-^@M-^Y to indicate Kilobytes,
- Megabytes, or Gigabytes, respectively. The default is between
- M-bM-^@M-^X1GM-bM-^@M-^Y and M-bM-^@M-^X4GM-bM-^@M-^Y, depending on the cipher. The optional second
- value is specified in seconds and may use any of the units
- documented in the TIME FORMATS section of sshd_config(5). The
- default value for RekeyLimit is M-bM-^@M-^\default noneM-bM-^@M-^], which means that
- rekeying is performed after the cipher's default amount of data
- has been sent or received and no time based rekeying is done.
- This option applies to protocol version 2 only.
-
- RemoteForward
- Specifies that a TCP port on the remote machine be forwarded over
- the secure channel to the specified host and port from the local
- machine. The first argument must be [bind_address:]port and the
- second argument must be host:hostport. IPv6 addresses can be
- specified by enclosing addresses in square brackets. Multiple
- forwardings may be specified, and additional forwardings can be
- given on the command line. Privileged ports can be forwarded
- only when logging in as root on the remote machine.
-
- If the port argument is M-bM-^@M-^X0M-bM-^@M-^Y, the listen port will be dynamically
- allocated on the server and reported to the client at run time.
-
- If the bind_address is not specified, the default is to only bind
- to loopback addresses. If the bind_address is M-bM-^@M-^X*M-bM-^@M-^Y or an empty
- string, then the forwarding is requested to listen on all
- interfaces. Specifying a remote bind_address will only succeed
- if the server's GatewayPorts option is enabled (see
- sshd_config(5)).
-
- RequestTTY
- Specifies whether to request a pseudo-tty for the session. The
- argument may be one of: M-bM-^@M-^\noM-bM-^@M-^] (never request a TTY), M-bM-^@M-^\yesM-bM-^@M-^] (always
- request a TTY when standard input is a TTY), M-bM-^@M-^\forceM-bM-^@M-^] (always
- request a TTY) or M-bM-^@M-^\autoM-bM-^@M-^] (request a TTY when opening a login
- session). This option mirrors the -t and -T flags for ssh(1).
-
- RevokedHostKeys
- Specifies revoked host public keys. Keys listed in this file
- will be refused for host authentication. Note that if this file
- does not exist or is not readable, then host authentication will
- be refused for all hosts. Keys may be specified as a text file,
- listing one public key per line, or as an OpenSSH Key Revocation
- List (KRL) as generated by ssh-keygen(1). For more information
- on KRLs, see the KEY REVOCATION LISTS section in ssh-keygen(1).
-
- RhostsRSAAuthentication
- Specifies whether to try rhosts based authentication with RSA
- host authentication. The argument must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The
- default is M-bM-^@M-^\noM-bM-^@M-^]. This option applies to protocol version 1 only
- and requires ssh(1) to be setuid root.
-
- RSAAuthentication
- Specifies whether to try RSA authentication. The argument to
- this keyword must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. RSA authentication will only
- be attempted if the identity file exists, or an authentication
- agent is running. The default is M-bM-^@M-^\yesM-bM-^@M-^]. Note that this option
- applies to protocol version 1 only.
-
- SendEnv
- Specifies what variables from the local environ(7) should be sent
- to the server. Note that environment passing is only supported
- for protocol 2. The server must also support it, and the server
- must be configured to accept these environment variables. Refer
- to AcceptEnv in sshd_config(5) for how to configure the server.
- Variables are specified by name, which may contain wildcard
- characters. Multiple environment variables may be separated by
- whitespace or spread across multiple SendEnv directives. The
- default is not to send any environment variables.
-
- See PATTERNS for more information on patterns.
-
- ServerAliveCountMax
- Sets the number of server alive messages (see below) which may be
- sent without ssh(1) receiving any messages back from the server.
- If this threshold is reached while server alive messages are
- being sent, ssh will disconnect from the server, terminating the
- session. It is important to note that the use of server alive
- messages is very different from TCPKeepAlive (below). The server
- alive messages are sent through the encrypted channel and
- therefore will not be spoofable. The TCP keepalive option
- enabled by TCPKeepAlive is spoofable. The server alive mechanism
- is valuable when the client or server depend on knowing when a
- connection has become inactive.
-
- The default value is 3. If, for example, ServerAliveInterval
- (see below) is set to 15 and ServerAliveCountMax is left at the
- default, if the server becomes unresponsive, ssh will disconnect
- after approximately 45 seconds. This option applies to protocol
- version 2 only.
-
- ServerAliveInterval
- Sets a timeout interval in seconds after which if no data has
- been received from the server, ssh(1) will send a message through
- the encrypted channel to request a response from the server. The
- default is 0, indicating that these messages will not be sent to
- the server. This option applies to protocol version 2 only.
-
- StreamLocalBindMask
- Sets the octal file creation mode mask (umask) used when creating
- a Unix-domain socket file for local or remote port forwarding.
- This option is only used for port forwarding to a Unix-domain
- socket file.
-
- The default value is 0177, which creates a Unix-domain socket
- file that is readable and writable only by the owner. Note that
- not all operating systems honor the file mode on Unix-domain
- socket files.
-
- StreamLocalBindUnlink
- Specifies whether to remove an existing Unix-domain socket file
- for local or remote port forwarding before creating a new one.
- If the socket file already exists and StreamLocalBindUnlink is
- not enabled, ssh will be unable to forward the port to the Unix-
- domain socket file. This option is only used for port forwarding
- to a Unix-domain socket file.
-
- The argument must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- StrictHostKeyChecking
- If this flag is set to M-bM-^@M-^\yesM-bM-^@M-^], ssh(1) will never automatically add
- host keys to the ~/.ssh/known_hosts file, and refuses to connect
- to hosts whose host key has changed. This provides maximum
- protection against trojan horse attacks, though it can be
- annoying when the /etc/ssh/ssh_known_hosts file is poorly
- maintained or when connections to new hosts are frequently made.
- This option forces the user to manually add all new hosts. If
- this flag is set to M-bM-^@M-^\noM-bM-^@M-^], ssh will automatically add new host
- keys to the user known hosts files. If this flag is set to
- M-bM-^@M-^\askM-bM-^@M-^], new host keys will be added to the user known host files
- only after the user has confirmed that is what they really want
- to do, and ssh will refuse to connect to hosts whose host key has
- changed. The host keys of known hosts will be verified
- automatically in all cases. The argument must be M-bM-^@M-^\yesM-bM-^@M-^], M-bM-^@M-^\noM-bM-^@M-^], or
- M-bM-^@M-^\askM-bM-^@M-^]. The default is M-bM-^@M-^\askM-bM-^@M-^].
-
- TCPKeepAlive
- Specifies whether the system should send TCP keepalive messages
- to the other side. If they are sent, death of the connection or
- crash of one of the machines will be properly noticed. However,
- this means that connections will die if the route is down
- temporarily, and some people find it annoying.
-
- The default is M-bM-^@M-^\yesM-bM-^@M-^] (to send TCP keepalive messages), and the
- client will notice if the network goes down or the remote host
- dies. This is important in scripts, and many users want it too.
-
- To disable TCP keepalive messages, the value should be set to
- M-bM-^@M-^\noM-bM-^@M-^].
-
- Tunnel Request tun(4) device forwarding between the client and the
- server. The argument must be M-bM-^@M-^\yesM-bM-^@M-^], M-bM-^@M-^\point-to-pointM-bM-^@M-^] (layer 3),
- M-bM-^@M-^\ethernetM-bM-^@M-^] (layer 2), or M-bM-^@M-^\noM-bM-^@M-^]. Specifying M-bM-^@M-^\yesM-bM-^@M-^] requests the
- default tunnel mode, which is M-bM-^@M-^\point-to-pointM-bM-^@M-^]. The default is
- M-bM-^@M-^\noM-bM-^@M-^].
-
- TunnelDevice
- Specifies the tun(4) devices to open on the client (local_tun)
- and the server (remote_tun).
-
- The argument must be local_tun[:remote_tun]. The devices may be
- specified by numerical ID or the keyword M-bM-^@M-^\anyM-bM-^@M-^], which uses the
- next available tunnel device. If remote_tun is not specified, it
- defaults to M-bM-^@M-^\anyM-bM-^@M-^]. The default is M-bM-^@M-^\any:anyM-bM-^@M-^].
-
- UpdateHostKeys
- Specifies whether ssh(1) should accept notifications of
- additional hostkeys from the server sent after authentication has
- completed and add them to UserKnownHostsFile. The argument must
- be M-bM-^@M-^\yesM-bM-^@M-^], M-bM-^@M-^\noM-bM-^@M-^] (the default) or M-bM-^@M-^\askM-bM-^@M-^]. Enabling this option
- allows learning alternate hostkeys for a server and supports
- graceful key rotation by allowing a server to send replacement
- public keys before old ones are removed. Additional hostkeys are
- only accepted if the key used to authenticate the host was
- already trusted or explicity accepted by the user. If
- UpdateHostKeys is set to M-bM-^@M-^\askM-bM-^@M-^], then the user is asked to confirm
- the modifications to the known_hosts file. Confirmation is
- currently incompatible with ControlPersist, and will be disabled
- if it is enabled.
-
- Presently, only sshd(8) from OpenSSH 6.8 and greater support the
- M-bM-^@M-^\hostkeys@openssh.comM-bM-^@M-^] protocol extension used to inform the
- client of all the server's hostkeys.
-
- UsePrivilegedPort
- Specifies whether to use a privileged port for outgoing
- connections. The argument must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is
- M-bM-^@M-^\noM-bM-^@M-^]. If set to M-bM-^@M-^\yesM-bM-^@M-^], ssh(1) must be setuid root. Note that
- this option must be set to M-bM-^@M-^\yesM-bM-^@M-^] for RhostsRSAAuthentication with
- older servers.
-
- User Specifies the user to log in as. This can be useful when a
- different user name is used on different machines. This saves
- the trouble of having to remember to give the user name on the
- command line.
-
- UserKnownHostsFile
- Specifies one or more files to use for the user host key
- database, separated by whitespace. The default is
- ~/.ssh/known_hosts, ~/.ssh/known_hosts2.
-
- VerifyHostKeyDNS
- Specifies whether to verify the remote key using DNS and SSHFP
- resource records. If this option is set to M-bM-^@M-^\yesM-bM-^@M-^], the client
- will implicitly trust keys that match a secure fingerprint from
- DNS. Insecure fingerprints will be handled as if this option was
- set to M-bM-^@M-^\askM-bM-^@M-^]. If this option is set to M-bM-^@M-^\askM-bM-^@M-^], information on
- fingerprint match will be displayed, but the user will still need
- to confirm new host keys according to the StrictHostKeyChecking
- option. The argument must be M-bM-^@M-^\yesM-bM-^@M-^], M-bM-^@M-^\noM-bM-^@M-^], or M-bM-^@M-^\askM-bM-^@M-^]. The default
- is M-bM-^@M-^\noM-bM-^@M-^]. Note that this option applies to protocol version 2
- only.
-
- See also VERIFYING HOST KEYS in ssh(1).
-
- VisualHostKey
- If this flag is set to M-bM-^@M-^\yesM-bM-^@M-^], an ASCII art representation of the
- remote host key fingerprint is printed in addition to the
- fingerprint string at login and for unknown host keys. If this
- flag is set to M-bM-^@M-^\noM-bM-^@M-^], no fingerprint strings are printed at login
- and only the fingerprint string will be printed for unknown host
- keys. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- XAuthLocation
- Specifies the full pathname of the xauth(1) program. The default
- is /usr/X11R6/bin/xauth.
-
-PATTERNS
- A pattern consists of zero or more non-whitespace characters, M-bM-^@M-^X*M-bM-^@M-^Y (a
- wildcard that matches zero or more characters), or M-bM-^@M-^X?M-bM-^@M-^Y (a wildcard that
- matches exactly one character). For example, to specify a set of
- declarations for any host in the M-bM-^@M-^\.co.ukM-bM-^@M-^] set of domains, the following
- pattern could be used:
-
- Host *.co.uk
-
- The following pattern would match any host in the 192.168.0.[0-9] network
- range:
-
- Host 192.168.0.?
-
- A pattern-list is a comma-separated list of patterns. Patterns within
- pattern-lists may be negated by preceding them with an exclamation mark
- (M-bM-^@M-^X!M-bM-^@M-^Y). For example, to allow a key to be used from anywhere within an
- organization except from the M-bM-^@M-^\dialupM-bM-^@M-^] pool, the following entry (in
- authorized_keys) could be used:
-
- from="!*.dialup.example.com,*.example.com"
-
-FILES
- ~/.ssh/config
- This is the per-user configuration file. The format of this file
- is described above. This file is used by the SSH client.
- Because of the potential for abuse, this file must have strict
- permissions: read/write for the user, and not accessible by
- others.
-
- /etc/ssh/ssh_config
- Systemwide configuration file. This file provides defaults for
- those values that are not specified in the user's configuration
- file, and for those users who do not have a configuration file.
- This file must be world-readable.
-
-SEE ALSO
- ssh(1)
-
-AUTHORS
- OpenSSH is a derivative of the original and free ssh 1.2.12 release by
- Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
- de Raadt and Dug Song removed many bugs, re-added newer features and
- created OpenSSH. Markus Friedl contributed the support for SSH protocol
- versions 1.5 and 2.0.
-
-OpenBSD 5.7 February 20, 2015 OpenBSD 5.7
diff --git a/ssh_config.5 b/ssh_config.5
index 140d0ba9..dc010ccb 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,16 +33,13 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh_config.5,v 1.205 2015/02/20 22:17:21 djm Exp $
-.Dd $Mdocdate: February 20 2015 $
+.\" $OpenBSD: ssh_config.5,v 1.325 2020/04/11 20:20:09 jmc Exp $
+.Dd $Mdocdate: April 11 2020 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
.Nm ssh_config
-.Nd OpenSSH SSH client configuration files
-.Sh SYNOPSIS
-.Nm ~/.ssh/config
-.Nm /etc/ssh/ssh_config
+.Nd OpenSSH client configuration file
.Sh DESCRIPTION
.Xr ssh 1
obtains configuration data from the following sources in
@@ -62,25 +59,25 @@ system-wide configuration file
For each parameter, the first obtained value
will be used.
The configuration files contain sections separated by
-.Dq Host
+.Cm Host
specifications, and that section is only applied for hosts that
match one of the patterns given in the specification.
The matched host name is usually the one given on the command line
(see the
.Cm CanonicalizeHostname
-option for exceptions.)
+option for exceptions).
.Pp
Since the first obtained value for each parameter is used, more
host-specific declarations should be given near the beginning of the
file, and general defaults at the end.
.Pp
-The configuration file has the following format:
-.Pp
-Empty lines and lines starting with
+The file contains keyword-argument pairs, one per line.
+Lines starting with
.Ql #
-are comments.
-Otherwise a line is of the format
-.Dq keyword arguments .
+and empty lines are interpreted as comments.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
Configuration options may be separated by whitespace or
optional whitespace and exactly one
.Ql = ;
@@ -92,9 +89,6 @@ and
.Nm sftp
.Fl o
option.
-Arguments may optionally be enclosed in double quotes
-.Pq \&"
-in order to represent arguments containing spaces.
.Pp
The possible
keywords and their meanings are as follows (note that
@@ -117,7 +111,7 @@ The host is usually the
argument given on the command line
(see the
.Cm CanonicalizeHostname
-option for exceptions.)
+keyword for exceptions).
.Pp
A pattern entry may be negated by prefixing it with an exclamation mark
.Pq Sq !\& .
@@ -139,12 +133,13 @@ or
keyword) to be used only when the conditions following the
.Cm Match
keyword are satisfied.
-Match conditions are specified using one or more critera
+Match conditions are specified using one or more criteria
or the single token
.Cm all
which always matches.
The available criteria keywords are:
.Cm canonical ,
+.Cm final ,
.Cm exec ,
.Cm host ,
.Cm originalhost ,
@@ -154,47 +149,51 @@ and
The
.Cm all
criteria must appear alone or immediately after
-.Cm canonical .
+.Cm canonical
+or
+.Cm final .
Other criteria may be combined arbitrarily.
All criteria but
-.Cm all
+.Cm all ,
+.Cm canonical ,
and
-.Cm canonical
+.Cm final
require an argument.
Criteria may be negated by prepending an exclamation mark
.Pq Sq !\& .
.Pp
The
.Cm canonical
-keywork matches only when the configuration file is being re-parsed
+keyword matches only when the configuration file is being re-parsed
after hostname canonicalization (see the
.Cm CanonicalizeHostname
-option.)
+option).
This may be useful to specify conditions that work with canonical host
names only.
+.Pp
+The
+.Cm final
+keyword requests that the configuration be re-parsed (regardless of whether
+.Cm CanonicalizeHostname
+is enabled), and matches only during this final pass.
+If
+.Cm CanonicalizeHostname
+is enabled, then
+.Cm canonical
+and
+.Cm final
+match during the same pass.
+.Pp
The
.Cm exec
keyword executes the specified command under the user's shell.
If the command returns a zero exit status then the condition is considered true.
Commands containing whitespace characters must be quoted.
-The following character sequences in the command will be expanded prior to
-execution:
-.Ql %L
-will be substituted by the first component of the local host name,
-.Ql %l
-will be substituted by the local host name (including any domain name),
-.Ql %h
-will be substituted by the target host name,
-.Ql %n
-will be substituted by the original target host name
-specified on the command-line,
-.Ql %p
-the destination port,
-.Ql %r
-by the remote login username, and
-.Ql %u
-by the username of the user running
-.Xr ssh 1 .
+Arguments to
+.Cm exec
+accept the tokens described in the
+.Sx TOKENS
+section.
.Pp
The other keywords' criteria must be single entries or comma-separated
lists and may use the wildcard and negation operators described in the
@@ -221,34 +220,67 @@ keyword matches against the name of the local user running
(this keyword may be useful in system-wide
.Nm
files).
+.It Cm AddKeysToAgent
+Specifies whether keys should be automatically added to a running
+.Xr ssh-agent 1 .
+If this option is set to
+.Cm yes
+and a key is loaded from a file, the key and its passphrase are added to
+the agent with the default lifetime, as if by
+.Xr ssh-add 1 .
+If this option is set to
+.Cm ask ,
+.Xr ssh 1
+will require confirmation using the
+.Ev SSH_ASKPASS
+program before adding a key (see
+.Xr ssh-add 1
+for details).
+If this option is set to
+.Cm confirm ,
+each use of the key must be confirmed, as if the
+.Fl c
+option was specified to
+.Xr ssh-add 1 .
+If this option is set to
+.Cm no ,
+no keys are added to the agent.
+The argument must be
+.Cm yes ,
+.Cm confirm ,
+.Cm ask ,
+or
+.Cm no
+(the default).
.It Cm AddressFamily
Specifies which address family to use when connecting.
Valid arguments are
-.Dq any ,
-.Dq inet
+.Cm any
+(the default),
+.Cm inet
(use IPv4 only), or
-.Dq inet6
+.Cm inet6
(use IPv6 only).
.It Cm BatchMode
If set to
-.Dq yes ,
-passphrase/password querying will be disabled.
+.Cm yes ,
+user interaction such as password prompts and host key confirmation requests
+will be disabled.
This option is useful in scripts and other batch jobs where no user
-is present to supply the password.
+is present to interact with
+.Xr ssh 1 .
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
-The default is
-.Dq no .
+.Cm no
+(the default).
.It Cm BindAddress
Use the specified address on the local machine as the source address of
the connection.
Only useful on systems with more than one address.
-Note that this option does not work if
-.Cm UsePrivilegedPort
-is set to
-.Dq yes .
+.It Cm BindInterface
+Use the address of the specified interface on the local machine as the
+source address of the connection.
.It Cm CanonicalDomains
When
.Cm CanonicalizeHostname
@@ -257,11 +289,11 @@ search for the specified destination host.
.It Cm CanonicalizeFallbackLocal
Specifies whether to fail with an error when hostname canonicalization fails.
The default,
-.Dq yes ,
+.Cm yes ,
will attempt to look up the unqualified hostname using the system resolver's
search rules.
A value of
-.Dq no
+.Cm no
will cause
.Xr ssh 1
to fail instantly if
@@ -272,13 +304,15 @@ specified by
.It Cm CanonicalizeHostname
Controls whether explicit hostname canonicalization is performed.
The default,
-.Dq no ,
+.Cm no ,
is not to perform any name rewriting and let the system resolver handle all
hostname lookups.
If set to
-.Dq yes
+.Cm yes
then, for connections that do not use a
-.Cm ProxyCommand ,
+.Cm ProxyCommand
+or
+.Cm ProxyJump ,
.Xr ssh 1
will attempt to canonicalize the hostname specified on the command line
using the
@@ -289,7 +323,7 @@ rules.
If
.Cm CanonicalizeHostname
is set to
-.Dq always ,
+.Cm always ,
then canonicalization is applied to proxied connections too.
.Pp
If this option is enabled, then the configuration files are processed
@@ -301,8 +335,7 @@ stanzas.
.It Cm CanonicalizeMaxDots
Specifies the maximum number of dot characters in a hostname before
canonicalization is disabled.
-The default,
-.Dq 1 ,
+The default, 1,
allows a single dot (i.e. hostname.subdomain).
.It Cm CanonicalizePermittedCNAMEs
Specifies rules to determine whether CNAMEs should be followed when
@@ -317,109 +350,118 @@ and
is a pattern-list of domains that they may resolve to.
.Pp
For example,
-.Dq *.a.example.com:*.b.example.com,*.c.example.com
+.Qq *.a.example.com:*.b.example.com,*.c.example.com
will allow hostnames matching
-.Dq *.a.example.com
+.Qq *.a.example.com
to be canonicalized to names in the
-.Dq *.b.example.com
+.Qq *.b.example.com
or
-.Dq *.c.example.com
+.Qq *.c.example.com
domains.
+.It Cm CASignatureAlgorithms
+Specifies which algorithms are allowed for signing of certificates
+by certificate authorities (CAs).
+The default is:
+.Bd -literal -offset indent
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
+.Ed
+.Pp
+.Xr ssh 1
+will not accept host certificates signed using algorithms other than those
+specified.
+.It Cm CertificateFile
+Specifies a file from which the user's certificate is read.
+A corresponding private key must be provided separately in order
+to use this certificate either
+from an
+.Cm IdentityFile
+directive or
+.Fl i
+flag to
+.Xr ssh 1 ,
+via
+.Xr ssh-agent 1 ,
+or via a
+.Cm PKCS11Provider
+or
+.Cm SecurityKeyProvider .
+.Pp
+Arguments to
+.Cm CertificateFile
+may use the tilde syntax to refer to a user's home directory
+or the tokens described in the
+.Sx TOKENS
+section.
+.Pp
+It is possible to have multiple certificate files specified in
+configuration files; these certificates will be tried in sequence.
+Multiple
+.Cm CertificateFile
+directives will add to the list of certificates used for
+authentication.
.It Cm ChallengeResponseAuthentication
Specifies whether to use challenge-response authentication.
The argument to this keyword must be
-.Dq yes
+.Cm yes
+(the default)
or
-.Dq no .
-The default is
-.Dq yes .
+.Cm no .
.It Cm CheckHostIP
-If this flag is set to
-.Dq yes ,
+If set to
+.Cm yes
+(the default),
.Xr ssh 1
will additionally check the host IP address in the
.Pa known_hosts
file.
-This allows ssh to detect if a host key changed due to DNS spoofing.
+This allows it to detect if a host key changed due to DNS spoofing
+and will add addresses of destination hosts to
+.Pa ~/.ssh/known_hosts
+in the process, regardless of the setting of
+.Cm StrictHostKeyChecking .
If the option is set to
-.Dq no ,
+.Cm no ,
the check will not be executed.
-The default is
-.Dq yes .
-.It Cm Cipher
-Specifies the cipher to use for encrypting the session
-in protocol version 1.
-Currently,
-.Dq blowfish ,
-.Dq 3des ,
-and
-.Dq des
-are supported.
-.Ar des
-is only supported in the
-.Xr ssh 1
-client for interoperability with legacy protocol 1 implementations
-that do not support the
-.Ar 3des
-cipher.
-Its use is strongly discouraged due to cryptographic weaknesses.
-The default is
-.Dq 3des .
.It Cm Ciphers
-Specifies the ciphers allowed for protocol version 2
-in order of preference.
+Specifies the ciphers allowed and their order of preference.
Multiple ciphers must be comma-separated.
-The supported ciphers are:
+If the specified list begins with a
+.Sq +
+character, then the specified ciphers will be appended to the default set
+instead of replacing them.
+If the specified list begins with a
+.Sq -
+character, then the specified ciphers (including wildcards) will be removed
+from the default set instead of replacing them.
+If the specified list begins with a
+.Sq ^
+character, then the specified ciphers will be placed at the head of the
+default set.
.Pp
-.Bl -item -compact -offset indent
-.It
+The supported ciphers are:
+.Bd -literal -offset indent
3des-cbc
-.It
aes128-cbc
-.It
aes192-cbc
-.It
aes256-cbc
-.It
aes128-ctr
-.It
aes192-ctr
-.It
aes256-ctr
-.It
aes128-gcm@openssh.com
-.It
aes256-gcm@openssh.com
-.It
-arcfour
-.It
-arcfour128
-.It
-arcfour256
-.It
-blowfish-cbc
-.It
-cast128-cbc
-.It
chacha20-poly1305@openssh.com
-.El
+.Ed
.Pp
The default is:
.Bd -literal -offset indent
-aes128-ctr,aes192-ctr,aes256-ctr,
-aes128-gcm@openssh.com,aes256-gcm@openssh.com,
chacha20-poly1305@openssh.com,
-arcfour256,arcfour128,
-aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,
-aes192-cbc,aes256-cbc,arcfour
+aes128-ctr,aes192-ctr,aes256-ctr,
+aes128-gcm@openssh.com,aes256-gcm@openssh.com
.Ed
.Pp
-The list of available ciphers may also be obtained using the
-.Fl Q
-option of
-.Xr ssh 1
-with an argument of
-.Dq cipher .
+The list of available ciphers may also be obtained using
+.Qq ssh -Q cipher .
.It Cm ClearAllForwardings
Specifies that all local, remote, and dynamic port forwardings
specified in the configuration files or on the command line be
@@ -432,26 +474,17 @@ configuration files, and is automatically set by
and
.Xr sftp 1 .
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
-The default is
-.Dq no .
+.Cm no
+(the default).
.It Cm Compression
Specifies whether to use compression.
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
-The default is
-.Dq no .
-.It Cm CompressionLevel
-Specifies the compression level to use if compression is enabled.
-The argument must be an integer from 1 (fast) to 9 (slow, best).
-The default level is 6, which is good for most applications.
-The meaning of the values is the same as in
-.Xr gzip 1 .
-Note that this option applies to protocol version 1 only.
+.Cm no
+(the default).
.It Cm ConnectionAttempts
Specifies the number of tries (one per second) to make before exiting.
The argument must be an integer.
@@ -460,12 +493,12 @@ The default is 1.
.It Cm ConnectTimeout
Specifies the timeout (in seconds) used when connecting to the
SSH server, instead of using the default system TCP timeout.
-This value is used only when the target is down or really unreachable,
-not when it refuses the connection.
+This timeout is applied both to establishing the connection and to performing
+the initial SSH protocol handshake and key exchange.
.It Cm ControlMaster
Enables the sharing of multiple sessions over a single network connection.
When set to
-.Dq yes ,
+.Cm yes ,
.Xr ssh 1
will listen for connections on a control socket specified using the
.Cm ControlPath
@@ -475,24 +508,23 @@ Additional sessions can connect to this socket using the same
with
.Cm ControlMaster
set to
-.Dq no
+.Cm no
(the default).
These sessions will try to reuse the master instance's network connection
rather than initiating new ones, but will fall back to connecting normally
if the control socket does not exist, or is not listening.
.Pp
Setting this to
-.Dq ask
-will cause ssh
-to listen for control connections, but require confirmation using the
-.Ev SSH_ASKPASS
-program before they are accepted (see
-.Xr ssh-add 1
-for details).
+.Cm ask
+will cause
+.Xr ssh 1
+to listen for control connections, but require confirmation using
+.Xr ssh-askpass 1 .
If the
.Cm ControlPath
cannot be opened,
-ssh will continue without connecting to a master instance.
+.Xr ssh 1
+will continue without connecting to a master instance.
.Pp
X11 and
.Xr ssh-agent 1
@@ -504,38 +536,25 @@ Two additional options allow for opportunistic multiplexing: try to use a
master connection but fall back to creating a new one if one does not already
exist.
These options are:
-.Dq auto
+.Cm auto
and
-.Dq autoask .
+.Cm autoask .
The latter requires confirmation like the
-.Dq ask
+.Cm ask
option.
.It Cm ControlPath
Specify the path to the control socket used for connection sharing as described
in the
.Cm ControlMaster
section above or the string
-.Dq none
+.Cm none
to disable connection sharing.
-In the path,
-.Ql %L
-will be substituted by the first component of the local host name,
-.Ql %l
-will be substituted by the local host name (including any domain name),
-.Ql %h
-will be substituted by the target host name,
-.Ql %n
-will be substituted by the original target host name
-specified on the command line,
-.Ql %p
-the destination port,
-.Ql %r
-by the remote login username,
-.Ql %u
-by the username of the user running
-.Xr ssh 1 , and
-.Ql \&%C
-by a hash of the concatenation: %l%h%p%r.
+Arguments to
+.Cm ControlPath
+may use the tilde syntax to refer to a user's home directory
+or the tokens described in the
+.Sx TOKENS
+section.
It is recommended that any
.Cm ControlPath
used for opportunistic connection sharing include
@@ -549,18 +568,16 @@ specifies that the master connection should remain open
in the background (waiting for future client connections)
after the initial client connection has been closed.
If set to
-.Dq no ,
+.Cm no
+(the default),
then the master connection will not be placed into the background,
and will close as soon as the initial client connection is closed.
If set to
-.Dq yes
-or
-.Dq 0 ,
+.Cm yes
+or 0,
then the master connection will remain in the background indefinitely
(until killed or closed via a mechanism such as the
-.Xr ssh 1
-.Dq Fl O No exit
-option).
+.Qq ssh -O exit ) .
If set to a time in seconds, or a time in any of the formats documented in
.Xr sshd_config 5 ,
then the backgrounded master connection will automatically terminate
@@ -586,7 +603,7 @@ may be used to bind the connection to a specific address.
The
.Ar bind_address
of
-.Dq localhost
+.Cm localhost
indicates that the listening port be bound for local use only, while an
empty address or
.Sq *
@@ -600,7 +617,7 @@ additional forwardings can be given on the command line.
Only the superuser can forward privileged ports.
.It Cm EnableSSHKeysign
Setting this option to
-.Dq yes
+.Cm yes
in the global client configuration file
.Pa /etc/ssh/ssh_config
enables the use of the helper program
@@ -608,11 +625,10 @@ enables the use of the helper program
during
.Cm HostbasedAuthentication .
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
-The default is
-.Dq no .
+.Cm no
+(the default).
This option should be placed in the non-hostspecific section.
See
.Xr ssh-keysign 8
@@ -625,7 +641,7 @@ be set on the command line.
The argument should be a single character,
.Ql ^
followed by a letter, or
-.Dq none
+.Cm none
to disable the escape
character entirely (making the connection transparent for binary
data).
@@ -633,30 +649,37 @@ data).
Specifies whether
.Xr ssh 1
should terminate the connection if it cannot set up all requested
-dynamic, tunnel, local, and remote port forwardings.
+dynamic, tunnel, local, and remote port forwardings, (e.g.\&
+if either end is unable to bind and listen on a specified port).
+Note that
+.Cm ExitOnForwardFailure
+does not apply to connections made over port forwardings and will not,
+for example, cause
+.Xr ssh 1
+to exit if TCP connections to the ultimate forwarding destination fail.
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
-The default is
-.Dq no .
+.Cm no
+(the default).
.It Cm FingerprintHash
Specifies the hash algorithm used when displaying key fingerprints.
Valid options are:
-.Dq md5
+.Cm md5
and
-.Dq sha256 .
-The default is
-.Dq sha256 .
+.Cm sha256
+(the default).
.It Cm ForwardAgent
Specifies whether the connection to the authentication agent (if any)
will be forwarded to the remote machine.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
+The argument may be
+.Cm yes ,
+.Cm no
+(the default),
+an explicit path to an agent socket or the name of an environment variable
+(beginning with
+.Sq $ )
+in which to find the path.
.Pp
Agent forwarding should be enabled with caution.
Users with the ability to bypass file permissions on the remote host
@@ -671,11 +694,10 @@ over the secure channel and
.Ev DISPLAY
set.
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
-The default is
-.Dq no .
+.Cm no
+(the default).
.Pp
X11 forwarding should be enabled with caution.
Users with the ability to bypass file permissions on the remote host
@@ -688,20 +710,26 @@ option is also enabled.
.It Cm ForwardX11Timeout
Specify a timeout for untrusted X11 forwarding
using the format described in the
-TIME FORMATS section of
+.Sx TIME FORMATS
+section of
.Xr sshd_config 5 .
X11 connections received by
.Xr ssh 1
after this time will be refused.
+Setting
+.Cm ForwardX11Timeout
+to zero will disable the timeout and permit X11 forwarding for the life
+of the connection.
The default is to disable untrusted X11 forwarding after twenty minutes has
elapsed.
.It Cm ForwardX11Trusted
If this option is set to
-.Dq yes ,
+.Cm yes ,
remote X11 clients will have full access to the original X11 display.
.Pp
If this option is set to
-.Dq no ,
+.Cm no
+(the default),
remote X11 clients will be considered untrusted and prevented
from stealing or tampering with data belonging to trusted X11
clients.
@@ -710,9 +738,6 @@ Furthermore, the
token used for the session will be set to expire after 20 minutes.
Remote clients will be refused access after this time.
.Pp
-The default is
-.Dq no .
-.Pp
See the X11 SECURITY extension specification for full details on
the restrictions imposed on untrusted clients.
.It Cm GatewayPorts
@@ -727,11 +752,10 @@ can be used to specify that ssh
should bind local port forwardings to the wildcard address,
thus allowing remote hosts to connect to forwarded ports.
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
-The default is
-.Dq no .
+.Cm no
+(the default).
.It Cm GlobalKnownHostsFile
Specifies one or more files to use for the global
host key database, separated by whitespace.
@@ -741,13 +765,11 @@ The default is
.It Cm GSSAPIAuthentication
Specifies whether user authentication based on GSSAPI is allowed.
The default is
-.Dq no .
-Note that this option applies to protocol version 2 only.
+.Cm no .
.It Cm GSSAPIDelegateCredentials
Forward (delegate) credentials to the server.
The default is
-.Dq no .
-Note that this option applies to protocol version 2 only.
+.Cm no .
.It Cm HashKnownHosts
Indicates that
.Xr ssh 1
@@ -757,10 +779,10 @@ These hashed names may be used normally by
.Xr ssh 1
and
.Xr sshd 8 ,
-but they do not reveal identifying information should the file's contents
-be disclosed.
+but they do not visually reveal identifying information if the
+file's contents are disclosed.
The default is
-.Dq no .
+.Cm no .
Note that existing names and addresses in known hosts files
will not be converted automatically,
but may be manually hashed using
@@ -769,107 +791,170 @@ but may be manually hashed using
Specifies whether to try rhosts based authentication with public key
authentication.
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
-The default is
-.Dq no .
-This option applies to protocol version 2 only and
-is similar to
-.Cm RhostsRSAAuthentication .
+.Cm no
+(the default).
.It Cm HostbasedKeyTypes
Specifies the key types that will be used for hostbased authentication
-as a comma-separated pattern list.
-The default
-.Dq *
-will allow all key types.
+as a comma-separated list of patterns.
+Alternately if the specified list begins with a
+.Sq +
+character, then the specified key types will be appended to the default set
+instead of replacing them.
+If the specified list begins with a
+.Sq -
+character, then the specified key types (including wildcards) will be removed
+from the default set instead of replacing them.
+If the specified list begins with a
+.Sq ^
+character, then the specified key types will be placed at the head of the
+default set.
+The default for this option is:
+.Bd -literal -offset 3n
+ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ecdsa-sha2-nistp384-cert-v01@openssh.com,
+ecdsa-sha2-nistp521-cert-v01@openssh.com,
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ssh-ed25519-cert-v01@openssh.com,
+sk-ssh-ed25519-cert-v01@openssh.com,
+rsa-sha2-512-cert-v01@openssh.com,
+rsa-sha2-256-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+sk-ecdsa-sha2-nistp256@openssh.com,
+ssh-ed25519,sk-ssh-ed25519@openssh.com,
+rsa-sha2-512,rsa-sha2-256,ssh-rsa
+.Ed
+.Pp
The
.Fl Q
option of
.Xr ssh 1
may be used to list supported key types.
.It Cm HostKeyAlgorithms
-Specifies the protocol version 2 host key algorithms
+Specifies the host key 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.
+If the specified list begins with a
+.Sq -
+character, then the specified key types (including wildcards) will be removed
+from the default set instead of replacing them.
+If the specified list begins with a
+.Sq ^
+character, then the specified key types will be placed at the head of the
+default set.
The default for this option is:
.Bd -literal -offset 3n
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
-ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,
-ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,
+sk-ssh-ed25519-cert-v01@openssh.com,
+rsa-sha2-512-cert-v01@openssh.com,
+rsa-sha2-256-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-ssh-ed25519,ssh-rsa,ssh-dss
+sk-ecdsa-sha2-nistp256@openssh.com,
+ssh-ed25519,sk-ssh-ed25519@openssh.com,
+rsa-sha2-512,rsa-sha2-256,ssh-rsa
.Ed
.Pp
If hostkeys are known for the destination host then this default is modified
to prefer their algorithms.
.Pp
-The list of available key types may also be obtained using the
-.Fl Q
-option of
-.Xr ssh 1
-with an argument of
-.Dq key .
+The list of available key types may also be obtained using
+.Qq ssh -Q HostKeyAlgorithms .
.It Cm HostKeyAlias
Specifies an alias that should be used instead of the
real host name when looking up or saving the host key
-in the host key database files.
+in the host key database files and when validating host certificates.
This option is useful for tunneling SSH connections
or for multiple servers running on a single host.
-.It Cm HostName
+.It Cm Hostname
Specifies the real host name to log into.
This can be used to specify nicknames or abbreviations for hosts.
-If the hostname contains the character sequence
-.Ql %h ,
-then this will be replaced with the host name specified on the command line
-(this is useful for manipulating unqualified names).
-The character sequence
-.Ql %%
-will be replaced by a single
-.Ql %
-character, which may be used when specifying IPv6 link-local addresses.
-.Pp
-The default is the name given on the command line.
+Arguments to
+.Cm Hostname
+accept the tokens described in the
+.Sx TOKENS
+section.
Numeric IP addresses are also permitted (both on the command line and in
-.Cm HostName
+.Cm Hostname
specifications).
+The default is the name given on the command line.
.It Cm IdentitiesOnly
Specifies that
.Xr ssh 1
-should only use the authentication identity files configured in the
+should only use the configured authentication identity and certificate files
+(either the default files, or those explicitly configured in the
.Nm
-files,
+files
+or passed on the
+.Xr ssh 1
+command-line),
even if
.Xr ssh-agent 1
or a
.Cm PKCS11Provider
+or
+.Cm SecurityKeyProvider
offers more identities.
The argument to this keyword must be
-.Dq yes
+.Cm yes
or
-.Dq no .
+.Cm no
+(the default).
This option is intended for situations where ssh-agent
offers many different identities.
-The default is
-.Dq no .
+.It Cm IdentityAgent
+Specifies the
+.Ux Ns -domain
+socket used to communicate with the authentication agent.
+.Pp
+This option overrides the
+.Ev SSH_AUTH_SOCK
+environment variable and can be used to select a specific agent.
+Setting the socket name to
+.Cm none
+disables the use of an authentication agent.
+If the string
+.Qq SSH_AUTH_SOCK
+is specified, the location of the socket will be read from the
+.Ev SSH_AUTH_SOCK
+environment variable.
+Otherwise if the specified value begins with a
+.Sq $
+character, then it will be treated as an environment variable containing
+the location of the socket.
+.Pp
+Arguments to
+.Cm IdentityAgent
+may use the tilde syntax to refer to a user's home directory
+or the tokens described in the
+.Sx TOKENS
+section.
.It Cm IdentityFile
-Specifies a file from which the user's DSA, ECDSA, Ed25519 or RSA authentication
-identity is read.
+Specifies a file from which the user's DSA, ECDSA, authenticator-hosted ECDSA,
+Ed25519, authenticator-hosted Ed25519 or RSA authentication identity is read.
The default is
-.Pa ~/.ssh/identity
-for protocol version 1, and
.Pa ~/.ssh/id_dsa ,
.Pa ~/.ssh/id_ecdsa ,
-.Pa ~/.ssh/id_ed25519
+.Pa ~/.ssh/id_ecdsa_sk ,
+.Pa ~/.ssh/id_ed25519 ,
+.Pa ~/.ssh/id_ed25519_sk
and
-.Pa ~/.ssh/id_rsa
-for protocol version 2.
+.Pa ~/.ssh/id_rsa .
Additionally, any identities represented by the authentication agent
will be used for authentication unless
.Cm IdentitiesOnly
is set.
+If no certificates have been explicitly specified by
+.Cm CertificateFile ,
.Xr ssh 1
will try to load certificate information from the filename obtained by
appending
@@ -877,19 +962,12 @@ appending
to the path of a specified
.Cm IdentityFile .
.Pp
-The file name may use the tilde
-syntax to refer to a user's home directory or one of the following
-escape characters:
-.Ql %d
-(local user's home directory),
-.Ql %u
-(local user name),
-.Ql %l
-(local host name),
-.Ql %h
-(remote host name) or
-.Ql %r
-(remote user name).
+Arguments to
+.Cm IdentityFile
+may use the tilde syntax to refer to a user's home directory
+or the tokens described in the
+.Sx TOKENS
+section.
.Pp
It is possible to have
multiple identity files specified in configuration files; all these
@@ -903,6 +981,11 @@ differs from that of other configuration directives).
may be used in conjunction with
.Cm IdentitiesOnly
to select which identities in an agent are offered during authentication.
+.Cm IdentityFile
+may also be used in conjunction with
+.Cm CertificateFile
+in order to provide any certificate also needed for authentication with
+the identity.
.It Cm IgnoreUnknown
Specifies a pattern-list of unknown options to be ignored if they are
encountered in configuration parsing.
@@ -914,51 +997,74 @@ It is recommended that
.Cm IgnoreUnknown
be listed early in the configuration file as it will not be applied
to unknown options that appear before it.
+.It Cm Include
+Include the specified configuration file(s).
+Multiple pathnames may be specified and each pathname may contain
+.Xr glob 7
+wildcards and, for user configurations, shell-like
+.Sq ~
+references to user home directories.
+Files without absolute paths are assumed to be in
+.Pa ~/.ssh
+if included in a user configuration file or
+.Pa /etc/ssh
+if included from the system configuration file.
+.Cm Include
+directive may appear inside a
+.Cm Match
+or
+.Cm Host
+block
+to perform conditional inclusion.
.It Cm IPQoS
Specifies the IPv4 type-of-service or DSCP class for connections.
Accepted values are
-.Dq af11 ,
-.Dq af12 ,
-.Dq af13 ,
-.Dq af21 ,
-.Dq af22 ,
-.Dq af23 ,
-.Dq af31 ,
-.Dq af32 ,
-.Dq af33 ,
-.Dq af41 ,
-.Dq af42 ,
-.Dq af43 ,
-.Dq cs0 ,
-.Dq cs1 ,
-.Dq cs2 ,
-.Dq cs3 ,
-.Dq cs4 ,
-.Dq cs5 ,
-.Dq cs6 ,
-.Dq cs7 ,
-.Dq ef ,
-.Dq lowdelay ,
-.Dq throughput ,
-.Dq reliability ,
-or a numeric value.
+.Cm af11 ,
+.Cm af12 ,
+.Cm af13 ,
+.Cm af21 ,
+.Cm af22 ,
+.Cm af23 ,
+.Cm af31 ,
+.Cm af32 ,
+.Cm af33 ,
+.Cm af41 ,
+.Cm af42 ,
+.Cm af43 ,
+.Cm cs0 ,
+.Cm cs1 ,
+.Cm cs2 ,
+.Cm cs3 ,
+.Cm cs4 ,
+.Cm cs5 ,
+.Cm cs6 ,
+.Cm cs7 ,
+.Cm ef ,
+.Cm le ,
+.Cm lowdelay ,
+.Cm throughput ,
+.Cm reliability ,
+a numeric value, or
+.Cm none
+to use the operating system default.
This option may take one or two arguments, separated by whitespace.
If one argument is specified, it is used as the packet class unconditionally.
If two values are specified, the first is automatically selected for
interactive sessions and the second for non-interactive sessions.
The default is
-.Dq lowdelay
+.Cm af21
+(Low-Latency Data)
for interactive sessions and
-.Dq throughput
+.Cm cs1
+(Lower Effort)
for non-interactive sessions.
.It Cm KbdInteractiveAuthentication
Specifies whether to use keyboard-interactive authentication.
The argument to this keyword must be
-.Dq yes
+.Cm yes
+(the default)
or
-.Dq no .
-The default is
-.Dq yes .
+.Cm no .
.It Cm KbdInteractiveDevices
Specifies the list of methods to use in keyboard-interactive authentication.
Multiple method names must be comma-separated.
@@ -966,51 +1072,46 @@ The default is to use the server specified list.
The methods available vary depending on what the server supports.
For an OpenSSH server,
it may be zero or more of:
-.Dq bsdauth ,
-.Dq pam ,
+.Cm bsdauth
and
-.Dq skey .
+.Cm pam .
.It Cm KexAlgorithms
Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.
+If the specified list begins with a
+.Sq +
+character, then the specified methods 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
+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
+default set.
The default is:
.Bd -literal -offset indent
-curve25519-sha256@libssh.org,
+curve25519-sha256,curve25519-sha256@libssh.org,
ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
diffie-hellman-group-exchange-sha256,
-diffie-hellman-group14-sha1,
-diffie-hellman-group-exchange-sha1,
-diffie-hellman-group1-sha1
+diffie-hellman-group16-sha512,
+diffie-hellman-group18-sha512,
+diffie-hellman-group14-sha256
.Ed
.Pp
-The list of available key exchange algorithms may also be obtained using the
-.Fl Q
-option of
-.Xr ssh 1
-with an argument of
-.Dq kex .
+The list of available key exchange algorithms may also be obtained using
+.Qq ssh -Q kex .
.It Cm LocalCommand
Specifies a command to execute on the local machine after successfully
connecting to the server.
The command string extends to the end of the line, and is executed with
the user's shell.
-The following escape character substitutions will be performed:
-.Ql %d
-(local user's home directory),
-.Ql %h
-(remote host name),
-.Ql %l
-(local host name),
-.Ql %n
-(host name as provided on the command line),
-.Ql %p
-(remote port),
-.Ql %r
-(remote user name) or
-.Ql %u
-(local user name) or
-.Ql \&%C
-by a hash of the concatenation: %l%h%p%r.
+Arguments to
+.Cm LocalCommand
+accept the tokens described in the
+.Sx TOKENS
+section.
.Pp
The command is run synchronously and does not have access to the
session of the
@@ -1024,12 +1125,15 @@ has been enabled.
.It Cm LocalForward
Specifies that a TCP port on the local machine be forwarded over
the secure channel to the specified host and port from the remote machine.
-The first argument must be
+The first argument specifies the listener and may be
.Sm off
.Oo Ar bind_address : Oc Ar port
.Sm on
-and the second argument must be
-.Ar host : Ns Ar hostport .
+or a Unix domain socket path.
+The second argument is the destination and may be
+.Ar host : Ns Ar hostport
+or a Unix domain socket path if the remote host supports it.
+.Pp
IPv6 addresses can be specified by enclosing addresses in square brackets.
Multiple forwardings may be specified, and additional forwardings can be
given on the command line.
@@ -1043,11 +1147,14 @@ may be used to bind the connection to a specific address.
The
.Ar bind_address
of
-.Dq localhost
+.Cm localhost
indicates that the listening port be bound for local use only, while an
empty address or
.Sq *
indicates that the port should be available from all interfaces.
+Unix domain socket paths accept the tokens described in the
+.Sx TOKENS
+section.
.It Cm LogLevel
Gives the verbosity level that is used when logging messages from
.Xr ssh 1 .
@@ -1059,42 +1166,44 @@ DEBUG2 and DEBUG3 each specify higher levels of verbose output.
.It Cm MACs
Specifies the MAC (message authentication code) algorithms
in order of preference.
-The MAC algorithm is used in protocol version 2
-for data integrity protection.
+The MAC algorithm is used for data integrity protection.
Multiple algorithms must be comma-separated.
+If the specified list begins with a
+.Sq +
+character, then the specified algorithms will be appended to the default set
+instead of replacing them.
+If the specified list begins with a
+.Sq -
+character, then the specified algorithms (including wildcards) will be removed
+from the default set instead of replacing them.
+If the specified list begins with a
+.Sq ^
+character, then the specified algorithms will be placed at the head of the
+default set.
+.Pp
The algorithms that contain
-.Dq -etm
+.Qq -etm
calculate the MAC after encryption (encrypt-then-mac).
These are considered safer and their use recommended.
+.Pp
The default is:
.Bd -literal -offset indent
umac-64-etm@openssh.com,umac-128-etm@openssh.com,
hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
+hmac-sha1-etm@openssh.com,
umac-64@openssh.com,umac-128@openssh.com,
-hmac-sha2-256,hmac-sha2-512,
-hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
-hmac-ripemd160-etm@openssh.com,
-hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,
-hmac-md5,hmac-sha1,hmac-ripemd160,
-hmac-sha1-96,hmac-md5-96
+hmac-sha2-256,hmac-sha2-512,hmac-sha1
.Ed
.Pp
-The list of available MAC algorithms may also be obtained using the
-.Fl Q
-option of
-.Xr ssh 1
-with an argument of
-.Dq mac .
+The list of available MAC algorithms may also be obtained using
+.Qq ssh -Q mac .
.It Cm NoHostAuthenticationForLocalhost
-This option can be used if the home directory is shared across machines.
-In this case localhost will refer to a different machine on each of
-the machines and the user will get many warnings about changed host keys.
-However, this option disables host authentication for localhost.
+Disable host authentication for localhost (loopback addresses).
The argument to this keyword must be
-.Dq yes
+.Cm yes
or
-.Dq no .
-The default is to check the host key for localhost.
+.Cm no
+(the default).
.It Cm NumberOfPasswordPrompts
Specifies the number of password prompts before giving up.
The argument to this keyword must be an integer.
@@ -1102,11 +1211,10 @@ The default is 3.
.It Cm PasswordAuthentication
Specifies whether to use password authentication.
The argument to this keyword must be
-.Dq yes
+.Cm yes
+(the default)
or
-.Dq no .
-The default is
-.Dq yes .
+.Cm no .
.It Cm PermitLocalCommand
Allow local command execution via the
.Ic LocalCommand
@@ -1115,23 +1223,23 @@ option or using the
escape sequence in
.Xr ssh 1 .
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
-The default is
-.Dq no .
+.Cm no
+(the default).
.It Cm PKCS11Provider
-Specifies which PKCS#11 provider to use.
-The argument to this keyword is the PKCS#11 shared library
+Specifies which PKCS#11 provider to use or
+.Cm none
+to indicate that no provider should be used (the default).
+The argument to this keyword is a path to the PKCS#11 shared library
.Xr ssh 1
-should use to communicate with a PKCS#11 token providing the user's
-private RSA key.
+should use to communicate with a PKCS#11 token providing keys for user
+authentication.
.It Cm Port
Specifies the port number to connect on the remote host.
The default is 22.
.It Cm PreferredAuthentications
-Specifies the order in which the client should try protocol 2
-authentication methods.
+Specifies the order in which the client should try authentication methods.
This allows a client to prefer one method (e.g.\&
.Cm keyboard-interactive )
over another method (e.g.\&
@@ -1141,22 +1249,6 @@ The default is:
gssapi-with-mic,hostbased,publickey,
keyboard-interactive,password
.Ed
-.It Cm Protocol
-Specifies the protocol versions
-.Xr ssh 1
-should support in order of preference.
-The possible values are
-.Sq 1
-and
-.Sq 2 .
-Multiple versions must be comma-separated.
-When this option is set to
-.Dq 2,1
-.Nm ssh
-will try version 2 and fall back to version 1
-if version 2 is not available.
-The default is
-.Sq 2 .
.It Cm ProxyCommand
Specifies the command to use to connect to the server.
The command
@@ -1165,14 +1257,11 @@ using the user's shell
.Ql exec
directive to avoid a lingering shell process.
.Pp
-In the command string, any occurrence of
-.Ql %h
-will be substituted by the host name to
-connect,
-.Ql %p
-by the port, and
-.Ql %r
-by the remote user name.
+Arguments to
+.Cm ProxyCommand
+accept the tokens described in the
+.Sx TOKENS
+section.
The command can be basically anything,
and should read from its standard input and write to its standard output.
It should eventually connect an
@@ -1181,10 +1270,10 @@ server running on some machine, or execute
.Ic sshd -i
somewhere.
Host key management will be done using the
-HostName of the host being connected (defaulting to the name typed by
-the user).
+.Cm Hostname
+of the host being connected (defaulting to the name typed by the user).
Setting the command to
-.Dq none
+.Cm none
disables this option entirely.
Note that
.Cm CheckHostIP
@@ -1198,6 +1287,37 @@ For example, the following directive would connect via an HTTP proxy at
.Bd -literal -offset 3n
ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
.Ed
+.It Cm ProxyJump
+Specifies one or more jump proxies as either
+.Xo
+.Sm off
+.Op Ar user No @
+.Ar host
+.Op : Ns Ar port
+.Sm on
+or an ssh URI
+.Xc .
+Multiple proxies may be separated by comma characters and will be visited
+sequentially.
+Setting this option will cause
+.Xr ssh 1
+to connect to the target host by first making a
+.Xr ssh 1
+connection to the specified
+.Cm ProxyJump
+host and then establishing a
+TCP forwarding to the ultimate target from there.
+.Pp
+Note that this option will compete with the
+.Cm ProxyCommand
+option - whichever is specified first will prevent later instances of the
+other from taking effect.
+.Pp
+Note also that the configuration for the destination host (either supplied
+via the command-line or the configuration file) is not generally applied
+to jump hosts.
+.Pa ~/.ssh/config
+should be used if specific configuration is required for jump hosts.
.It Cm ProxyUseFdpass
Specifies that
.Cm ProxyCommand
@@ -1205,16 +1325,48 @@ will pass a connected file descriptor back to
.Xr ssh 1
instead of continuing to execute and pass data.
The default is
-.Dq no .
+.Cm no .
+.It Cm PubkeyAcceptedKeyTypes
+Specifies the key types 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
+instead of replacing it.
+If the specified list begins with a
+.Sq -
+character, then the specified key types (including wildcards) will be removed
+from the default set instead of replacing them.
+If the specified list begins with a
+.Sq ^
+character, then the specified key types will be placed at the head of the
+default set.
+The default for this option is:
+.Bd -literal -offset 3n
+ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ecdsa-sha2-nistp384-cert-v01@openssh.com,
+ecdsa-sha2-nistp521-cert-v01@openssh.com,
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ssh-ed25519-cert-v01@openssh.com,
+sk-ssh-ed25519-cert-v01@openssh.com,
+rsa-sha2-512-cert-v01@openssh.com,
+rsa-sha2-256-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+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 .
.It Cm PubkeyAuthentication
Specifies whether to try public key authentication.
The argument to this keyword must be
-.Dq yes
+.Cm yes
+(the default)
or
-.Dq no .
-The default is
-.Dq yes .
-This option applies to protocol version 2 only.
+.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
@@ -1231,35 +1383,53 @@ and
.Sq 4G ,
depending on the cipher.
The optional second value is specified in seconds and may use any of the
-units documented in the
-TIME FORMATS section of
+units documented in the TIME FORMATS section of
.Xr sshd_config 5 .
The default value for
.Cm RekeyLimit
is
-.Dq default none ,
+.Cm default none ,
which means that rekeying is performed after the cipher's default amount
of data has been sent or received and no time based rekeying is done.
-This option applies to protocol version 2 only.
+.It Cm RemoteCommand
+Specifies a command to execute on the remote machine after successfully
+connecting to the server.
+The command string extends to the end of the line, and is executed with
+the user's shell.
+Arguments to
+.Cm RemoteCommand
+accept the tokens described in the
+.Sx TOKENS
+section.
.It Cm RemoteForward
Specifies that a TCP port on the remote machine be forwarded over
-the secure channel to the specified host and port from the local machine.
-The first argument must be
+the secure channel.
+The remote port may either be forwarded to a specified host and port
+from the local machine, or may act as a SOCKS 4/5 proxy that allows a remote
+client to connect to arbitrary destinations from the local machine.
+The first argument is the listening specification and may be
.Sm off
.Oo Ar bind_address : Oc Ar port
.Sm on
-and the second argument must be
-.Ar host : Ns Ar hostport .
+or, if the remote host supports it, a Unix domain socket path.
+If forwarding to a specific destination then the second argument must be
+.Ar host : Ns Ar hostport
+or a Unix domain socket path,
+otherwise if no destination argument is specified then the remote forwarding
+will be established as a SOCKS proxy.
+.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
+.Sx TOKENS
+section.
.Pp
If the
.Ar port
-argument is
-.Ql 0 ,
+argument is 0,
the listen port will be dynamically allocated on the server and reported
to the client at run time.
.Pp
@@ -1281,13 +1451,13 @@ option is enabled (see
.It Cm RequestTTY
Specifies whether to request a pseudo-tty for the session.
The argument may be one of:
-.Dq no
+.Cm no
(never request a TTY),
-.Dq yes
+.Cm yes
(always request a TTY when standard input is a TTY),
-.Dq force
+.Cm force
(always request a TTY) or
-.Dq auto
+.Cm auto
(request a TTY when opening a login session).
This option mirrors the
.Fl t
@@ -1305,37 +1475,25 @@ an OpenSSH Key Revocation List (KRL) as generated by
.Xr ssh-keygen 1 .
For more information on KRLs, see the KEY REVOCATION LISTS section in
.Xr ssh-keygen 1 .
-.It Cm RhostsRSAAuthentication
-Specifies whether to try rhosts based authentication with RSA host
-authentication.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
-This option applies to protocol version 1 only and requires
-.Xr ssh 1
-to be setuid root.
-.It Cm RSAAuthentication
-Specifies whether to try RSA authentication.
-The argument to this keyword must be
-.Dq yes
-or
-.Dq no .
-RSA authentication will only be
-attempted if the identity file exists, or an authentication agent is
-running.
-The default is
-.Dq yes .
-Note that this option applies to protocol version 1 only.
+.It Cm SecurityKeyProvider
+Specifies a path to a library that will be used when loading any
+FIDO authenticator-hosted keys, overriding the default of using
+the built-in USB HID support.
+.Pp
+If the specified value begins with a
+.Sq $
+character, then it will be treated as an environment variable containing
+the path to the library.
.It Cm SendEnv
Specifies what variables from the local
.Xr environ 7
should be sent to the server.
-Note that environment passing is only supported for protocol 2.
The server must also support it, and the server must be configured to
accept these environment variables.
+Note that the
+.Ev TERM
+environment variable is always sent whenever a
+pseudo-terminal is requested as it is required by the protocol.
Refer to
.Cm AcceptEnv
in
@@ -1346,11 +1504,16 @@ Multiple environment variables may be separated by whitespace or spread
across multiple
.Cm SendEnv
directives.
-The default is not to send any environment variables.
.Pp
See
.Sx PATTERNS
for more information on patterns.
+.Pp
+It is possible to clear previously set
+.Cm SendEnv
+variable names by prefixing patterns with
+.Pa - .
+The default is not to send any environment variables.
.It Cm ServerAliveCountMax
Sets the number of server alive messages (see below) which may be
sent without
@@ -1368,7 +1531,7 @@ The TCP keepalive option enabled by
.Cm TCPKeepAlive
is spoofable.
The server alive mechanism is valuable when the client or
-server depend on knowing when a connection has become inactive.
+server depend on knowing when a connection has become unresponsive.
.Pp
The default value is 3.
If, for example,
@@ -1377,7 +1540,6 @@ If, for example,
.Cm ServerAliveCountMax
is left at the default, if the server becomes unresponsive,
ssh will disconnect after approximately 45 seconds.
-This option applies to protocol version 2 only.
.It Cm ServerAliveInterval
Sets a timeout interval in seconds after which if no data has been received
from the server,
@@ -1386,7 +1548,12 @@ 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.
-This option applies to protocol version 2 only.
+.It Cm SetEnv
+Directly specify one or more environment variables and their contents to
+be sent to the server.
+Similarly to
+.Cm SendEnv ,
+the server must be prepared to accept the environment variable.
.It Cm StreamLocalBindMask
Sets the octal file creation mode mask
.Pq umask
@@ -1409,44 +1576,52 @@ will be unable to forward the port to the Unix-domain socket file.
This option is only used for port forwarding to a Unix-domain socket file.
.Pp
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
-The default is
-.Dq no .
+.Cm no
+(the default).
.It Cm StrictHostKeyChecking
If this flag is set to
-.Dq yes ,
+.Cm yes ,
.Xr ssh 1
will never automatically add host keys to the
.Pa ~/.ssh/known_hosts
file, and refuses to connect to hosts whose host key has changed.
-This provides maximum protection against trojan horse attacks,
+This provides maximum protection against man-in-the-middle (MITM) attacks,
though it can be annoying when the
.Pa /etc/ssh/ssh_known_hosts
file is poorly maintained or when connections to new hosts are
frequently made.
This option forces the user to manually
add all new hosts.
+.Pp
If this flag is set to
-.Dq no ,
-ssh will automatically add new host keys to the
-user known hosts files.
+.Dq accept-new
+then ssh will automatically add new host keys to the user
+known hosts files, but will not permit connections to hosts with
+changed host keys.
If this flag is set to
-.Dq ask ,
+.Dq no
+or
+.Dq off ,
+ssh will automatically add new host keys to the user known hosts files
+and allow connections to hosts with changed hostkeys to proceed,
+subject to some restrictions.
+If this flag is set to
+.Cm ask
+(the default),
new host keys
will be added to the user known host files only after the user
has confirmed that is what they really want to do, and
ssh will refuse to connect to hosts whose host key has changed.
The host keys of
known hosts will be verified automatically in all cases.
-The argument must be
-.Dq yes ,
-.Dq no ,
-or
-.Dq ask .
-The default is
-.Dq ask .
+.It Cm SyslogFacility
+Gives the facility code that is used when logging messages from
+.Xr ssh 1 .
+The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+The default is USER.
.It Cm TCPKeepAlive
Specifies whether the system should send TCP keepalive messages to the
other side.
@@ -1457,31 +1632,33 @@ connections will die if the route is down temporarily, and some people
find it annoying.
.Pp
The default is
-.Dq yes
+.Cm yes
(to send TCP keepalive messages), and the client will notice
if the network goes down or the remote host dies.
This is important in scripts, and many users want it too.
.Pp
To disable TCP keepalive messages, the value should be set to
-.Dq no .
+.Cm no .
+See also
+.Cm ServerAliveInterval
+for protocol-level keepalives.
.It Cm Tunnel
Request
.Xr tun 4
device forwarding between the client and the server.
The argument must be
-.Dq yes ,
-.Dq point-to-point
+.Cm yes ,
+.Cm point-to-point
(layer 3),
-.Dq ethernet
+.Cm ethernet
(layer 2),
or
-.Dq no .
+.Cm no
+(the default).
Specifying
-.Dq yes
+.Cm yes
requests the default tunnel mode, which is
-.Dq point-to-point .
-The default is
-.Dq no .
+.Cm point-to-point .
.It Cm TunnelDevice
Specifies the
.Xr tun 4
@@ -1495,14 +1672,14 @@ The argument must be
.Ar local_tun Op : Ar remote_tun .
.Sm on
The devices may be specified by numerical ID or the keyword
-.Dq any ,
+.Cm any ,
which uses the next available tunnel device.
If
.Ar remote_tun
is not specified, it defaults to
-.Dq any .
+.Cm any .
The default is
-.Dq any:any .
+.Cm any:any .
.It Cm UpdateHostKeys
Specifies whether
.Xr ssh 1
@@ -1510,19 +1687,28 @@ should accept notifications of additional hostkeys from the server sent
after authentication has completed and add them to
.Cm UserKnownHostsFile .
The argument must be
-.Dq yes ,
-.Dq no
-(the default) or
-.Dq ask .
-Enabling this option allows learning alternate hostkeys for a server
+.Cm yes ,
+.Cm no
+or
+.Cm ask .
+This option allows learning alternate hostkeys for a server
and supports graceful key rotation by allowing a server to send replacement
public keys before old ones are removed.
Additional hostkeys are only accepted if the key used to authenticate the
-host was already trusted or explicity accepted by the user.
+host was already trusted or explicitly accepted by the user.
+.Pp
+.Cm UpdateHostKeys
+is enabled by default if the user has not overridden the default
+.Cm UserKnownHostsFile
+setting, otherwise
+.Cm UpdateHostKeys
+will be set to
+.Cm ask .
+.Pp
If
.Cm UpdateHostKeys
is set to
-.Dq ask ,
+.Cm ask ,
then the user is asked to confirm the modifications to the known_hosts file.
Confirmation is currently incompatible with
.Cm ControlPersist ,
@@ -1531,25 +1717,8 @@ and will be disabled if it is enabled.
Presently, only
.Xr sshd 8
from OpenSSH 6.8 and greater support the
-.Dq hostkeys@openssh.com
+.Qq hostkeys@openssh.com
protocol extension used to inform the client of all the server's hostkeys.
-.It Cm UsePrivilegedPort
-Specifies whether to use a privileged port for outgoing connections.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
-If set to
-.Dq yes ,
-.Xr ssh 1
-must be setuid root.
-Note that this option must be set to
-.Dq yes
-for
-.Cm RhostsRSAAuthentication
-with older servers.
.It Cm User
Specifies the user to log in as.
This can be useful when a different user name is used on different machines.
@@ -1565,40 +1734,35 @@ The default is
Specifies whether to verify the remote key using DNS and SSHFP resource
records.
If this option is set to
-.Dq yes ,
+.Cm yes ,
the client will implicitly trust keys that match a secure fingerprint
from DNS.
Insecure fingerprints will be handled as if this option was set to
-.Dq ask .
+.Cm ask .
If this option is set to
-.Dq ask ,
+.Cm ask ,
information on fingerprint match will be displayed, but the user will still
need to confirm new host keys according to the
.Cm StrictHostKeyChecking
option.
-The argument must be
-.Dq yes ,
-.Dq no ,
-or
-.Dq ask .
The default is
-.Dq no .
-Note that this option applies to protocol version 2 only.
+.Cm no .
.Pp
-See also VERIFYING HOST KEYS in
+See also
+.Sx VERIFYING HOST KEYS
+in
.Xr ssh 1 .
.It Cm VisualHostKey
If this flag is set to
-.Dq yes ,
+.Cm yes ,
an ASCII art representation of the remote host key fingerprint is
printed in addition to the fingerprint string at login and
for unknown host keys.
If this flag is set to
-.Dq no ,
+.Cm no
+(the default),
no fingerprint strings are printed at login and
only the fingerprint string will be printed for unknown host keys.
-The default is
-.Dq no .
.It Cm XAuthLocation
Specifies the full pathname of the
.Xr xauth 1
@@ -1616,7 +1780,7 @@ or
.Sq ?\&
(a wildcard that matches exactly one character).
For example, to specify a set of declarations for any host in the
-.Dq .co.uk
+.Qq .co.uk
set of domains,
the following pattern could be used:
.Pp
@@ -1636,11 +1800,81 @@ by preceding them with an exclamation mark
For example,
to allow a key to be used from anywhere within an organization
except from the
-.Dq dialup
+.Qq dialup
pool,
the following entry (in authorized_keys) could be used:
.Pp
.Dl from=\&"!*.dialup.example.com,*.example.com\&"
+.Pp
+Note that a negated match will never produce a positive result by itself.
+For example, attempting to match
+.Qq host3
+against the following pattern-list will fail:
+.Pp
+.Dl from=\&"!host1,!host2\&"
+.Pp
+The solution here is to include a term that will yield a positive match,
+such as a wildcard:
+.Pp
+.Dl from=\&"!host1,!host2,*\&"
+.Sh TOKENS
+Arguments to some keywords can make use of tokens,
+which are expanded at runtime:
+.Pp
+.Bl -tag -width XXXX -offset indent -compact
+.It %%
+A literal
+.Sq % .
+.It \&%C
+Hash of %l%h%p%r.
+.It %d
+Local user's home directory.
+.It %h
+The remote hostname.
+.It %i
+The local user ID.
+.It %L
+The local hostname.
+.It %l
+The local hostname, including the domain name.
+.It %n
+The original remote hostname, as given on the command line.
+.It %p
+The remote port.
+.It %r
+The remote username.
+.It \&%T
+The local
+.Xr tun 4
+or
+.Xr tap 4
+network interface assigned if
+tunnel forwarding was requested, or
+.Qq NONE
+otherwise.
+.It %u
+The local username.
+.El
+.Pp
+.Cm CertificateFile ,
+.Cm ControlPath ,
+.Cm IdentityAgent ,
+.Cm IdentityFile ,
+.Cm LocalForward ,
+.Cm Match exec ,
+.Cm RemoteCommand ,
+and
+.Cm RemoteForward
+accept the tokens %%, %C, %d, %h, %i, %L, %l, %n, %p, %r, and %u.
+.Pp
+.Cm Hostname
+accepts the tokens %% and %h.
+.Pp
+.Cm LocalCommand
+accepts all tokens.
+.Pp
+.Cm ProxyCommand
+accepts the tokens %%, %h, %n, %p, and %r.
.Sh FILES
.Bl -tag -width Ds
.It Pa ~/.ssh/config
@@ -1648,7 +1882,7 @@ This is the per-user configuration file.
The format of this file is described above.
This file is used by the SSH client.
Because of the potential for abuse, this file must have strict permissions:
-read/write for the user, and not accessible by others.
+read/write for the user, and not writable by others.
.It Pa /etc/ssh/ssh_config
Systemwide configuration file.
This file provides defaults for those
@@ -1659,11 +1893,15 @@ This file must be world-readable.
.Sh SEE ALSO
.Xr ssh 1
.Sh AUTHORS
+.An -nosplit
OpenSSH is a derivative of the original and free
-ssh 1.2.12 release by Tatu Ylonen.
-Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
-Theo de Raadt and Dug Song
+ssh 1.2.12 release by
+.An Tatu Ylonen .
+.An Aaron Campbell , Bob Beck , Markus Friedl ,
+.An Niels Provos , Theo de Raadt
+and
+.An Dug Song
removed many bugs, re-added newer features and
created OpenSSH.
-Markus Friedl contributed the support for SSH
-protocol versions 1.5 and 2.0.
+.An Markus Friedl
+contributed the support for SSH protocol versions 1.5 and 2.0.
diff --git a/sshbuf-getput-basic.c b/sshbuf-getput-basic.c
index 8ff8a0a2..da834d00 100644
--- a/sshbuf-getput-basic.c
+++ b/sshbuf-getput-basic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshbuf-getput-basic.c,v 1.4 2015/01/14 15:02:39 djm Exp $ */
+/* $OpenBSD: sshbuf-getput-basic.c,v 1.10 2019/12/13 19:09:37 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -19,9 +19,14 @@
#include "includes.h"
#include <sys/types.h>
+
+#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
#include "ssherr.h"
#include "sshbuf.h"
@@ -91,6 +96,93 @@ sshbuf_get_u8(struct sshbuf *buf, u_char *valp)
return 0;
}
+static int
+check_offset(const struct sshbuf *buf, int wr, size_t offset, size_t len)
+{
+ if (sshbuf_ptr(buf) == NULL) /* calls sshbuf_check_sanity() */
+ return SSH_ERR_INTERNAL_ERROR;
+ if (offset >= SIZE_MAX - len)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (offset + len > sshbuf_len(buf)) {
+ return wr ?
+ SSH_ERR_NO_BUFFER_SPACE : SSH_ERR_MESSAGE_INCOMPLETE;
+ }
+ return 0;
+}
+
+static int
+check_roffset(const struct sshbuf *buf, size_t offset, size_t len,
+ const u_char **p)
+{
+ int r;
+
+ *p = NULL;
+ if ((r = check_offset(buf, 0, offset, len)) != 0)
+ return r;
+ *p = sshbuf_ptr(buf) + offset;
+ return 0;
+}
+
+int
+sshbuf_peek_u64(const struct sshbuf *buf, size_t offset, u_int64_t *valp)
+{
+ const u_char *p = NULL;
+ int r;
+
+ if (valp != NULL)
+ *valp = 0;
+ if ((r = check_roffset(buf, offset, 8, &p)) != 0)
+ return r;
+ if (valp != NULL)
+ *valp = PEEK_U64(p);
+ return 0;
+}
+
+int
+sshbuf_peek_u32(const struct sshbuf *buf, size_t offset, u_int32_t *valp)
+{
+ const u_char *p = NULL;
+ int r;
+
+ if (valp != NULL)
+ *valp = 0;
+ if ((r = check_roffset(buf, offset, 4, &p)) != 0)
+ return r;
+ if (valp != NULL)
+ *valp = PEEK_U32(p);
+ return 0;
+}
+
+int
+sshbuf_peek_u16(const struct sshbuf *buf, size_t offset, u_int16_t *valp)
+{
+ const u_char *p = NULL;
+ int r;
+
+ if (valp != NULL)
+ *valp = 0;
+ if ((r = check_roffset(buf, offset, 2, &p)) != 0)
+ return r;
+ if (valp != NULL)
+ *valp = PEEK_U16(p);
+ return 0;
+}
+
+int
+sshbuf_peek_u8(const struct sshbuf *buf, size_t offset, u_char *valp)
+{
+ const u_char *p = NULL;
+ int r;
+
+ if (valp != NULL)
+ *valp = 0;
+ if ((r = check_roffset(buf, offset, 1, &p)) != 0)
+ return r;
+ if (valp != NULL)
+ *valp = *p;
+ return 0;
+}
+
int
sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp)
{
@@ -131,7 +223,7 @@ sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, size_t *lenp)
*lenp = 0;
if ((r = sshbuf_peek_string_direct(buf, &p, &len)) < 0)
return r;
- if (valp != 0)
+ if (valp != NULL)
*valp = p;
if (lenp != NULL)
*lenp = len;
@@ -168,7 +260,7 @@ sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp,
SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE"));
return SSH_ERR_MESSAGE_INCOMPLETE;
}
- if (valp != 0)
+ if (valp != NULL)
*valp = p + 4;
if (lenp != NULL)
*lenp = len;
@@ -268,7 +360,7 @@ sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap)
int r, len;
u_char *p;
- va_copy(ap2, ap);
+ VA_COPY(ap2, ap);
if ((len = vsnprintf(NULL, 0, fmt, ap2)) < 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
@@ -278,7 +370,7 @@ sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap)
goto out; /* Nothing to do */
}
va_end(ap2);
- va_copy(ap2, ap);
+ VA_COPY(ap2, ap);
if ((r = sshbuf_reserve(buf, (size_t)len + 1, &p)) < 0)
goto out;
if ((r = vsnprintf((char *)p, len + 1, fmt, ap2)) != len) {
@@ -342,6 +434,80 @@ sshbuf_put_u8(struct sshbuf *buf, u_char val)
return 0;
}
+static int
+check_woffset(struct sshbuf *buf, size_t offset, size_t len, u_char **p)
+{
+ int r;
+
+ *p = NULL;
+ if ((r = check_offset(buf, 1, offset, len)) != 0)
+ return r;
+ if (sshbuf_mutable_ptr(buf) == NULL)
+ return SSH_ERR_BUFFER_READ_ONLY;
+ *p = sshbuf_mutable_ptr(buf) + offset;
+ return 0;
+}
+
+int
+sshbuf_poke_u64(struct sshbuf *buf, size_t offset, u_int64_t val)
+{
+ u_char *p = NULL;
+ int r;
+
+ if ((r = check_woffset(buf, offset, 8, &p)) != 0)
+ return r;
+ POKE_U64(p, val);
+ return 0;
+}
+
+int
+sshbuf_poke_u32(struct sshbuf *buf, size_t offset, u_int32_t val)
+{
+ u_char *p = NULL;
+ int r;
+
+ if ((r = check_woffset(buf, offset, 4, &p)) != 0)
+ return r;
+ POKE_U32(p, val);
+ return 0;
+}
+
+int
+sshbuf_poke_u16(struct sshbuf *buf, size_t offset, u_int16_t val)
+{
+ u_char *p = NULL;
+ int r;
+
+ if ((r = check_woffset(buf, offset, 2, &p)) != 0)
+ return r;
+ POKE_U16(p, val);
+ return 0;
+}
+
+int
+sshbuf_poke_u8(struct sshbuf *buf, size_t offset, u_char val)
+{
+ u_char *p = NULL;
+ int r;
+
+ if ((r = check_woffset(buf, offset, 1, &p)) != 0)
+ return r;
+ *p = val;
+ return 0;
+}
+
+int
+sshbuf_poke(struct sshbuf *buf, size_t offset, void *v, size_t len)
+{
+ u_char *p = NULL;
+ int r;
+
+ if ((r = check_woffset(buf, offset, len, &p)) != 0)
+ return r;
+ memcpy(p, v, len);
+ return 0;
+}
+
int
sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len)
{
@@ -363,12 +529,15 @@ sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len)
int
sshbuf_put_cstring(struct sshbuf *buf, const char *v)
{
- return sshbuf_put_string(buf, (u_char *)v, v == NULL ? 0 : strlen(v));
+ return sshbuf_put_string(buf, v, v == NULL ? 0 : strlen(v));
}
int
sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v)
{
+ if (v == NULL)
+ return sshbuf_put_string(buf, NULL, 0);
+
return sshbuf_put_string(buf, sshbuf_ptr(v), sshbuf_len(v));
}
@@ -448,7 +617,7 @@ sshbuf_get_bignum2_bytes_direct(struct sshbuf *buf,
d++;
len--;
}
- if (valp != 0)
+ if (valp != NULL)
*valp = d;
if (lenp != NULL)
*lenp = len;
diff --git a/sshbuf-getput-crypto.c b/sshbuf-getput-crypto.c
index e2e093c0..2e61d3bc 100644
--- a/sshbuf-getput-crypto.c
+++ b/sshbuf-getput-crypto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshbuf-getput-crypto.c,v 1.4 2015/01/14 15:02:39 djm Exp $ */
+/* $OpenBSD: sshbuf-getput-crypto.c,v 1.8 2019/11/15 06:00:20 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <string.h>
+#ifdef WITH_OPENSSL
#include <openssl/bn.h>
#ifdef OPENSSL_HAS_ECC
# include <openssl/ec.h>
@@ -32,41 +33,24 @@
#include "sshbuf.h"
int
-sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM *v)
+sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM **valp)
{
+ BIGNUM *v;
const u_char *d;
size_t len;
int r;
+ if (valp != NULL)
+ *valp = NULL;
if ((r = sshbuf_get_bignum2_bytes_direct(buf, &d, &len)) != 0)
return r;
- if (v != NULL && BN_bin2bn(d, len, v) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- return 0;
-}
-
-int
-sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v)
-{
- const u_char *d = sshbuf_ptr(buf);
- u_int16_t len_bits;
- size_t len_bytes;
-
- /* Length in bits */
- if (sshbuf_len(buf) < 2)
- return SSH_ERR_MESSAGE_INCOMPLETE;
- len_bits = PEEK_U16(d);
- len_bytes = (len_bits + 7) >> 3;
- if (len_bytes > SSHBUF_MAX_BIGNUM)
- return SSH_ERR_BIGNUM_TOO_LARGE;
- if (sshbuf_len(buf) < 2 + len_bytes)
- return SSH_ERR_MESSAGE_INCOMPLETE;
- if (v != NULL && BN_bin2bn(d + 2, len_bytes, v) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if (sshbuf_consume(buf, 2 + len_bytes) != 0) {
- SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
- SSHBUF_ABORT();
- return SSH_ERR_INTERNAL_ERROR;
+ if (valp != NULL) {
+ if ((v = BN_new()) == NULL ||
+ BN_bin2bn(d, len, v) == NULL) {
+ BN_clear_free(v);
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ *valp = v;
}
return 0;
}
@@ -158,32 +142,10 @@ sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v)
if (len > 0 && (d[1] & 0x80) != 0)
prepend = 1;
if ((r = sshbuf_put_string(buf, d + 1 - prepend, len + prepend)) < 0) {
- bzero(d, sizeof(d));
- return r;
- }
- bzero(d, sizeof(d));
- return 0;
-}
-
-int
-sshbuf_put_bignum1(struct sshbuf *buf, const BIGNUM *v)
-{
- int r, len_bits = BN_num_bits(v);
- size_t len_bytes = (len_bits + 7) / 8;
- u_char d[SSHBUF_MAX_BIGNUM], *dp;
-
- if (len_bits < 0 || len_bytes > SSHBUF_MAX_BIGNUM)
- return SSH_ERR_INVALID_ARGUMENT;
- if (BN_bn2bin(v, d) != (int)len_bytes)
- return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
- if ((r = sshbuf_reserve(buf, len_bytes + 2, &dp)) < 0) {
- bzero(d, sizeof(d));
+ explicit_bzero(d, sizeof(d));
return r;
}
- POKE_U16(dp, len_bits);
- if (len_bytes != 0)
- memcpy(dp + 2, d, len_bytes);
- bzero(d, sizeof(d));
+ explicit_bzero(d, sizeof(d));
return 0;
}
@@ -192,25 +154,19 @@ int
sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g)
{
u_char d[SSHBUF_MAX_ECPOINT];
- BN_CTX *bn_ctx;
size_t len;
int ret;
- if ((bn_ctx = BN_CTX_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
if ((len = EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
- NULL, 0, bn_ctx)) > SSHBUF_MAX_ECPOINT) {
- BN_CTX_free(bn_ctx);
+ NULL, 0, NULL)) > SSHBUF_MAX_ECPOINT) {
return SSH_ERR_INVALID_ARGUMENT;
}
if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
- d, len, bn_ctx) != len) {
- BN_CTX_free(bn_ctx);
+ d, len, NULL) != len) {
return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
}
- BN_CTX_free(bn_ctx);
ret = sshbuf_put_string(buf, d, len);
- bzero(d, len);
+ explicit_bzero(d, len);
return ret;
}
@@ -221,4 +177,4 @@ sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v)
EC_KEY_get0_group(v));
}
#endif /* OPENSSL_HAS_ECC */
-
+#endif /* WITH_OPENSSL */
diff --git a/sshbuf-io.c b/sshbuf-io.c
new file mode 100644
index 00000000..13ef40e7
--- /dev/null
+++ b/sshbuf-io.c
@@ -0,0 +1,117 @@
+/* $OpenBSD: sshbuf-io.c,v 1.2 2020/01/25 23:28:06 djm Exp $ */
+/*
+ * Copyright (c) 2011 Damien Miller
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ssherr.h"
+#include "sshbuf.h"
+#include "atomicio.h"
+
+/* Load a file from a fd into a buffer */
+int
+sshbuf_load_fd(int fd, struct sshbuf **blobp)
+{
+ u_char buf[4096];
+ size_t len;
+ struct stat st;
+ int r;
+ struct sshbuf *blob;
+
+ *blobp = NULL;
+
+ if (fstat(fd, &st) == -1)
+ return SSH_ERR_SYSTEM_ERROR;
+ if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
+ st.st_size > SSHBUF_SIZE_MAX)
+ return SSH_ERR_INVALID_FORMAT;
+ if ((blob = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ for (;;) {
+ if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
+ if (errno == EPIPE)
+ break;
+ r = SSH_ERR_SYSTEM_ERROR;
+ goto out;
+ }
+ if ((r = sshbuf_put(blob, buf, len)) != 0)
+ goto out;
+ if (sshbuf_len(blob) > SSHBUF_SIZE_MAX) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ }
+ if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
+ st.st_size != (off_t)sshbuf_len(blob)) {
+ r = SSH_ERR_FILE_CHANGED;
+ goto out;
+ }
+ /* success */
+ *blobp = blob;
+ blob = NULL; /* transferred */
+ r = 0;
+ out:
+ explicit_bzero(buf, sizeof(buf));
+ sshbuf_free(blob);
+ return r;
+}
+
+int
+sshbuf_load_file(const char *path, struct sshbuf **bufp)
+{
+ int r, fd, oerrno;
+
+ *bufp = NULL;
+ if ((fd = open(path, O_RDONLY)) == -1)
+ return SSH_ERR_SYSTEM_ERROR;
+ if ((r = sshbuf_load_fd(fd, bufp)) != 0)
+ goto out;
+ /* success */
+ r = 0;
+ out:
+ oerrno = errno;
+ close(fd);
+ if (r != 0)
+ errno = oerrno;
+ return r;
+}
+
+int
+sshbuf_write_file(const char *path, struct sshbuf *buf)
+{
+ int fd, oerrno;
+
+ if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1)
+ return SSH_ERR_SYSTEM_ERROR;
+ if (atomicio(vwrite, fd, sshbuf_mutable_ptr(buf),
+ sshbuf_len(buf)) != sshbuf_len(buf) || close(fd) != 0) {
+ oerrno = errno;
+ close(fd);
+ unlink(path);
+ errno = oerrno;
+ return SSH_ERR_SYSTEM_ERROR;
+ }
+ return 0;
+}
+
diff --git a/sshbuf-misc.c b/sshbuf-misc.c
index f1c2d03c..9b5aa208 100644
--- a/sshbuf-misc.c
+++ b/sshbuf-misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshbuf-misc.c,v 1.3 2015/02/05 12:59:57 millert Exp $ */
+/* $OpenBSD: sshbuf-misc.c,v 1.14 2020/02/26 13:40:09 jsg Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -23,7 +23,7 @@
#include <errno.h>
#include <stdlib.h>
#ifdef HAVE_STDINT_H
-#include <stdint.h>
+# include <stdint.h>
#endif
#include <stdio.h>
#include <limits.h>
@@ -42,7 +42,7 @@ sshbuf_dump_data(const void *s, size_t len, FILE *f)
const u_char *p = (const u_char *)s;
for (i = 0; i < len; i += 16) {
- fprintf(f, "%.4zd: ", i);
+ fprintf(f, "%.4zu: ", i);
for (j = i; j < i + 16; j++) {
if (j < len)
fprintf(f, "%02x ", p[j]);
@@ -89,24 +89,58 @@ sshbuf_dtob16(struct sshbuf *buf)
return ret;
}
+int
+sshbuf_dtob64(const struct sshbuf *d, struct sshbuf *b64, int wrap)
+{
+ size_t i, slen = 0;
+ char *s = NULL;
+ int r;
+
+ if (d == NULL || b64 == NULL || sshbuf_len(d) >= SIZE_MAX / 2)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (sshbuf_len(d) == 0)
+ return 0;
+ slen = ((sshbuf_len(d) + 2) / 3) * 4 + 1;
+ if ((s = malloc(slen)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if (b64_ntop(sshbuf_ptr(d), sshbuf_len(d), s, slen) == -1) {
+ r = SSH_ERR_INTERNAL_ERROR;
+ goto fail;
+ }
+ if (wrap) {
+ for (i = 0; s[i] != '\0'; i++) {
+ if ((r = sshbuf_put_u8(b64, s[i])) != 0)
+ goto fail;
+ if (i % 70 == 69 && (r = sshbuf_put_u8(b64, '\n')) != 0)
+ goto fail;
+ }
+ if ((i - 1) % 70 != 69 && (r = sshbuf_put_u8(b64, '\n')) != 0)
+ goto fail;
+ } else {
+ if ((r = sshbuf_put(b64, s, strlen(s))) != 0)
+ goto fail;
+ }
+ /* Success */
+ r = 0;
+ fail:
+ freezero(s, slen);
+ return r;
+}
+
char *
-sshbuf_dtob64(struct sshbuf *buf)
+sshbuf_dtob64_string(const struct sshbuf *buf, int wrap)
{
- size_t len = sshbuf_len(buf), plen;
- const u_char *p = sshbuf_ptr(buf);
+ struct sshbuf *tmp;
char *ret;
- int r;
- if (len == 0)
- return strdup("");
- plen = ((len + 2) / 3) * 4 + 1;
- if (SIZE_MAX / 2 <= len || (ret = malloc(plen)) == NULL)
+ if ((tmp = sshbuf_new()) == NULL)
return NULL;
- if ((r = b64_ntop(p, len, ret, plen)) == -1) {
- bzero(ret, plen);
- free(ret);
+ if (sshbuf_dtob64(buf, tmp, wrap) != 0) {
+ sshbuf_free(tmp);
return NULL;
}
+ ret = sshbuf_dup_string(tmp);
+ sshbuf_free(tmp);
return ret;
}
@@ -122,17 +156,73 @@ sshbuf_b64tod(struct sshbuf *buf, const char *b64)
if ((p = malloc(plen)) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((nlen = b64_pton(b64, p, plen)) < 0) {
- bzero(p, plen);
- free(p);
+ freezero(p, plen);
return SSH_ERR_INVALID_FORMAT;
}
if ((r = sshbuf_put(buf, p, nlen)) < 0) {
- bzero(p, plen);
- free(p);
+ freezero(p, plen);
return r;
}
- bzero(p, plen);
- free(p);
+ freezero(p, plen);
return 0;
}
+char *
+sshbuf_dup_string(struct sshbuf *buf)
+{
+ const u_char *p = NULL, *s = sshbuf_ptr(buf);
+ size_t l = sshbuf_len(buf);
+ char *r;
+
+ if (s == NULL || l > SIZE_MAX)
+ return NULL;
+ /* accept a nul only as the last character in the buffer */
+ if (l > 0 && (p = memchr(s, '\0', l)) != NULL) {
+ if (p != s + l - 1)
+ return NULL;
+ l--; /* the nul is put back below */
+ }
+ if ((r = malloc(l + 1)) == NULL)
+ return NULL;
+ if (l > 0)
+ memcpy(r, s, l);
+ r[l] = '\0';
+ return r;
+}
+
+int
+sshbuf_cmp(const struct sshbuf *b, size_t offset,
+ const void *s, size_t len)
+{
+ if (sshbuf_ptr(b) == NULL)
+ return SSH_ERR_INTERNAL_ERROR;
+ if (offset > SSHBUF_SIZE_MAX || len > SSHBUF_SIZE_MAX || len == 0)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (offset + len > sshbuf_len(b))
+ return SSH_ERR_MESSAGE_INCOMPLETE;
+ if (timingsafe_bcmp(sshbuf_ptr(b) + offset, s, len) != 0)
+ return SSH_ERR_INVALID_FORMAT;
+ return 0;
+}
+
+int
+sshbuf_find(const struct sshbuf *b, size_t start_offset,
+ const void *s, size_t len, size_t *offsetp)
+{
+ void *p;
+
+ if (offsetp != NULL)
+ *offsetp = 0;
+ if (sshbuf_ptr(b) == NULL)
+ return SSH_ERR_INTERNAL_ERROR;
+ if (start_offset > SSHBUF_SIZE_MAX || len > SSHBUF_SIZE_MAX || len == 0)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (start_offset > sshbuf_len(b) || start_offset + len > sshbuf_len(b))
+ return SSH_ERR_MESSAGE_INCOMPLETE;
+ if ((p = memmem(sshbuf_ptr(b) + start_offset,
+ sshbuf_len(b) - start_offset, s, len)) == NULL)
+ return SSH_ERR_INVALID_FORMAT;
+ if (offsetp != NULL)
+ *offsetp = (const u_char *)p - sshbuf_ptr(b);
+ return 0;
+}
diff --git a/sshbuf.c b/sshbuf.c
index dbe0c919..368ba798 100644
--- a/sshbuf.c
+++ b/sshbuf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshbuf.c,v 1.3 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: sshbuf.c,v 1.15 2020/02/26 13:40:09 jsg Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -18,7 +18,6 @@
#define SSHBUF_INTERNAL
#include "includes.h"
-#include <sys/param.h> /* roundup */
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
@@ -27,6 +26,7 @@
#include "ssherr.h"
#include "sshbuf.h"
+#include "misc.h"
static inline int
sshbuf_check_sanity(const struct sshbuf *buf)
@@ -36,14 +36,13 @@ sshbuf_check_sanity(const struct sshbuf *buf)
(!buf->readonly && buf->d != buf->cd) ||
buf->refcount < 1 || buf->refcount > SSHBUF_REFS_MAX ||
buf->cd == NULL ||
- (buf->dont_free && (buf->readonly || buf->parent != NULL)) ||
buf->max_size > SSHBUF_SIZE_MAX ||
buf->alloc > buf->max_size ||
buf->size > buf->alloc ||
buf->off > buf->size)) {
/* Do not try to recover from corrupted buffer internals */
SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
- signal(SIGSEGV, SIG_DFL);
+ ssh_signal(SIGSEGV, SIG_DFL);
raise(SIGSEGV);
return SSH_ERR_INTERNAL_ERROR;
}
@@ -132,23 +131,8 @@ sshbuf_fromb(struct sshbuf *buf)
}
void
-sshbuf_init(struct sshbuf *ret)
-{
- bzero(ret, sizeof(*ret));
- ret->alloc = SSHBUF_SIZE_INIT;
- ret->max_size = SSHBUF_SIZE_MAX;
- ret->readonly = 0;
- ret->dont_free = 1;
- ret->refcount = 1;
- if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL)
- ret->alloc = 0;
-}
-
-void
sshbuf_free(struct sshbuf *buf)
{
- int dont_free = 0;
-
if (buf == NULL)
return;
/*
@@ -159,14 +143,7 @@ sshbuf_free(struct sshbuf *buf)
*/
if (sshbuf_check_sanity(buf) != 0)
return;
- /*
- * If we are a child, the free our parent to decrement its reference
- * count and possibly free it.
- */
- if (buf->parent != NULL) {
- sshbuf_free(buf->parent);
- buf->parent = NULL;
- }
+
/*
* If we are a parent with still-extant children, then don't free just
* yet. The last child's call to sshbuf_free should decrement our
@@ -175,14 +152,19 @@ sshbuf_free(struct sshbuf *buf)
buf->refcount--;
if (buf->refcount > 0)
return;
- dont_free = buf->dont_free;
+
+ /*
+ * If we are a child, the free our parent to decrement its reference
+ * count and possibly free it.
+ */
+ sshbuf_free(buf->parent);
+ buf->parent = NULL;
+
if (!buf->readonly) {
- bzero(buf->d, buf->alloc);
+ explicit_bzero(buf->d, buf->alloc);
free(buf->d);
}
- bzero(buf, sizeof(*buf));
- if (!dont_free)
- free(buf);
+ freezero(buf, sizeof(*buf));
}
void
@@ -195,15 +177,16 @@ sshbuf_reset(struct sshbuf *buf)
buf->off = buf->size;
return;
}
- if (sshbuf_check_sanity(buf) == 0)
- bzero(buf->d, buf->alloc);
+ (void) sshbuf_check_sanity(buf);
buf->off = buf->size = 0;
if (buf->alloc != SSHBUF_SIZE_INIT) {
- if ((d = realloc(buf->d, SSHBUF_SIZE_INIT)) != NULL) {
+ if ((d = recallocarray(buf->d, buf->alloc, SSHBUF_SIZE_INIT,
+ 1)) != NULL) {
buf->cd = buf->d = d;
buf->alloc = SSHBUF_SIZE_INIT;
}
}
+ explicit_bzero(buf->d, SSHBUF_SIZE_INIT);
}
size_t
@@ -252,12 +235,11 @@ sshbuf_set_max_size(struct sshbuf *buf, size_t max_size)
if (buf->size < SSHBUF_SIZE_INIT)
rlen = SSHBUF_SIZE_INIT;
else
- rlen = roundup(buf->size, SSHBUF_SIZE_INC);
+ rlen = ROUNDUP(buf->size, SSHBUF_SIZE_INC);
if (rlen > max_size)
rlen = max_size;
- bzero(buf->d + buf->size, buf->alloc - buf->size);
SSHBUF_DBG(("new alloc = %zu", rlen));
- if ((dp = realloc(buf->d, rlen)) == NULL)
+ if ((dp = recallocarray(buf->d, buf->alloc, rlen, 1)) == NULL)
return SSH_ERR_ALLOC_FAIL;
buf->cd = buf->d = dp;
buf->alloc = rlen;
@@ -318,16 +300,13 @@ sshbuf_check_reserve(const struct sshbuf *buf, size_t len)
}
int
-sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp)
+sshbuf_allocate(struct sshbuf *buf, size_t len)
{
size_t rlen, need;
u_char *dp;
int r;
- if (dpp != NULL)
- *dpp = NULL;
-
- SSHBUF_DBG(("reserve buf = %p len = %zu", buf, len));
+ SSHBUF_DBG(("allocate buf = %p len = %zu", buf, len));
if ((r = sshbuf_check_reserve(buf, len)) != 0)
return r;
/*
@@ -335,36 +314,49 @@ sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp)
* then pack the buffer, zeroing buf->off.
*/
sshbuf_maybe_pack(buf, buf->size + len > buf->max_size);
- SSHBUF_TELL("reserve");
- if (len + buf->size > buf->alloc) {
- /*
- * Prefer to alloc in SSHBUF_SIZE_INC units, but
- * allocate less if doing so would overflow max_size.
- */
- need = len + buf->size - buf->alloc;
- rlen = roundup(buf->alloc + need, SSHBUF_SIZE_INC);
- SSHBUF_DBG(("need %zu initial rlen %zu", need, rlen));
- if (rlen > buf->max_size)
- rlen = buf->alloc + need;
- SSHBUF_DBG(("adjusted rlen %zu", rlen));
- if ((dp = realloc(buf->d, rlen)) == NULL) {
- SSHBUF_DBG(("realloc fail"));
- if (dpp != NULL)
- *dpp = NULL;
- return SSH_ERR_ALLOC_FAIL;
- }
- buf->alloc = rlen;
- buf->cd = buf->d = dp;
- if ((r = sshbuf_check_reserve(buf, len)) < 0) {
- /* shouldn't fail */
- if (dpp != NULL)
- *dpp = NULL;
- return r;
- }
+ SSHBUF_TELL("allocate");
+ if (len + buf->size <= buf->alloc)
+ return 0; /* already have it. */
+
+ /*
+ * Prefer to alloc in SSHBUF_SIZE_INC units, but
+ * allocate less if doing so would overflow max_size.
+ */
+ need = len + buf->size - buf->alloc;
+ rlen = ROUNDUP(buf->alloc + need, SSHBUF_SIZE_INC);
+ SSHBUF_DBG(("need %zu initial rlen %zu", need, rlen));
+ if (rlen > buf->max_size)
+ rlen = buf->alloc + need;
+ SSHBUF_DBG(("adjusted rlen %zu", rlen));
+ if ((dp = recallocarray(buf->d, buf->alloc, rlen, 1)) == NULL) {
+ SSHBUF_DBG(("realloc fail"));
+ return SSH_ERR_ALLOC_FAIL;
}
+ buf->alloc = rlen;
+ buf->cd = buf->d = dp;
+ if ((r = sshbuf_check_reserve(buf, len)) < 0) {
+ /* shouldn't fail */
+ return r;
+ }
+ SSHBUF_TELL("done");
+ return 0;
+}
+
+int
+sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp)
+{
+ u_char *dp;
+ int r;
+
+ if (dpp != NULL)
+ *dpp = NULL;
+
+ SSHBUF_DBG(("reserve buf = %p len = %zu", buf, len));
+ if ((r = sshbuf_allocate(buf, len)) != 0)
+ return r;
+
dp = buf->d + buf->size;
buf->size += len;
- SSHBUF_TELL("done");
if (dpp != NULL)
*dpp = dp;
return 0;
@@ -383,6 +375,9 @@ sshbuf_consume(struct sshbuf *buf, size_t len)
if (len > sshbuf_len(buf))
return SSH_ERR_MESSAGE_INCOMPLETE;
buf->off += len;
+ /* deal with empty buffer */
+ if (buf->off == buf->size)
+ buf->off = buf->size = 0;
SSHBUF_TELL("done");
return 0;
}
diff --git a/sshbuf.h b/sshbuf.h
index eb0d92e1..94392c8b 100644
--- a/sshbuf.h
+++ b/sshbuf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshbuf.h,v 1.4 2015/01/14 15:02:39 djm Exp $ */
+/* $OpenBSD: sshbuf.h,v 1.21 2020/04/26 09:38:14 dtucker Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -50,15 +50,6 @@ struct sshbuf {
struct sshbuf *parent; /* If child, pointer to parent */
};
-#ifndef SSHBUF_NO_DEPREACTED
-/*
- * NB. Please do not use sshbuf_init() in new code. Please use sshbuf_new()
- * instead. sshbuf_init() is deprectated and will go away soon (it is
- * only included to allow compat with buffer_* in OpenSSH)
- */
-void sshbuf_init(struct sshbuf *buf);
-#endif
-
/*
* Create a new sshbuf buffer.
* Returns pointer to buffer on success, or NULL on allocation failure.
@@ -120,12 +111,12 @@ size_t sshbuf_len(const struct sshbuf *buf);
size_t sshbuf_avail(const struct sshbuf *buf);
/*
- * Returns a read-only pointer to the start of the the data in buf
+ * Returns a read-only pointer to the start of the data in buf
*/
const u_char *sshbuf_ptr(const struct sshbuf *buf);
/*
- * Returns a mutable pointer to the start of the the data in buf, or
+ * Returns a mutable pointer to the start of the data in buf, or
* NULL if the buffer is read-only.
*/
u_char *sshbuf_mutable_ptr(const struct sshbuf *buf);
@@ -139,9 +130,17 @@ u_char *sshbuf_mutable_ptr(const struct sshbuf *buf);
int sshbuf_check_reserve(const struct sshbuf *buf, size_t len);
/*
+ * Preallocates len additional bytes in buf.
+ * Useful for cases where the caller knows how many bytes will ultimately be
+ * required to avoid realloc in the buffer code.
+ * Returns 0 on success, or a negative SSH_ERR_* error code on failure.
+ */
+int sshbuf_allocate(struct sshbuf *buf, size_t len);
+
+/*
* Reserve len bytes in buf.
* Returns 0 on success and a pointer to the first reserved byte via the
- * optional dpp parameter or a negative * SSH_ERR_* error code on failure.
+ * optional dpp parameter or a negative SSH_ERR_* error code on failure.
*/
int sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp);
@@ -177,6 +176,26 @@ int sshbuf_put_u32(struct sshbuf *buf, u_int32_t val);
int sshbuf_put_u16(struct sshbuf *buf, u_int16_t val);
int sshbuf_put_u8(struct sshbuf *buf, u_char val);
+/* Functions to peek at the contents of a buffer without modifying it. */
+int sshbuf_peek_u64(const struct sshbuf *buf, size_t offset,
+ u_int64_t *valp);
+int sshbuf_peek_u32(const struct sshbuf *buf, size_t offset,
+ u_int32_t *valp);
+int sshbuf_peek_u16(const struct sshbuf *buf, size_t offset,
+ u_int16_t *valp);
+int sshbuf_peek_u8(const struct sshbuf *buf, size_t offset,
+ u_char *valp);
+
+/*
+ * Functions to poke values into an existing buffer (e.g. a length header
+ * to a packet). The destination bytes must already exist in the buffer.
+ */
+int sshbuf_poke_u64(struct sshbuf *buf, size_t offset, u_int64_t val);
+int sshbuf_poke_u32(struct sshbuf *buf, size_t offset, u_int32_t val);
+int sshbuf_poke_u16(struct sshbuf *buf, size_t offset, u_int16_t val);
+int sshbuf_poke_u8(struct sshbuf *buf, size_t offset, u_char val);
+int sshbuf_poke(struct sshbuf *buf, size_t offset, void *v, size_t len);
+
/*
* Functions to extract or store SSH wire encoded strings (u32 len || data)
* The "cstring" variants admit no \0 characters in the string contents.
@@ -212,10 +231,8 @@ int sshbuf_put_bignum2_bytes(struct sshbuf *buf, const void *v, size_t len);
int sshbuf_get_bignum2_bytes_direct(struct sshbuf *buf,
const u_char **valp, size_t *lenp);
#ifdef WITH_OPENSSL
-int sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM *v);
-int sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v);
+int sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM **valp);
int sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v);
-int sshbuf_put_bignum1(struct sshbuf *buf, const BIGNUM *v);
# ifdef OPENSSL_HAS_ECC
int sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g);
int sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v);
@@ -234,52 +251,106 @@ void sshbuf_dump_data(const void *s, size_t len, FILE *f);
char *sshbuf_dtob16(struct sshbuf *buf);
/* Encode the contents of the buffer as base64 */
-char *sshbuf_dtob64(struct sshbuf *buf);
+char *sshbuf_dtob64_string(const struct sshbuf *buf, int wrap);
+int sshbuf_dtob64(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);
+/*
+ * Tests whether the buffer contains the specified byte sequence at the
+ * specified offset. Returns 0 on successful match, or a ssherr.h code
+ * otherwise. SSH_ERR_INVALID_FORMAT indicates sufficient bytes were
+ * present but the buffer contents did not match those supplied. Zero-
+ * length comparisons are not allowed.
+ *
+ * If sufficient data is present to make a comparison, then it is
+ * performed with timing independent of the value of the data. If
+ * insufficient data is present then the comparison is not attempted at
+ * all.
+ */
+int sshbuf_cmp(const struct sshbuf *b, size_t offset,
+ const void *s, size_t len);
+
+/*
+ * Searches the buffer for the specified string. Returns 0 on success
+ * and updates *offsetp with the offset of the first match, relative to
+ * the start of the buffer. Otherwise sshbuf_find will return a ssherr.h
+ * error code. SSH_ERR_INVALID_FORMAT indicates sufficient bytes were
+ * present in the buffer for a match to be possible but none was found.
+ * Searches for zero-length data are not allowed.
+ */
+int
+sshbuf_find(const struct sshbuf *b, size_t start_offset,
+ const void *s, size_t len, size_t *offsetp);
+
+/*
+ * Duplicate the contents of a buffer to a string (caller to free).
+ * Returns NULL on buffer error, or if the buffer contains a premature
+ * nul character.
+ */
+char *sshbuf_dup_string(struct sshbuf *buf);
+
+/*
+ * Fill a buffer from a file descriptor or filename. Both allocate the
+ * buffer for the caller.
+ */
+int sshbuf_load_fd(int, struct sshbuf **)
+ __attribute__((__nonnull__ (2)));
+int sshbuf_load_file(const char *, struct sshbuf **)
+ __attribute__((__nonnull__ (2)));
+
+/*
+ * Write a buffer to a path, creating/truncating as needed (mode 0644,
+ * subject to umask). The buffer contents are not modified.
+ */
+int sshbuf_write_file(const char *path, struct sshbuf *buf)
+ __attribute__((__nonnull__ (2)));
+
/* Macros for decoding/encoding integers */
#define PEEK_U64(p) \
- (((u_int64_t)(((u_char *)(p))[0]) << 56) | \
- ((u_int64_t)(((u_char *)(p))[1]) << 48) | \
- ((u_int64_t)(((u_char *)(p))[2]) << 40) | \
- ((u_int64_t)(((u_char *)(p))[3]) << 32) | \
- ((u_int64_t)(((u_char *)(p))[4]) << 24) | \
- ((u_int64_t)(((u_char *)(p))[5]) << 16) | \
- ((u_int64_t)(((u_char *)(p))[6]) << 8) | \
- (u_int64_t)(((u_char *)(p))[7]))
+ (((u_int64_t)(((const u_char *)(p))[0]) << 56) | \
+ ((u_int64_t)(((const u_char *)(p))[1]) << 48) | \
+ ((u_int64_t)(((const u_char *)(p))[2]) << 40) | \
+ ((u_int64_t)(((const u_char *)(p))[3]) << 32) | \
+ ((u_int64_t)(((const u_char *)(p))[4]) << 24) | \
+ ((u_int64_t)(((const u_char *)(p))[5]) << 16) | \
+ ((u_int64_t)(((const u_char *)(p))[6]) << 8) | \
+ (u_int64_t)(((const u_char *)(p))[7]))
#define PEEK_U32(p) \
- (((u_int32_t)(((u_char *)(p))[0]) << 24) | \
- ((u_int32_t)(((u_char *)(p))[1]) << 16) | \
- ((u_int32_t)(((u_char *)(p))[2]) << 8) | \
- (u_int32_t)(((u_char *)(p))[3]))
+ (((u_int32_t)(((const u_char *)(p))[0]) << 24) | \
+ ((u_int32_t)(((const u_char *)(p))[1]) << 16) | \
+ ((u_int32_t)(((const u_char *)(p))[2]) << 8) | \
+ (u_int32_t)(((const u_char *)(p))[3]))
#define PEEK_U16(p) \
- (((u_int16_t)(((u_char *)(p))[0]) << 8) | \
- (u_int16_t)(((u_char *)(p))[1]))
+ (((u_int16_t)(((const u_char *)(p))[0]) << 8) | \
+ (u_int16_t)(((const u_char *)(p))[1]))
#define POKE_U64(p, v) \
do { \
- ((u_char *)(p))[0] = (((u_int64_t)(v)) >> 56) & 0xff; \
- ((u_char *)(p))[1] = (((u_int64_t)(v)) >> 48) & 0xff; \
- ((u_char *)(p))[2] = (((u_int64_t)(v)) >> 40) & 0xff; \
- ((u_char *)(p))[3] = (((u_int64_t)(v)) >> 32) & 0xff; \
- ((u_char *)(p))[4] = (((u_int64_t)(v)) >> 24) & 0xff; \
- ((u_char *)(p))[5] = (((u_int64_t)(v)) >> 16) & 0xff; \
- ((u_char *)(p))[6] = (((u_int64_t)(v)) >> 8) & 0xff; \
- ((u_char *)(p))[7] = ((u_int64_t)(v)) & 0xff; \
+ const u_int64_t __v = (v); \
+ ((u_char *)(p))[0] = (__v >> 56) & 0xff; \
+ ((u_char *)(p))[1] = (__v >> 48) & 0xff; \
+ ((u_char *)(p))[2] = (__v >> 40) & 0xff; \
+ ((u_char *)(p))[3] = (__v >> 32) & 0xff; \
+ ((u_char *)(p))[4] = (__v >> 24) & 0xff; \
+ ((u_char *)(p))[5] = (__v >> 16) & 0xff; \
+ ((u_char *)(p))[6] = (__v >> 8) & 0xff; \
+ ((u_char *)(p))[7] = __v & 0xff; \
} while (0)
#define POKE_U32(p, v) \
do { \
- ((u_char *)(p))[0] = (((u_int64_t)(v)) >> 24) & 0xff; \
- ((u_char *)(p))[1] = (((u_int64_t)(v)) >> 16) & 0xff; \
- ((u_char *)(p))[2] = (((u_int64_t)(v)) >> 8) & 0xff; \
- ((u_char *)(p))[3] = ((u_int64_t)(v)) & 0xff; \
+ const u_int32_t __v = (v); \
+ ((u_char *)(p))[0] = (__v >> 24) & 0xff; \
+ ((u_char *)(p))[1] = (__v >> 16) & 0xff; \
+ ((u_char *)(p))[2] = (__v >> 8) & 0xff; \
+ ((u_char *)(p))[3] = __v & 0xff; \
} while (0)
#define POKE_U16(p, v) \
do { \
- ((u_char *)(p))[0] = (((u_int64_t)(v)) >> 8) & 0xff; \
- ((u_char *)(p))[1] = ((u_int64_t)(v)) & 0xff; \
+ const u_int16_t __v = (v); \
+ ((u_char *)(p))[0] = (__v >> 8) & 0xff; \
+ ((u_char *)(p))[1] = __v & 0xff; \
} while (0)
/* Internal definitions follow. Exposed for regress tests */
diff --git a/sshconnect.c b/sshconnect.c
index 9e515066..af08be41 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.c,v 1.259 2015/01/28 22:36:00 djm Exp $ */
+/* $OpenBSD: sshconnect.c,v 1.329 2020/03/13 04:01:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -15,7 +15,6 @@
#include "includes.h"
-#include <sys/param.h> /* roundup */
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
@@ -24,6 +23,7 @@
# include <sys/time.h>
#endif
+#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -35,76 +35,98 @@
#include <paths.h>
#endif
#include <pwd.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
#include <signal.h>
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdarg.h>
#include <string.h>
#include <unistd.h>
+#ifdef HAVE_IFADDRS_H
+# include <ifaddrs.h>
+#endif
#include "xmalloc.h"
-#include "key.h"
#include "hostfile.h"
#include "ssh.h"
-#include "rsa.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "packet.h"
-#include "uidswap.h"
#include "compat.h"
-#include "key.h"
+#include "sshkey.h"
#include "sshconnect.h"
-#include "hostfile.h"
#include "log.h"
#include "misc.h"
#include "readconf.h"
#include "atomicio.h"
#include "dns.h"
-#include "roaming.h"
#include "monitor_fdpass.h"
#include "ssh2.h"
#include "version.h"
#include "authfile.h"
#include "ssherr.h"
+#include "authfd.h"
+#include "kex.h"
-char *client_version_string = NULL;
-char *server_version_string = NULL;
-Key *previous_host_key = NULL;
+struct sshkey *previous_host_key = NULL;
static int matching_host_key_dns = 0;
static pid_t proxy_command_pid = 0;
/* import */
+extern int debug_flag;
extern Options options;
extern char *__progname;
-extern uid_t original_real_uid;
-extern uid_t original_effective_uid;
-static int show_other_keys(struct hostkeys *, Key *);
-static void warn_changed_key(Key *);
+static int show_other_keys(struct hostkeys *, struct sshkey *);
+static void warn_changed_key(struct sshkey *);
/* Expand a proxy command */
static char *
expand_proxy_command(const char *proxy_command, const char *user,
- const char *host, int port)
+ const char *host, const char *host_arg, int port)
{
char *tmp, *ret, strport[NI_MAXSERV];
snprintf(strport, sizeof strport, "%d", port);
xasprintf(&tmp, "exec %s", proxy_command);
- ret = percent_expand(tmp, "h", host, "p", strport,
- "r", options.user, (char *)NULL);
+ ret = percent_expand(tmp,
+ "h", host,
+ "n", host_arg,
+ "p", strport,
+ "r", options.user,
+ (char *)NULL);
free(tmp);
return ret;
}
+static void
+stderr_null(void)
+{
+ int devnull;
+
+ if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1) {
+ error("Can't open %s for stderr redirection: %s",
+ _PATH_DEVNULL, strerror(errno));
+ return;
+ }
+ if (devnull == STDERR_FILENO)
+ return;
+ if (dup2(devnull, STDERR_FILENO) == -1)
+ error("Cannot redirect stderr to %s", _PATH_DEVNULL);
+ if (devnull > STDERR_FILENO)
+ close(devnull);
+}
+
/*
* Connect to the given ssh server using a proxy command that passes a
* a connected fd back to us.
*/
static int
-ssh_proxy_fdpass_connect(const char *host, u_short port,
- const char *proxy_command)
+ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host,
+ const char *host_arg, u_short port, const char *proxy_command)
{
char *command_string;
int sp[2], sock;
@@ -114,38 +136,39 @@ ssh_proxy_fdpass_connect(const char *host, u_short port,
if ((shell = getenv("SHELL")) == NULL)
shell = _PATH_BSHELL;
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) < 0)
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == -1)
fatal("Could not create socketpair to communicate with "
"proxy dialer: %.100s", strerror(errno));
command_string = expand_proxy_command(proxy_command, options.user,
- host, port);
+ host, host_arg, port);
debug("Executing proxy dialer command: %.500s", command_string);
/* Fork and execute the proxy command. */
if ((pid = fork()) == 0) {
char *argv[10];
- /* Child. Permanently give up superuser privileges. */
- permanently_drop_suid(original_real_uid);
-
close(sp[1]);
/* Redirect stdin and stdout. */
if (sp[0] != 0) {
- if (dup2(sp[0], 0) < 0)
+ if (dup2(sp[0], 0) == -1)
perror("dup2 stdin");
}
if (sp[0] != 1) {
- if (dup2(sp[0], 1) < 0)
+ if (dup2(sp[0], 1) == -1)
perror("dup2 stdout");
}
if (sp[0] >= 2)
close(sp[0]);
/*
- * Stderr is left as it is so that error messages get
- * printed on the user's terminal.
+ * Stderr is left for non-ControlPersist connections is so
+ * error messages may be printed on the user's terminal.
*/
+ if (!debug_flag && options.control_path != NULL &&
+ options.control_persist)
+ stderr_null();
+
argv[0] = shell;
argv[1] = "-c";
argv[2] = command_string;
@@ -160,20 +183,22 @@ ssh_proxy_fdpass_connect(const char *host, u_short port,
exit(1);
}
/* Parent. */
- if (pid < 0)
+ if (pid == -1)
fatal("fork failed: %.100s", strerror(errno));
close(sp[0]);
free(command_string);
if ((sock = mm_receive_fd(sp[1])) == -1)
fatal("proxy dialer did not pass back a connection");
+ close(sp[1]);
while (waitpid(pid, NULL, 0) == -1)
if (errno != EINTR)
fatal("Couldn't wait for child: %s", strerror(errno));
/* Set the connection file descriptors. */
- packet_set_connection(sock, sock);
+ if (ssh_packet_set_connection(ssh, sock, sock) == NULL)
+ return -1; /* ssh_packet_set_connection logs error */
return 0;
}
@@ -182,7 +207,8 @@ ssh_proxy_fdpass_connect(const char *host, u_short port,
* Connect to the given ssh server using a proxy command.
*/
static int
-ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
+ssh_proxy_connect(struct ssh *ssh, const char *host, const char *host_arg,
+ u_short port, const char *proxy_command)
{
char *command_string;
int pin[2], pout[2];
@@ -193,36 +219,39 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
shell = _PATH_BSHELL;
/* Create pipes for communicating with the proxy. */
- if (pipe(pin) < 0 || pipe(pout) < 0)
+ if (pipe(pin) == -1 || pipe(pout) == -1)
fatal("Could not create pipes to communicate with the proxy: %.100s",
strerror(errno));
command_string = expand_proxy_command(proxy_command, options.user,
- host, port);
+ host, host_arg, port);
debug("Executing proxy command: %.500s", command_string);
/* Fork and execute the proxy command. */
if ((pid = fork()) == 0) {
char *argv[10];
- /* Child. Permanently give up superuser privileges. */
- permanently_drop_suid(original_real_uid);
-
/* Redirect stdin and stdout. */
close(pin[1]);
if (pin[0] != 0) {
- if (dup2(pin[0], 0) < 0)
+ if (dup2(pin[0], 0) == -1)
perror("dup2 stdin");
close(pin[0]);
}
close(pout[0]);
- if (dup2(pout[1], 1) < 0)
+ if (dup2(pout[1], 1) == -1)
perror("dup2 stdout");
/* Cannot be 1 because pin allocated two descriptors. */
close(pout[1]);
- /* Stderr is left as it is so that error messages get
- printed on the user's terminal. */
+ /*
+ * Stderr is left for non-ControlPersist connections is so
+ * error messages may be printed on the user's terminal.
+ */
+ if (!debug_flag && options.control_path != NULL &&
+ options.control_persist)
+ stderr_null();
+
argv[0] = shell;
argv[1] = "-c";
argv[2] = command_string;
@@ -230,13 +259,13 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
/* Execute the proxy command. Note that we gave up any
extra privileges above. */
- signal(SIGPIPE, SIG_DFL);
+ ssh_signal(SIGPIPE, SIG_DFL);
execv(argv[0], argv);
perror(argv[0]);
exit(1);
}
/* Parent. */
- if (pid < 0)
+ if (pid == -1)
fatal("fork failed: %.100s", strerror(errno));
else
proxy_command_pid = pid; /* save pid to clean up later */
@@ -249,9 +278,9 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
free(command_string);
/* Set the connection file descriptors. */
- packet_set_connection(pout[0], pin[1]);
+ if (ssh_packet_set_connection(ssh, pout[0], pin[1]) == NULL)
+ return -1; /* ssh_packet_set_connection logs error */
- /* Indicate OK return */
return 0;
}
@@ -266,173 +295,179 @@ ssh_kill_proxy_command(void)
kill(proxy_command_pid, SIGHUP);
}
+#ifdef HAVE_IFADDRS_H
+/*
+ * Search a interface address list (returned from getifaddrs(3)) for an
+ * address that matches the desired address family on the specified interface.
+ * Returns 0 and fills in *resultp and *rlenp on success. Returns -1 on failure.
+ */
+static int
+check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs,
+ struct sockaddr_storage *resultp, socklen_t *rlenp)
+{
+ struct sockaddr_in6 *sa6;
+ struct sockaddr_in *sa;
+ struct in6_addr *v6addr;
+ const struct ifaddrs *ifa;
+ int allow_local;
+
+ /*
+ * Prefer addresses that are not loopback or linklocal, but use them
+ * if nothing else matches.
+ */
+ for (allow_local = 0; allow_local < 2; allow_local++) {
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL ||
+ (ifa->ifa_flags & IFF_UP) == 0 ||
+ ifa->ifa_addr->sa_family != af ||
+ strcmp(ifa->ifa_name, options.bind_interface) != 0)
+ continue;
+ switch (ifa->ifa_addr->sa_family) {
+ case AF_INET:
+ sa = (struct sockaddr_in *)ifa->ifa_addr;
+ if (!allow_local && sa->sin_addr.s_addr ==
+ htonl(INADDR_LOOPBACK))
+ continue;
+ if (*rlenp < sizeof(struct sockaddr_in)) {
+ error("%s: v4 addr doesn't fit",
+ __func__);
+ return -1;
+ }
+ *rlenp = sizeof(struct sockaddr_in);
+ memcpy(resultp, sa, *rlenp);
+ return 0;
+ case AF_INET6:
+ sa6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+ v6addr = &sa6->sin6_addr;
+ if (!allow_local &&
+ (IN6_IS_ADDR_LINKLOCAL(v6addr) ||
+ IN6_IS_ADDR_LOOPBACK(v6addr)))
+ continue;
+ if (*rlenp < sizeof(struct sockaddr_in6)) {
+ error("%s: v6 addr doesn't fit",
+ __func__);
+ return -1;
+ }
+ *rlenp = sizeof(struct sockaddr_in6);
+ memcpy(resultp, sa6, *rlenp);
+ return 0;
+ }
+ }
+ }
+ return -1;
+}
+#endif
+
/*
- * Creates a (possibly privileged) socket for use as the ssh connection.
+ * Creates a socket for use as the ssh connection.
*/
static int
-ssh_create_socket(int privileged, struct addrinfo *ai)
+ssh_create_socket(struct addrinfo *ai)
{
- int sock, r, gaierr;
+ int sock, r;
+ struct sockaddr_storage bindaddr;
+ socklen_t bindaddrlen = 0;
struct addrinfo hints, *res = NULL;
+#ifdef HAVE_IFADDRS_H
+ struct ifaddrs *ifaddrs = NULL;
+#endif
+ char ntop[NI_MAXHOST];
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (sock < 0) {
+ if (sock == -1) {
error("socket: %s", strerror(errno));
return -1;
}
fcntl(sock, F_SETFD, FD_CLOEXEC);
/* Bind the socket to an alternative local IP address */
- if (options.bind_address == NULL && !privileged)
+ if (options.bind_address == NULL && options.bind_interface == NULL)
return sock;
- if (options.bind_address) {
+ if (options.bind_address != NULL) {
memset(&hints, 0, sizeof(hints));
hints.ai_family = ai->ai_family;
hints.ai_socktype = ai->ai_socktype;
hints.ai_protocol = ai->ai_protocol;
hints.ai_flags = AI_PASSIVE;
- gaierr = getaddrinfo(options.bind_address, NULL, &hints, &res);
- if (gaierr) {
+ if ((r = getaddrinfo(options.bind_address, NULL,
+ &hints, &res)) != 0) {
error("getaddrinfo: %s: %s", options.bind_address,
- ssh_gai_strerror(gaierr));
- close(sock);
- return -1;
+ ssh_gai_strerror(r));
+ goto fail;
}
- }
- /*
- * If we are running as root and want to connect to a privileged
- * port, bind our own socket to a privileged port.
- */
- if (privileged) {
- PRIV_START;
- r = bindresvport_sa(sock, res ? res->ai_addr : NULL);
- PRIV_END;
- if (r < 0) {
- error("bindresvport_sa: af=%d %s", ai->ai_family,
- strerror(errno));
+ if (res == NULL) {
+ error("getaddrinfo: no addrs");
goto fail;
}
- } else {
- if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
- error("bind: %s: %s", options.bind_address,
- strerror(errno));
- fail:
- close(sock);
- freeaddrinfo(res);
- return -1;
+ memcpy(&bindaddr, res->ai_addr, res->ai_addrlen);
+ bindaddrlen = res->ai_addrlen;
+ } else if (options.bind_interface != NULL) {
+#ifdef HAVE_IFADDRS_H
+ if ((r = getifaddrs(&ifaddrs)) != 0) {
+ error("getifaddrs: %s: %s", options.bind_interface,
+ strerror(errno));
+ goto fail;
}
+ bindaddrlen = sizeof(bindaddr);
+ if (check_ifaddrs(options.bind_interface, ai->ai_family,
+ ifaddrs, &bindaddr, &bindaddrlen) != 0) {
+ logit("getifaddrs: %s: no suitable addresses",
+ options.bind_interface);
+ goto fail;
+ }
+#else
+ error("BindInterface not supported on this platform.");
+#endif
+ }
+ if ((r = getnameinfo((struct sockaddr *)&bindaddr, bindaddrlen,
+ ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST)) != 0) {
+ error("%s: getnameinfo failed: %s", __func__,
+ ssh_gai_strerror(r));
+ goto fail;
+ }
+ if (bind(sock, (struct sockaddr *)&bindaddr, bindaddrlen) != 0) {
+ error("bind %s: %s", ntop, strerror(errno));
+ goto fail;
}
+ debug("%s: bound to %s", __func__, ntop);
+ /* success */
+ goto out;
+fail:
+ close(sock);
+ sock = -1;
+ out:
if (res != NULL)
freeaddrinfo(res);
+#ifdef HAVE_IFADDRS_H
+ if (ifaddrs != NULL)
+ freeifaddrs(ifaddrs);
+#endif
return sock;
}
-static int
-timeout_connect(int sockfd, const struct sockaddr *serv_addr,
- socklen_t addrlen, int *timeoutp)
-{
- fd_set *fdset;
- struct timeval tv, t_start;
- socklen_t optlen;
- int optval, rc, result = -1;
-
- gettimeofday(&t_start, NULL);
-
- if (*timeoutp <= 0) {
- result = connect(sockfd, serv_addr, addrlen);
- goto done;
- }
-
- set_nonblock(sockfd);
- rc = connect(sockfd, serv_addr, addrlen);
- if (rc == 0) {
- unset_nonblock(sockfd);
- result = 0;
- goto done;
- }
- if (errno != EINPROGRESS) {
- result = -1;
- goto done;
- }
-
- fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS),
- sizeof(fd_mask));
- FD_SET(sockfd, fdset);
- ms_to_timeval(&tv, *timeoutp);
-
- for (;;) {
- rc = select(sockfd + 1, NULL, fdset, NULL, &tv);
- if (rc != -1 || errno != EINTR)
- break;
- }
-
- switch (rc) {
- case 0:
- /* Timed out */
- errno = ETIMEDOUT;
- break;
- case -1:
- /* Select error */
- debug("select: %s", strerror(errno));
- break;
- case 1:
- /* Completed or failed */
- optval = 0;
- optlen = sizeof(optval);
- if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval,
- &optlen) == -1) {
- debug("getsockopt: %s", strerror(errno));
- break;
- }
- if (optval != 0) {
- errno = optval;
- break;
- }
- result = 0;
- unset_nonblock(sockfd);
- break;
- default:
- /* Should not occur */
- fatal("Bogus return (%d) from select()", rc);
- }
-
- free(fdset);
-
- done:
- if (result == 0 && *timeoutp > 0) {
- ms_subtract_diff(&t_start, timeoutp);
- if (*timeoutp <= 0) {
- errno = ETIMEDOUT;
- result = -1;
- }
- }
-
- return (result);
-}
-
/*
* Opens a TCP/IP connection to the remote server on the given host.
* The address of the remote host will be returned in hostaddr.
- * If port is 0, the default port will be used. If needpriv is true,
- * a privileged port will be allocated to make the connection.
- * This requires super-user privileges if needpriv is true.
+ * If port is 0, the default port will be used.
* Connection_attempts specifies the maximum number of tries (one per
* second). If proxy_command is non-NULL, it specifies the command (with %h
* and %p substituted for host and port, respectively) to use to contact
* the daemon.
*/
static int
-ssh_connect_direct(const char *host, struct addrinfo *aitop,
+ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop,
struct sockaddr_storage *hostaddr, u_short port, int family,
- int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv)
+ int connection_attempts, int *timeout_ms, int want_keepalive)
{
- int on = 1;
- int sock = -1, attempt;
+ int on = 1, saved_timeout_ms = *timeout_ms;
+ int oerrno, sock = -1, attempt;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
struct addrinfo *ai;
- debug2("ssh_connect: needpriv %d", needpriv);
+ debug2("%s", __func__);
+ memset(ntop, 0, sizeof(ntop));
+ memset(strport, 0, sizeof(strport));
for (attempt = 0; attempt < connection_attempts; attempt++) {
if (attempt > 0) {
@@ -446,33 +481,42 @@ ssh_connect_direct(const char *host, struct addrinfo *aitop,
*/
for (ai = aitop; ai; ai = ai->ai_next) {
if (ai->ai_family != AF_INET &&
- ai->ai_family != AF_INET6)
+ ai->ai_family != AF_INET6) {
+ errno = EAFNOSUPPORT;
continue;
+ }
if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
ntop, sizeof(ntop), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
- error("ssh_connect: getnameinfo failed");
+ oerrno = errno;
+ error("%s: getnameinfo failed", __func__);
+ errno = oerrno;
continue;
}
debug("Connecting to %.200s [%.100s] port %s.",
host, ntop, strport);
/* Create a socket for connecting. */
- sock = ssh_create_socket(needpriv, ai);
- if (sock < 0)
+ sock = ssh_create_socket(ai);
+ if (sock < 0) {
/* Any error is already output */
+ errno = 0;
continue;
+ }
+ *timeout_ms = saved_timeout_ms;
if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen,
timeout_ms) >= 0) {
/* Successful connection. */
memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
break;
} else {
+ oerrno = errno;
debug("connect to address %s port %s: %s",
ntop, strport, strerror(errno));
close(sock);
sock = -1;
+ errno = oerrno;
}
}
if (sock != -1)
@@ -482,8 +526,8 @@ ssh_connect_direct(const char *host, struct addrinfo *aitop,
/* Return failure if we didn't get a successful connection. */
if (sock == -1) {
error("ssh: connect to host %s port %s: %s",
- host, strport, strerror(errno));
- return (-1);
+ host, strport, errno == 0 ? "failure" : strerror(errno));
+ return -1;
}
debug("Connection established.");
@@ -491,233 +535,96 @@ ssh_connect_direct(const char *host, struct addrinfo *aitop,
/* Set SO_KEEPALIVE if requested. */
if (want_keepalive &&
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
- sizeof(on)) < 0)
+ sizeof(on)) == -1)
error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
/* Set the connection. */
- packet_set_connection(sock, sock);
+ if (ssh_packet_set_connection(ssh, sock, sock) == NULL)
+ return -1; /* ssh_packet_set_connection logs error */
return 0;
}
int
-ssh_connect(const char *host, struct addrinfo *addrs,
- struct sockaddr_storage *hostaddr, u_short port, int family,
- int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv)
+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 in, out;
+
if (options.proxy_command == NULL) {
- return ssh_connect_direct(host, addrs, hostaddr, port, family,
- connection_attempts, timeout_ms, want_keepalive, needpriv);
+ return ssh_connect_direct(ssh, host, addrs, hostaddr, port,
+ family, connection_attempts, timeout_ms, want_keepalive);
} else if (strcmp(options.proxy_command, "-") == 0) {
- packet_set_connection(STDIN_FILENO, STDOUT_FILENO);
- return 0; /* Always succeeds */
+ if ((in = dup(STDIN_FILENO)) == -1 ||
+ (out = dup(STDOUT_FILENO)) == -1) {
+ if (in >= 0)
+ close(in);
+ error("%s: dup() in/out failed", __func__);
+ return -1; /* ssh_packet_set_connection logs error */
+ }
+ if ((ssh_packet_set_connection(ssh, in, out)) == NULL)
+ return -1; /* ssh_packet_set_connection logs error */
+ return 0;
} else if (options.proxy_use_fdpass) {
- return ssh_proxy_fdpass_connect(host, port,
+ return ssh_proxy_fdpass_connect(ssh, host, host_arg, port,
options.proxy_command);
}
- return ssh_proxy_connect(host, port, options.proxy_command);
-}
-
-static void
-send_client_banner(int connection_out, int minor1)
-{
- /* Send our own protocol version identification. */
- if (compat20) {
- xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n",
- PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION);
- } else {
- xasprintf(&client_version_string, "SSH-%d.%d-%.100s\n",
- PROTOCOL_MAJOR_1, minor1, SSH_VERSION);
- }
- if (roaming_atomicio(vwrite, connection_out, client_version_string,
- strlen(client_version_string)) != strlen(client_version_string))
- fatal("write: %.100s", strerror(errno));
- chop(client_version_string);
- debug("Local version string %.100s", client_version_string);
-}
-
-/*
- * Waits for the server identification string, and sends our own
- * identification string.
- */
-void
-ssh_exchange_identification(int timeout_ms)
-{
- char buf[256], remote_version[256]; /* must be same size! */
- int remote_major, remote_minor, mismatch;
- int connection_in = packet_get_connection_in();
- int connection_out = packet_get_connection_out();
- int minor1 = PROTOCOL_MINOR_1, client_banner_sent = 0;
- u_int i, n;
- size_t len;
- int fdsetsz, remaining, rc;
- struct timeval t_start, t_remaining;
- fd_set *fdset;
-
- fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask);
- fdset = xcalloc(1, fdsetsz);
-
- /*
- * If we are SSH2-only then we can send the banner immediately and
- * save a round-trip.
- */
- if (options.protocol == SSH_PROTO_2) {
- enable_compat20();
- send_client_banner(connection_out, 0);
- client_banner_sent = 1;
- }
-
- /* Read other side's version identification. */
- remaining = timeout_ms;
- for (n = 0;;) {
- for (i = 0; i < sizeof(buf) - 1; i++) {
- if (timeout_ms > 0) {
- gettimeofday(&t_start, NULL);
- ms_to_timeval(&t_remaining, remaining);
- FD_SET(connection_in, fdset);
- rc = select(connection_in + 1, fdset, NULL,
- fdset, &t_remaining);
- ms_subtract_diff(&t_start, &remaining);
- if (rc == 0 || remaining <= 0)
- fatal("Connection timed out during "
- "banner exchange");
- if (rc == -1) {
- if (errno == EINTR)
- continue;
- fatal("ssh_exchange_identification: "
- "select: %s", strerror(errno));
- }
- }
-
- len = roaming_atomicio(read, connection_in, &buf[i], 1);
-
- if (len != 1 && errno == EPIPE)
- fatal("ssh_exchange_identification: "
- "Connection closed by remote host");
- else if (len != 1)
- fatal("ssh_exchange_identification: "
- "read: %.100s", strerror(errno));
- if (buf[i] == '\r') {
- buf[i] = '\n';
- buf[i + 1] = 0;
- continue; /**XXX wait for \n */
- }
- if (buf[i] == '\n') {
- buf[i + 1] = 0;
- break;
- }
- if (++n > 65536)
- fatal("ssh_exchange_identification: "
- "No banner received");
- }
- buf[sizeof(buf) - 1] = 0;
- if (strncmp(buf, "SSH-", 4) == 0)
- break;
- debug("ssh_exchange_identification: %s", buf);
- }
- server_version_string = xstrdup(buf);
- free(fdset);
-
- /*
- * Check that the versions match. In future this might accept
- * several versions and set appropriate flags to handle them.
- */
- if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n",
- &remote_major, &remote_minor, remote_version) != 3)
- fatal("Bad remote protocol version identification: '%.100s'", buf);
- debug("Remote protocol version %d.%d, remote software version %.100s",
- remote_major, remote_minor, remote_version);
-
- active_state->compat = compat_datafellows(remote_version);
- mismatch = 0;
-
- switch (remote_major) {
- case 1:
- if (remote_minor == 99 &&
- (options.protocol & SSH_PROTO_2) &&
- !(options.protocol & SSH_PROTO_1_PREFERRED)) {
- enable_compat20();
- break;
- }
- if (!(options.protocol & SSH_PROTO_1)) {
- mismatch = 1;
- break;
- }
- if (remote_minor < 3) {
- fatal("Remote machine has too old SSH software version.");
- } else if (remote_minor == 3 || remote_minor == 4) {
- /* We speak 1.3, too. */
- enable_compat13();
- minor1 = 3;
- if (options.forward_agent) {
- logit("Agent forwarding disabled for protocol 1.3");
- options.forward_agent = 0;
- }
- }
- break;
- case 2:
- if (options.protocol & SSH_PROTO_2) {
- enable_compat20();
- break;
- }
- /* FALLTHROUGH */
- default:
- mismatch = 1;
- break;
- }
- if (mismatch)
- fatal("Protocol major versions differ: %d vs. %d",
- (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
- remote_major);
- if ((datafellows & SSH_BUG_DERIVEKEY) != 0)
- fatal("Server version \"%.100s\" uses unsafe key agreement; "
- "refusing connection", remote_version);
- if ((datafellows & SSH_BUG_RSASIGMD5) != 0)
- logit("Server version \"%.100s\" uses unsafe RSA signature "
- "scheme; disabling use of RSA keys", remote_version);
- if (!client_banner_sent)
- send_client_banner(connection_out, minor1);
- chop(server_version_string);
+ return ssh_proxy_connect(ssh, host, host_arg, port,
+ options.proxy_command);
}
/* defaults to 'no' */
static int
-confirm(const char *prompt)
+confirm(const char *prompt, const char *fingerprint)
{
const char *msg, *again = "Please type 'yes' or 'no': ";
- char *p;
+ const char *again_fp = "Please type 'yes', 'no' or the fingerprint: ";
+ char *p, *cp;
int ret = -1;
if (options.batch_mode)
return 0;
- for (msg = prompt;;msg = again) {
- p = read_passphrase(msg, RP_ECHO);
- if (p == NULL ||
- (p[0] == '\0') || (p[0] == '\n') ||
- strncasecmp(p, "no", 2) == 0)
+ for (msg = prompt;;msg = fingerprint ? again_fp : again) {
+ cp = p = read_passphrase(msg, RP_ECHO);
+ if (p == NULL)
+ return 0;
+ p += strspn(p, " \t"); /* skip leading whitespace */
+ p[strcspn(p, " \t\n")] = '\0'; /* remove trailing whitespace */
+ if (p[0] == '\0' || strcasecmp(p, "no") == 0)
ret = 0;
- if (p && strncasecmp(p, "yes", 3) == 0)
+ else if (strcasecmp(p, "yes") == 0 || (fingerprint != NULL &&
+ strcasecmp(p, fingerprint) == 0))
ret = 1;
- free(p);
+ free(cp);
if (ret != -1)
return ret;
}
}
static int
-check_host_cert(const char *host, const Key *host_key)
+check_host_cert(const char *host, const struct sshkey *key)
{
const char *reason;
+ int r;
- if (key_cert_check_authority(host_key, 1, 0, host, &reason) != 0) {
+ if (sshkey_cert_check_authority(key, 1, 0, host, &reason) != 0) {
error("%s", reason);
return 0;
}
- if (buffer_len(host_key->cert->critical) != 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;
}
@@ -803,21 +710,21 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr,
#define ROQUIET 2
static int
check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
- Key *host_key, int readonly,
+ struct sshkey *host_key, int readonly,
char **user_hostfiles, u_int num_user_hostfiles,
char **system_hostfiles, u_int num_system_hostfiles)
{
HostStatus host_status;
HostStatus ip_status;
- Key *raw_key = NULL;
+ struct sshkey *raw_key = NULL;
char *ip = NULL, *host = NULL;
char hostline[1000], *hostp, *fp, *ra;
char msg[1024];
const char *type;
const struct hostkey_entry *host_found, *ip_found;
- int len, cancelled_forwarding = 0;
+ int len, cancelled_forwarding = 0, confirmed;
int local = sockaddr_is_local(hostaddr);
- int r, want_cert = key_is_cert(host_key), host_ip_differ = 0;
+ int r, want_cert = sshkey_is_cert(host_key), host_ip_differ = 0;
int hostkey_trusted = 0; /* Known or explicitly accepted by user */
struct hostkeys *host_hostkeys, *ip_hostkeys;
u_int i;
@@ -868,8 +775,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
retry:
/* Reload these as they may have changed on cert->key downgrade */
- want_cert = key_is_cert(host_key);
- type = key_type(host_key);
+ want_cert = sshkey_is_cert(host_key);
+ type = sshkey_type(host_key);
/*
* Check if the host key is present in the user's list of known
@@ -887,9 +794,9 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
ip_status = check_key_in_hostkeys(ip_hostkeys, host_key,
&ip_found);
if (host_status == HOST_CHANGED &&
- (ip_status != HOST_CHANGED ||
+ (ip_status != HOST_CHANGED ||
(ip_found != NULL &&
- !key_equal(ip_found->key, host_found->key))))
+ !sshkey_equal(ip_found->key, host_found->key))))
host_ip_differ = 1;
} else
ip_status = host_status;
@@ -901,7 +808,9 @@ 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(hostname, host_key))
+ if (want_cert &&
+ !check_host_cert(options.host_key_alias == NULL ?
+ hostname : options.host_key_alias, host_key))
goto fail;
if (options.check_host_ip && ip_status == HOST_NEW) {
if (readonly || want_cert)
@@ -912,7 +821,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
host_key, options.hash_known_hosts))
logit("Failed to add the %s host key for IP "
"address '%.128s' to the list of known "
- "hosts (%.30s).", type, ip,
+ "hosts (%.500s).", type, ip,
user_hostfiles[0]);
else
logit("Warning: Permanently added the %s host "
@@ -925,7 +834,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
options.fingerprint_hash, SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
- logit("Host key fingerprint is %s\n%s\n", fp, ra);
+ logit("Host key fingerprint is %s\n%s", fp, ra);
free(ra);
free(fp);
}
@@ -945,7 +854,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
if (readonly || want_cert)
goto fail;
/* The host is new. */
- if (options.strict_host_key_checking == 1) {
+ if (options.strict_host_key_checking ==
+ SSH_STRICT_HOSTKEY_YES) {
/*
* User has requested strict host key checking. We
* will not add the host key automatically. The only
@@ -954,7 +864,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
error("No %s host key is known for %.200s and you "
"have requested strict checking.", type, host);
goto fail;
- } else if (options.strict_host_key_checking == 2) {
+ } else if (options.strict_host_key_checking ==
+ SSH_STRICT_HOSTKEY_ASK) {
char msg1[1024], msg2[1024];
if (show_other_keys(host_hostkeys, host_key))
@@ -986,20 +897,21 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
"established%s\n"
"%s key fingerprint is %s.%s%s\n%s"
"Are you sure you want to continue connecting "
- "(yes/no)? ",
+ "(yes/no/[fingerprint])? ",
host, ip, msg1, type, fp,
options.visual_host_key ? "\n" : "",
options.visual_host_key ? ra : "",
msg2);
free(ra);
+ confirmed = confirm(msg, fp);
free(fp);
- if (!confirm(msg))
+ if (!confirmed)
goto fail;
hostkey_trusted = 1; /* user explicitly confirmed */
}
/*
- * If not in strict mode, add the key automatically to the
- * local known_hosts file.
+ * If in "new" or "off" strict mode, add the key automatically
+ * to the local known_hosts file.
*/
if (options.check_host_ip && ip_status == HOST_NEW) {
snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
@@ -1041,7 +953,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
* If strict host key checking is in use, the user will have
* to edit the key manually and we can only abort.
*/
- if (options.strict_host_key_checking) {
+ if (options.strict_host_key_checking !=
+ SSH_STRICT_HOSTKEY_OFF) {
error("%s host key for %.200s was revoked and you have "
"requested strict checking.", type, host);
goto fail;
@@ -1086,14 +999,16 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
warn_changed_key(host_key);
error("Add correct host key in %.100s to get rid of this message.",
user_hostfiles[0]);
- error("Offending %s key in %s:%lu", key_type(host_found->key),
+ error("Offending %s key in %s:%lu",
+ sshkey_type(host_found->key),
host_found->file, host_found->line);
/*
* If strict host key checking is in use, the user will have
* to edit the key manually and we can only abort.
*/
- if (options.strict_host_key_checking) {
+ if (options.strict_host_key_checking !=
+ SSH_STRICT_HOSTKEY_OFF) {
error("%s host key for %.200s has changed and you have "
"requested strict checking.", type, host);
goto fail;
@@ -1180,15 +1095,17 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
"\nMatching host key in %s:%lu",
host_found->file, host_found->line);
}
- if (options.strict_host_key_checking == 1) {
- logit("%s", msg);
- error("Exiting, you have requested strict checking.");
- goto fail;
- } else if (options.strict_host_key_checking == 2) {
+ if (options.strict_host_key_checking ==
+ SSH_STRICT_HOSTKEY_ASK) {
strlcat(msg, "\nAre you sure you want "
"to continue connecting (yes/no)? ", sizeof(msg));
- if (!confirm(msg))
+ if (!confirm(msg, NULL))
goto fail;
+ } else if (options.strict_host_key_checking !=
+ SSH_STRICT_HOSTKEY_OFF) {
+ logit("%s", msg);
+ error("Exiting, you have requested strict checking.");
+ goto fail;
} else {
logit("%s", msg);
}
@@ -1215,14 +1132,15 @@ fail:
* search normally.
*/
debug("No matching CA found. Retry with plain key");
- raw_key = key_from_private(host_key);
- if (key_drop_cert(raw_key) != 0)
- fatal("Couldn't drop certificate");
+ if ((r = sshkey_from_private(host_key, &raw_key)) != 0)
+ fatal("%s: sshkey_from_private: %s",
+ __func__, ssh_err(r));
+ if ((r = sshkey_drop_cert(raw_key)) != 0)
+ fatal("Couldn't drop certificate: %s", ssh_err(r));
host_key = raw_key;
goto retry;
}
- if (raw_key != NULL)
- key_free(raw_key);
+ sshkey_free(raw_key);
free(ip);
free(host);
if (host_hostkeys != NULL)
@@ -1234,10 +1152,11 @@ fail:
/* returns 0 if key verifies or -1 if key does NOT verify */
int
-verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
+verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key)
{
+ u_int i;
int r = -1, flags = 0;
- char *fp = NULL;
+ char valid[64], *fp = NULL, *cafp = NULL;
struct sshkey *plain = NULL;
if ((fp = sshkey_fingerprint(host_key,
@@ -1247,8 +1166,30 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
goto out;
}
- debug("Server host key: %s %s",
- compat20 ? sshkey_ssh_name(host_key) : sshkey_type(host_key), fp);
+ if (sshkey_is_cert(host_key)) {
+ if ((cafp = sshkey_fingerprint(host_key->cert->signature_key,
+ options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
+ error("%s: fingerprint CA key: %s",
+ __func__, ssh_err(r));
+ r = -1;
+ goto out;
+ }
+ sshkey_format_cert_validity(host_key->cert,
+ valid, sizeof(valid));
+ debug("Server host certificate: %s %s, serial %llu "
+ "ID \"%s\" CA %s %s valid %s",
+ sshkey_ssh_name(host_key), fp,
+ (unsigned long long)host_key->cert->serial,
+ host_key->cert->key_id,
+ sshkey_ssh_name(host_key->cert->signature_key), cafp,
+ valid);
+ for (i = 0; i < host_key->cert->nprincipals; i++) {
+ debug2("Server host certificate hostname: %s",
+ host_key->cert->principals[i]);
+ }
+ } else {
+ debug("Server host key: %s %s", sshkey_ssh_name(host_key), fp);
+ }
if (sshkey_equal(previous_host_key, host_key)) {
debug2("%s: server host key %s %s matches cached key",
@@ -1313,9 +1254,10 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
out:
sshkey_free(plain);
free(fp);
+ free(cafp);
if (r == 0 && host_key != NULL) {
- key_free(previous_host_key);
- previous_host_key = key_from_private(host_key);
+ sshkey_free(previous_host_key);
+ r = sshkey_from_private(host_key, &previous_host_key);
}
return r;
@@ -1329,11 +1271,12 @@ out:
* This function does not require super-user privileges.
*/
void
-ssh_login(Sensitive *sensitive, const char *orighost,
+ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost,
struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms)
{
char *host;
char *server_user, *local_user;
+ int r;
local_user = xstrdup(pw->pw_name);
server_user = options.user ? options.user : local_user;
@@ -1343,55 +1286,31 @@ ssh_login(Sensitive *sensitive, const char *orighost,
lowercase(host);
/* Exchange protocol version identification strings with the server. */
- ssh_exchange_identification(timeout_ms);
+ if ((r = kex_exchange_identification(ssh, timeout_ms, NULL)) != 0)
+ sshpkt_fatal(ssh, r, "banner exchange");
/* Put the connection into non-blocking mode. */
- packet_set_nonblocking();
+ ssh_packet_set_nonblocking(ssh);
/* key exchange */
/* authenticate user */
- if (compat20) {
- ssh_kex2(host, hostaddr, port);
- ssh_userauth2(local_user, server_user, host, sensitive);
- } else {
-#ifdef WITH_SSH1
- ssh_kex(host, hostaddr);
- ssh_userauth1(local_user, server_user, host, sensitive);
-#else
- fatal("ssh1 is not unsupported");
-#endif
- }
+ debug("Authenticating to %s:%d as '%s'", host, port, server_user);
+ ssh_kex2(ssh, host, hostaddr, port);
+ ssh_userauth2(ssh, local_user, server_user, host, sensitive);
free(local_user);
-}
-
-void
-ssh_put_password(char *password)
-{
- int size;
- char *padded;
-
- if (datafellows & SSH_BUG_PASSWORDPAD) {
- packet_put_cstring(password);
- return;
- }
- size = roundup(strlen(password) + 1, 32);
- padded = xcalloc(1, size);
- strlcpy(padded, password, size);
- packet_put_string(padded, size);
- explicit_bzero(padded, size);
- free(padded);
+ free(host);
}
/* print all known host keys for a given host, but skip keys of given type */
static int
-show_other_keys(struct hostkeys *hostkeys, Key *key)
+show_other_keys(struct hostkeys *hostkeys, struct sshkey *key)
{
int type[] = {
- KEY_RSA1,
KEY_RSA,
KEY_DSA,
KEY_ECDSA,
KEY_ED25519,
+ KEY_XMSS,
-1
};
int i, ret = 0;
@@ -1412,9 +1331,9 @@ show_other_keys(struct hostkeys *hostkeys, Key *key)
logit("WARNING: %s key found for host %s\n"
"in %s:%lu\n"
"%s key fingerprint %s.",
- key_type(found->key),
+ sshkey_type(found->key),
found->host, found->file, found->line,
- key_type(found->key), fp);
+ sshkey_type(found->key), fp);
if (options.visual_host_key)
logit("%s", ra);
free(ra);
@@ -1425,7 +1344,7 @@ show_other_keys(struct hostkeys *hostkeys, Key *key)
}
static void
-warn_changed_key(Key *host_key)
+warn_changed_key(struct sshkey *host_key)
{
char *fp;
@@ -1441,7 +1360,7 @@ warn_changed_key(Key *host_key)
error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
error("It is also possible that a host key has just been changed.");
error("The fingerprint for the %s key sent by the remote host is\n%s.",
- key_type(host_key), fp);
+ sshkey_type(host_key), fp);
error("Please contact your system administrator.");
free(fp);
@@ -1465,10 +1384,10 @@ ssh_local_cmd(const char *args)
if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
shell = _PATH_BSHELL;
- osighand = signal(SIGCHLD, SIG_DFL);
+ osighand = ssh_signal(SIGCHLD, SIG_DFL);
pid = fork();
if (pid == 0) {
- signal(SIGPIPE, SIG_DFL);
+ ssh_signal(SIGPIPE, SIG_DFL);
debug3("Executing %s -c \"%s\"", shell, args);
execl(shell, shell, "-c", args, (char *)NULL);
error("Couldn't execute %s -c \"%s\": %s",
@@ -1479,10 +1398,42 @@ ssh_local_cmd(const char *args)
while (waitpid(pid, &status, 0) == -1)
if (errno != EINTR)
fatal("Couldn't wait for child: %s", strerror(errno));
- signal(SIGCHLD, osighand);
+ ssh_signal(SIGCHLD, osighand);
if (!WIFEXITED(status))
return (1);
return (WEXITSTATUS(status));
}
+
+void
+maybe_add_key_to_agent(const char *authfile, struct sshkey *private,
+ const char *comment, const char *passphrase)
+{
+ int auth_sock = -1, r;
+ const char *skprovider = NULL;
+
+ if (options.add_keys_to_agent == 0)
+ return;
+
+ if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) {
+ debug3("no authentication agent, not adding key");
+ return;
+ }
+
+ if (options.add_keys_to_agent == 2 &&
+ !ask_permission("Add key %s (%s) to agent?", authfile, comment)) {
+ debug3("user denied adding this key");
+ close(auth_sock);
+ return;
+ }
+ if (sshkey_is_sk(private))
+ skprovider = options.sk_provider;
+ if ((r = ssh_add_identity_constrained(auth_sock, private,
+ comment == NULL ? authfile : comment, 0,
+ (options.add_keys_to_agent == 3), 0, skprovider)) == 0)
+ debug("identity added to agent: %s", authfile);
+ else
+ debug("could not add identity to agent: %s (%d)", authfile, r);
+ close(auth_sock);
+}
diff --git a/sshconnect.h b/sshconnect.h
index 0ea6e99f..7c091e2b 100644
--- a/sshconnect.h
+++ b/sshconnect.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.h,v 1.28 2013/10/16 02:31:47 djm Exp $ */
+/* $OpenBSD: sshconnect.h,v 1.40 2020/01/25 07:17:18 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -26,50 +26,32 @@
typedef struct Sensitive Sensitive;
struct Sensitive {
- Key **keys;
- int nkeys;
- int external_keysign;
+ struct sshkey **keys;
+ int nkeys;
};
struct addrinfo;
-int ssh_connect(const char *, struct addrinfo *, struct sockaddr_storage *,
- u_short, int, int, int *, int, int);
-void ssh_kill_proxy_command(void);
+struct ssh;
-void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short,
- struct passwd *, int);
+int ssh_connect(struct ssh *, const char *, const char *,
+ struct addrinfo *, struct sockaddr_storage *, u_short,
+ int, int, int *, int);
+void ssh_kill_proxy_command(void);
-void ssh_exchange_identification(int);
+void ssh_login(struct ssh *, Sensitive *, const char *,
+ struct sockaddr *, u_short, struct passwd *, int);
-int verify_host_key(char *, struct sockaddr *, Key *);
+int verify_host_key(char *, struct sockaddr *, struct sshkey *);
void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short,
char **, char **);
-void ssh_kex(char *, struct sockaddr *);
-void ssh_kex2(char *, struct sockaddr *, u_short);
+void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short);
-void ssh_userauth1(const char *, const char *, char *, Sensitive *);
-void ssh_userauth2(const char *, const char *, char *, Sensitive *);
+void ssh_userauth2(struct ssh *ssh, const char *, const char *,
+ char *, Sensitive *);
-void ssh_put_password(char *);
int ssh_local_cmd(const char *);
-/*
- * Macros to raise/lower permissions.
- */
-#define PRIV_START do { \
- int save_errno = errno; \
- if (seteuid(original_effective_uid) != 0) \
- fatal("PRIV_START: seteuid: %s", \
- strerror(errno)); \
- errno = save_errno; \
-} while (0)
-
-#define PRIV_END do { \
- int save_errno = errno; \
- if (seteuid(original_real_uid) != 0) \
- fatal("PRIV_END: seteuid: %s", \
- strerror(errno)); \
- errno = save_errno; \
-} while (0)
+void maybe_add_key_to_agent(const char *, struct sshkey *,
+ const char *, const char *);
diff --git a/sshconnect1.c b/sshconnect1.c
deleted file mode 100644
index 016abbce..00000000
--- a/sshconnect1.c
+++ /dev/null
@@ -1,771 +0,0 @@
-/* $OpenBSD: sshconnect1.c,v 1.77 2015/01/14 20:05:27 djm Exp $ */
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Code to connect to a remote host, and to perform the client side of the
- * login (authentication) dialog.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-
-#include "includes.h"
-
-#ifdef WITH_SSH1
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <openssl/bn.h>
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <pwd.h>
-
-#include "xmalloc.h"
-#include "ssh.h"
-#include "ssh1.h"
-#include "rsa.h"
-#include "buffer.h"
-#include "packet.h"
-#include "key.h"
-#include "cipher.h"
-#include "kex.h"
-#include "uidswap.h"
-#include "log.h"
-#include "misc.h"
-#include "readconf.h"
-#include "authfd.h"
-#include "sshconnect.h"
-#include "authfile.h"
-#include "canohost.h"
-#include "hostfile.h"
-#include "auth.h"
-#include "digest.h"
-#include "ssherr.h"
-
-/* Session id for the current session. */
-u_char session_id[16];
-u_int supported_authentications = 0;
-
-extern Options options;
-extern char *__progname;
-
-/*
- * Checks if the user has an authentication agent, and if so, tries to
- * authenticate using the agent.
- */
-static int
-try_agent_authentication(void)
-{
- int r, type, agent_fd, ret = 0;
- u_char response[16];
- size_t i;
- BIGNUM *challenge;
- struct ssh_identitylist *idlist = NULL;
-
- /* Get connection to 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));
- return 0;
- }
-
- if ((challenge = BN_new()) == NULL)
- fatal("try_agent_authentication: BN_new failed");
-
- /* Loop through identities served by the agent. */
- if ((r = ssh_fetch_identitylist(agent_fd, 1, &idlist)) != 0) {
- if (r != SSH_ERR_AGENT_NO_IDENTITIES)
- debug("%s: ssh_fetch_identitylist: %s",
- __func__, ssh_err(r));
- goto out;
- }
- for (i = 0; i < idlist->nkeys; i++) {
- /* Try this identity. */
- debug("Trying RSA authentication via agent with '%.100s'",
- idlist->comments[i]);
-
- /* Tell the server that we are willing to authenticate using this key. */
- packet_start(SSH_CMSG_AUTH_RSA);
- packet_put_bignum(idlist->keys[i]->rsa->n);
- packet_send();
- packet_write_wait();
-
- /* Wait for server's response. */
- type = packet_read();
-
- /* The server sends failure if it doesn't like our key or
- does not support RSA authentication. */
- if (type == SSH_SMSG_FAILURE) {
- debug("Server refused our key.");
- continue;
- }
- /* Otherwise it should have sent a challenge. */
- if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
- packet_disconnect("Protocol error during RSA authentication: %d",
- type);
-
- packet_get_bignum(challenge);
- packet_check_eom();
-
- debug("Received RSA challenge from server.");
-
- /* Ask the agent to decrypt the challenge. */
- if ((r = ssh_decrypt_challenge(agent_fd, idlist->keys[i],
- challenge, session_id, response)) != 0) {
- /*
- * The agent failed to authenticate this identifier
- * although it advertised it supports this. Just
- * return a wrong value.
- */
- logit("Authentication agent failed to decrypt "
- "challenge: %s", ssh_err(r));
- explicit_bzero(response, sizeof(response));
- }
- debug("Sending response to RSA challenge.");
-
- /* Send the decrypted challenge back to the server. */
- packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
- for (i = 0; i < 16; i++)
- packet_put_char(response[i]);
- packet_send();
- packet_write_wait();
-
- /* Wait for response from the server. */
- type = packet_read();
-
- /*
- * The server returns success if it accepted the
- * authentication.
- */
- if (type == SSH_SMSG_SUCCESS) {
- debug("RSA authentication accepted by server.");
- ret = 1;
- break;
- } else if (type != SSH_SMSG_FAILURE)
- packet_disconnect("Protocol error waiting RSA auth "
- "response: %d", type);
- }
- if (ret != 1)
- debug("RSA authentication using agent refused.");
- out:
- ssh_free_identitylist(idlist);
- ssh_close_authentication_socket(agent_fd);
- BN_clear_free(challenge);
- return ret;
-}
-
-/*
- * Computes the proper response to a RSA challenge, and sends the response to
- * the server.
- */
-static void
-respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
-{
- u_char buf[32], response[16];
- struct ssh_digest_ctx *md;
- int i, len;
-
- /* Decrypt the challenge using the private key. */
- /* XXX think about Bleichenbacher, too */
- if (rsa_private_decrypt(challenge, challenge, prv) != 0)
- packet_disconnect(
- "respond_to_rsa_challenge: rsa_private_decrypt failed");
-
- /* Compute the response. */
- /* The response is MD5 of decrypted challenge plus session id. */
- len = BN_num_bytes(challenge);
- if (len <= 0 || (u_int)len > sizeof(buf))
- packet_disconnect(
- "respond_to_rsa_challenge: bad challenge length %d", len);
-
- memset(buf, 0, sizeof(buf));
- BN_bn2bin(challenge, buf + sizeof(buf) - len);
- if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
- ssh_digest_update(md, buf, 32) < 0 ||
- ssh_digest_update(md, session_id, 16) < 0 ||
- ssh_digest_final(md, response, sizeof(response)) < 0)
- fatal("%s: md5 failed", __func__);
- ssh_digest_free(md);
-
- debug("Sending response to host key RSA challenge.");
-
- /* Send the response back to the server. */
- packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
- for (i = 0; i < 16; i++)
- packet_put_char(response[i]);
- packet_send();
- packet_write_wait();
-
- explicit_bzero(buf, sizeof(buf));
- explicit_bzero(response, sizeof(response));
- explicit_bzero(&md, sizeof(md));
-}
-
-/*
- * Checks if the user has authentication file, and if so, tries to authenticate
- * the user using it.
- */
-static int
-try_rsa_authentication(int idx)
-{
- BIGNUM *challenge;
- Key *public, *private;
- char buf[300], *passphrase, *comment, *authfile;
- int i, perm_ok = 1, type, quit;
-
- public = options.identity_keys[idx];
- authfile = options.identity_files[idx];
- comment = xstrdup(authfile);
-
- debug("Trying RSA authentication with key '%.100s'", comment);
-
- /* Tell the server that we are willing to authenticate using this key. */
- packet_start(SSH_CMSG_AUTH_RSA);
- packet_put_bignum(public->rsa->n);
- packet_send();
- packet_write_wait();
-
- /* Wait for server's response. */
- type = packet_read();
-
- /*
- * The server responds with failure if it doesn't like our key or
- * doesn't support RSA authentication.
- */
- if (type == SSH_SMSG_FAILURE) {
- debug("Server refused our key.");
- free(comment);
- return 0;
- }
- /* Otherwise, the server should respond with a challenge. */
- if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
- packet_disconnect("Protocol error during RSA authentication: %d", type);
-
- /* Get the challenge from the packet. */
- if ((challenge = BN_new()) == NULL)
- fatal("try_rsa_authentication: BN_new failed");
- packet_get_bignum(challenge);
- packet_check_eom();
-
- debug("Received RSA challenge from server.");
-
- /*
- * If the key is not stored in external hardware, we have to
- * load the private key. Try first with empty passphrase; if it
- * fails, ask for a passphrase.
- */
- if (public->flags & SSHKEY_FLAG_EXT)
- private = public;
- else
- private = key_load_private_type(KEY_RSA1, authfile, "", NULL,
- &perm_ok);
- if (private == NULL && !options.batch_mode && perm_ok) {
- snprintf(buf, sizeof(buf),
- "Enter passphrase for RSA key '%.100s': ", comment);
- for (i = 0; i < options.number_of_password_prompts; i++) {
- passphrase = read_passphrase(buf, 0);
- if (strcmp(passphrase, "") != 0) {
- private = key_load_private_type(KEY_RSA1,
- authfile, passphrase, NULL, NULL);
- quit = 0;
- } else {
- debug2("no passphrase given, try next key");
- quit = 1;
- }
- explicit_bzero(passphrase, strlen(passphrase));
- free(passphrase);
- if (private != NULL || quit)
- break;
- debug2("bad passphrase given, try again...");
- }
- }
- /* We no longer need the comment. */
- free(comment);
-
- if (private == NULL) {
- if (!options.batch_mode && perm_ok)
- error("Bad passphrase.");
-
- /* Send a dummy response packet to avoid protocol error. */
- packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
- for (i = 0; i < 16; i++)
- packet_put_char(0);
- packet_send();
- packet_write_wait();
-
- /* Expect the server to reject it... */
- packet_read_expect(SSH_SMSG_FAILURE);
- BN_clear_free(challenge);
- return 0;
- }
-
- /* Compute and send a response to the challenge. */
- respond_to_rsa_challenge(challenge, private->rsa);
-
- /* Destroy the private key unless it in external hardware. */
- if (!(private->flags & SSHKEY_FLAG_EXT))
- key_free(private);
-
- /* We no longer need the challenge. */
- BN_clear_free(challenge);
-
- /* Wait for response from the server. */
- type = packet_read();
- if (type == SSH_SMSG_SUCCESS) {
- debug("RSA authentication accepted by server.");
- return 1;
- }
- if (type != SSH_SMSG_FAILURE)
- packet_disconnect("Protocol error waiting RSA auth response: %d", type);
- debug("RSA authentication refused.");
- return 0;
-}
-
-/*
- * Tries to authenticate the user using combined rhosts or /etc/hosts.equiv
- * authentication and RSA host authentication.
- */
-static int
-try_rhosts_rsa_authentication(const char *local_user, Key * host_key)
-{
- int type;
- BIGNUM *challenge;
-
- debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication.");
-
- /* Tell the server that we are willing to authenticate using this key. */
- packet_start(SSH_CMSG_AUTH_RHOSTS_RSA);
- packet_put_cstring(local_user);
- packet_put_int(BN_num_bits(host_key->rsa->n));
- packet_put_bignum(host_key->rsa->e);
- packet_put_bignum(host_key->rsa->n);
- packet_send();
- packet_write_wait();
-
- /* Wait for server's response. */
- type = packet_read();
-
- /* The server responds with failure if it doesn't admit our
- .rhosts authentication or doesn't know our host key. */
- if (type == SSH_SMSG_FAILURE) {
- debug("Server refused our rhosts authentication or host key.");
- return 0;
- }
- /* Otherwise, the server should respond with a challenge. */
- if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
- packet_disconnect("Protocol error during RSA authentication: %d", type);
-
- /* Get the challenge from the packet. */
- if ((challenge = BN_new()) == NULL)
- fatal("try_rhosts_rsa_authentication: BN_new failed");
- packet_get_bignum(challenge);
- packet_check_eom();
-
- debug("Received RSA challenge for host key from server.");
-
- /* Compute a response to the challenge. */
- respond_to_rsa_challenge(challenge, host_key->rsa);
-
- /* We no longer need the challenge. */
- BN_clear_free(challenge);
-
- /* Wait for response from the server. */
- type = packet_read();
- if (type == SSH_SMSG_SUCCESS) {
- debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server.");
- return 1;
- }
- if (type != SSH_SMSG_FAILURE)
- packet_disconnect("Protocol error waiting RSA auth response: %d", type);
- debug("Rhosts or /etc/hosts.equiv with RSA host authentication refused.");
- return 0;
-}
-
-/*
- * Tries to authenticate with any string-based challenge/response system.
- * Note that the client code is not tied to s/key or TIS.
- */
-static int
-try_challenge_response_authentication(void)
-{
- int type, i;
- u_int clen;
- char prompt[1024];
- char *challenge, *response;
-
- debug("Doing challenge response authentication.");
-
- for (i = 0; i < options.number_of_password_prompts; i++) {
- /* request a challenge */
- packet_start(SSH_CMSG_AUTH_TIS);
- packet_send();
- packet_write_wait();
-
- type = packet_read();
- if (type != SSH_SMSG_FAILURE &&
- type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
- packet_disconnect("Protocol error: got %d in response "
- "to SSH_CMSG_AUTH_TIS", type);
- }
- if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
- debug("No challenge.");
- return 0;
- }
- challenge = packet_get_string(&clen);
- packet_check_eom();
- snprintf(prompt, sizeof prompt, "%s%s", challenge,
- strchr(challenge, '\n') ? "" : "\nResponse: ");
- free(challenge);
- if (i != 0)
- error("Permission denied, please try again.");
- if (options.cipher == SSH_CIPHER_NONE)
- logit("WARNING: Encryption is disabled! "
- "Response will be transmitted in clear text.");
- response = read_passphrase(prompt, 0);
- if (strcmp(response, "") == 0) {
- free(response);
- break;
- }
- packet_start(SSH_CMSG_AUTH_TIS_RESPONSE);
- ssh_put_password(response);
- explicit_bzero(response, strlen(response));
- free(response);
- packet_send();
- packet_write_wait();
- type = packet_read();
- if (type == SSH_SMSG_SUCCESS)
- return 1;
- if (type != SSH_SMSG_FAILURE)
- packet_disconnect("Protocol error: got %d in response "
- "to SSH_CMSG_AUTH_TIS_RESPONSE", type);
- }
- /* failure */
- return 0;
-}
-
-/*
- * Tries to authenticate with plain passwd authentication.
- */
-static int
-try_password_authentication(char *prompt)
-{
- int type, i;
- char *password;
-
- debug("Doing password authentication.");
- if (options.cipher == SSH_CIPHER_NONE)
- logit("WARNING: Encryption is disabled! Password will be transmitted in clear text.");
- for (i = 0; i < options.number_of_password_prompts; i++) {
- if (i != 0)
- error("Permission denied, please try again.");
- password = read_passphrase(prompt, 0);
- packet_start(SSH_CMSG_AUTH_PASSWORD);
- ssh_put_password(password);
- explicit_bzero(password, strlen(password));
- free(password);
- packet_send();
- packet_write_wait();
-
- type = packet_read();
- if (type == SSH_SMSG_SUCCESS)
- return 1;
- if (type != SSH_SMSG_FAILURE)
- packet_disconnect("Protocol error: got %d in response to passwd auth", type);
- }
- /* failure */
- return 0;
-}
-
-/*
- * SSH1 key exchange
- */
-void
-ssh_kex(char *host, struct sockaddr *hostaddr)
-{
- int i;
- BIGNUM *key;
- Key *host_key, *server_key;
- int bits, rbits;
- int ssh_cipher_default = SSH_CIPHER_3DES;
- u_char session_key[SSH_SESSION_KEY_LENGTH];
- u_char cookie[8];
- u_int supported_ciphers;
- u_int server_flags, client_flags;
- u_int32_t rnd = 0;
-
- debug("Waiting for server public key.");
-
- /* Wait for a public key packet from the server. */
- packet_read_expect(SSH_SMSG_PUBLIC_KEY);
-
- /* Get cookie from the packet. */
- for (i = 0; i < 8; i++)
- cookie[i] = packet_get_char();
-
- /* Get the public key. */
- server_key = key_new(KEY_RSA1);
- bits = packet_get_int();
- packet_get_bignum(server_key->rsa->e);
- packet_get_bignum(server_key->rsa->n);
-
- rbits = BN_num_bits(server_key->rsa->n);
- if (bits != rbits) {
- logit("Warning: Server lies about size of server public key: "
- "actual size is %d bits vs. announced %d.", rbits, bits);
- logit("Warning: This may be due to an old implementation of ssh.");
- }
- /* Get the host key. */
- host_key = key_new(KEY_RSA1);
- bits = packet_get_int();
- packet_get_bignum(host_key->rsa->e);
- packet_get_bignum(host_key->rsa->n);
-
- rbits = BN_num_bits(host_key->rsa->n);
- if (bits != rbits) {
- logit("Warning: Server lies about size of server host key: "
- "actual size is %d bits vs. announced %d.", rbits, bits);
- logit("Warning: This may be due to an old implementation of ssh.");
- }
-
- /* Get protocol flags. */
- server_flags = packet_get_int();
- packet_set_protocol_flags(server_flags);
-
- supported_ciphers = packet_get_int();
- supported_authentications = packet_get_int();
- packet_check_eom();
-
- debug("Received server public key (%d bits) and host key (%d bits).",
- BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n));
-
- if (verify_host_key(host, hostaddr, host_key) == -1)
- fatal("Host key verification failed.");
-
- client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN;
-
- derive_ssh1_session_id(host_key->rsa->n, server_key->rsa->n, cookie, session_id);
-
- /*
- * Generate an encryption key for the session. The key is a 256 bit
- * random number, interpreted as a 32-byte key, with the least
- * significant 8 bits being the first byte of the key.
- */
- for (i = 0; i < 32; i++) {
- if (i % 4 == 0)
- rnd = arc4random();
- session_key[i] = rnd & 0xff;
- rnd >>= 8;
- }
-
- /*
- * According to the protocol spec, the first byte of the session key
- * is the highest byte of the integer. The session key is xored with
- * the first 16 bytes of the session id.
- */
- if ((key = BN_new()) == NULL)
- fatal("ssh_kex: BN_new failed");
- if (BN_set_word(key, 0) == 0)
- fatal("ssh_kex: BN_set_word failed");
- for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
- if (BN_lshift(key, key, 8) == 0)
- fatal("ssh_kex: BN_lshift failed");
- if (i < 16) {
- if (BN_add_word(key, session_key[i] ^ session_id[i])
- == 0)
- fatal("ssh_kex: BN_add_word failed");
- } else {
- if (BN_add_word(key, session_key[i]) == 0)
- fatal("ssh_kex: BN_add_word failed");
- }
- }
-
- /*
- * Encrypt the integer using the public key and host key of the
- * server (key with smaller modulus first).
- */
- if (BN_cmp(server_key->rsa->n, host_key->rsa->n) < 0) {
- /* Public key has smaller modulus. */
- if (BN_num_bits(host_key->rsa->n) <
- BN_num_bits(server_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
- fatal("respond_to_rsa_challenge: host_key %d < server_key %d + "
- "SSH_KEY_BITS_RESERVED %d",
- BN_num_bits(host_key->rsa->n),
- BN_num_bits(server_key->rsa->n),
- SSH_KEY_BITS_RESERVED);
- }
- if (rsa_public_encrypt(key, key, server_key->rsa) != 0 ||
- rsa_public_encrypt(key, key, host_key->rsa) != 0)
- fatal("%s: rsa_public_encrypt failed", __func__);
- } else {
- /* Host key has smaller modulus (or they are equal). */
- if (BN_num_bits(server_key->rsa->n) <
- BN_num_bits(host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
- fatal("respond_to_rsa_challenge: server_key %d < host_key %d + "
- "SSH_KEY_BITS_RESERVED %d",
- BN_num_bits(server_key->rsa->n),
- BN_num_bits(host_key->rsa->n),
- SSH_KEY_BITS_RESERVED);
- }
- if (rsa_public_encrypt(key, key, host_key->rsa) != 0 ||
- rsa_public_encrypt(key, key, server_key->rsa) != 0)
- fatal("%s: rsa_public_encrypt failed", __func__);
- }
-
- /* Destroy the public keys since we no longer need them. */
- key_free(server_key);
- key_free(host_key);
-
- if (options.cipher == SSH_CIPHER_NOT_SET) {
- if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default))
- options.cipher = ssh_cipher_default;
- } else if (options.cipher == SSH_CIPHER_INVALID ||
- !(cipher_mask_ssh1(1) & (1 << options.cipher))) {
- logit("No valid SSH1 cipher, using %.100s instead.",
- cipher_name(ssh_cipher_default));
- options.cipher = ssh_cipher_default;
- }
- /* Check that the selected cipher is supported. */
- if (!(supported_ciphers & (1 << options.cipher)))
- fatal("Selected cipher type %.100s not supported by server.",
- cipher_name(options.cipher));
-
- debug("Encryption type: %.100s", cipher_name(options.cipher));
-
- /* Send the encrypted session key to the server. */
- packet_start(SSH_CMSG_SESSION_KEY);
- packet_put_char(options.cipher);
-
- /* Send the cookie back to the server. */
- for (i = 0; i < 8; i++)
- packet_put_char(cookie[i]);
-
- /* Send and destroy the encrypted encryption key integer. */
- packet_put_bignum(key);
- BN_clear_free(key);
-
- /* Send protocol flags. */
- packet_put_int(client_flags);
-
- /* Send the packet now. */
- packet_send();
- packet_write_wait();
-
- debug("Sent encrypted session key.");
-
- /* Set the encryption key. */
- packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, options.cipher);
-
- /*
- * We will no longer need the session key here.
- * Destroy any extra copies.
- */
- explicit_bzero(session_key, sizeof(session_key));
-
- /*
- * Expect a success message from the server. Note that this message
- * will be received in encrypted form.
- */
- packet_read_expect(SSH_SMSG_SUCCESS);
-
- debug("Received encrypted confirmation.");
-}
-
-/*
- * Authenticate user
- */
-void
-ssh_userauth1(const char *local_user, const char *server_user, char *host,
- Sensitive *sensitive)
-{
- int i, type;
-
- if (supported_authentications == 0)
- fatal("ssh_userauth1: server supports no auth methods");
-
- /* Send the name of the user to log in as on the server. */
- packet_start(SSH_CMSG_USER);
- packet_put_cstring(server_user);
- packet_send();
- packet_write_wait();
-
- /*
- * The server should respond with success if no authentication is
- * needed (the user has no password). Otherwise the server responds
- * with failure.
- */
- type = packet_read();
-
- /* check whether the connection was accepted without authentication. */
- if (type == SSH_SMSG_SUCCESS)
- goto success;
- if (type != SSH_SMSG_FAILURE)
- packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", type);
-
- /*
- * Try .rhosts or /etc/hosts.equiv authentication with RSA host
- * authentication.
- */
- if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
- options.rhosts_rsa_authentication) {
- for (i = 0; i < sensitive->nkeys; i++) {
- if (sensitive->keys[i] != NULL &&
- sensitive->keys[i]->type == KEY_RSA1 &&
- try_rhosts_rsa_authentication(local_user,
- sensitive->keys[i]))
- goto success;
- }
- }
- /* Try RSA authentication if the server supports it. */
- if ((supported_authentications & (1 << SSH_AUTH_RSA)) &&
- options.rsa_authentication) {
- /*
- * Try RSA authentication using the authentication agent. The
- * agent is tried first because no passphrase is needed for
- * it, whereas identity files may require passphrases.
- */
- if (try_agent_authentication())
- goto success;
-
- /* Try RSA authentication for each identity. */
- for (i = 0; i < options.num_identity_files; i++)
- if (options.identity_keys[i] != NULL &&
- options.identity_keys[i]->type == KEY_RSA1 &&
- try_rsa_authentication(i))
- goto success;
- }
- /* Try challenge response authentication if the server supports it. */
- if ((supported_authentications & (1 << SSH_AUTH_TIS)) &&
- options.challenge_response_authentication && !options.batch_mode) {
- if (try_challenge_response_authentication())
- goto success;
- }
- /* Try password authentication if the server supports it. */
- if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) &&
- options.password_authentication && !options.batch_mode) {
- char prompt[80];
-
- snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
- server_user, host);
- if (try_password_authentication(prompt))
- goto success;
- }
- /* All authentication methods have failed. Exit with an error message. */
- fatal("Permission denied.");
- /* NOTREACHED */
-
- success:
- return; /* need statement after label */
-}
-
-#endif /* WITH_SSH1 */
diff --git a/sshconnect2.c b/sshconnect2.c
index ba56f643..1a6545ed 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect2.c,v 1.223 2015/01/30 11:43:14 djm Exp $ */
+/* $OpenBSD: sshconnect2.c,v 1.321 2020/04/17 03:38:47 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -36,9 +36,9 @@
#include <netdb.h>
#include <pwd.h>
#include <signal.h>
-#include <stdarg.h>
#include <stdio.h>
#include <string.h>
+#include <stdarg.h>
#include <unistd.h>
#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
#include <vis.h>
@@ -49,11 +49,11 @@
#include "xmalloc.h"
#include "ssh.h"
#include "ssh2.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "packet.h"
#include "compat.h"
#include "cipher.h"
-#include "key.h"
+#include "sshkey.h"
#include "kex.h"
#include "myproposal.h"
#include "sshconnect.h"
@@ -71,6 +71,9 @@
#include "uidswap.h"
#include "hostfile.h"
#include "ssherr.h"
+#include "utf8.h"
+#include "ssh-sk.h"
+#include "sk-api.h"
#ifdef GSSAPI
#include "ssh-gss.h"
@@ -92,7 +95,7 @@ char *xxx_host;
struct sockaddr *xxx_hostaddr;
static int
-verify_host_key_callback(Key *hostkey, struct ssh *ssh)
+verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
{
if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1)
fatal("Host key verification failed.");
@@ -116,7 +119,7 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
for (i = 0; i < options.num_system_hostfiles; i++)
load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
- oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG);
+ oavail = avail = xstrdup(options.hostkeyalgorithms);
maxlen = strlen(avail) + 1;
first = xmalloc(maxlen);
last = xmalloc(maxlen);
@@ -154,90 +157,96 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
}
void
-ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
+ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
{
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
- struct kex *kex;
- int r;
+ char *s, *all_key;
+ int r, use_known_hosts_order = 0;
xxx_host = host;
xxx_hostaddr = hostaddr;
- if (options.ciphers == (char *)-1) {
- logit("No valid ciphers for protocol version 2 given, using defaults.");
- options.ciphers = NULL;
- }
- if (options.ciphers != NULL) {
- myproposal[PROPOSAL_ENC_ALGS_CTOS] =
- myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
- }
+ /*
+ * If the user has not specified HostkeyAlgorithms, or has only
+ * appended or removed algorithms from that list then prefer algorithms
+ * that are in the list that are supported by known_hosts keys.
+ */
+ if (options.hostkeyalgorithms == NULL ||
+ options.hostkeyalgorithms[0] == '-' ||
+ options.hostkeyalgorithms[0] == '+')
+ use_known_hosts_order = 1;
+
+ /* Expand or fill in HostkeyAlgorithms */
+ all_key = sshkey_alg_list(0, 0, 1, ',');
+ if (kex_assemble_names(&options.hostkeyalgorithms,
+ kex_default_pk_alg(), all_key) != 0)
+ fatal("%s: kex_assemble_namelist", __func__);
+ 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);
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
- compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
+ compat_cipher_proposal(options.ciphers);
myproposal[PROPOSAL_ENC_ALGS_STOC] =
- compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
- if (options.compression) {
- myproposal[PROPOSAL_COMP_ALGS_CTOS] =
- myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib@openssh.com,zlib,none";
- } else {
- myproposal[PROPOSAL_COMP_ALGS_CTOS] =
- myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com,zlib";
- }
- if (options.macs != NULL) {
- myproposal[PROPOSAL_MAC_ALGS_CTOS] =
- myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
- }
- if (options.hostkeyalgorithms != NULL)
- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
- compat_pkalg_proposal(options.hostkeyalgorithms);
- else {
- /* Prefer algorithms that we already have keys for */
+ compat_cipher_proposal(options.ciphers);
+ myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+ myproposal[PROPOSAL_COMP_ALGS_STOC] =
+ (char *)compression_alg_list(options.compression);
+ myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+ myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+ 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));
+ } else {
+ /* Use specified HostkeyAlgorithms exactly */
+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
+ compat_pkalg_proposal(options.hostkeyalgorithms);
}
- if (options.kex_algorithms != NULL)
- myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
- myproposal[PROPOSAL_KEX_ALGS]);
if (options.rekey_limit || options.rekey_interval)
- packet_set_rekey_limits((u_int32_t)options.rekey_limit,
- (time_t)options.rekey_interval);
+ ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
+ options.rekey_interval);
/* start key exchange */
- if ((r = kex_setup(active_state, myproposal)) != 0)
+ if ((r = kex_setup(ssh, myproposal)) != 0)
fatal("kex_setup: %s", ssh_err(r));
- kex = active_state->kex;
#ifdef WITH_OPENSSL
- kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
- kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
- kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
- kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
+ ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
+ ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
# ifdef OPENSSL_HAS_ECC
- kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
+ ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client;
# endif
#endif
- kex->kex[KEX_C25519_SHA256] = kexc25519_client;
- kex->client_version_string=client_version_string;
- kex->server_version_string=server_version_string;
- kex->verify_host_key=&verify_host_key_callback;
+ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
+ ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
+ ssh->kex->verify_host_key=&verify_host_key_callback;
- dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
+ ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done);
- if (options.use_roaming && !kex->roaming) {
- debug("Roaming not allowed by server");
- options.use_roaming = 0;
- }
+ /* remove ext-info from the KEX proposals for rekeying */
+ myproposal[PROPOSAL_KEX_ALGS] =
+ compat_kex_proposal(options.kex_algorithms);
+ if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0)
+ fatal("kex_prop2buf: %s", ssh_err(r));
- session_id2 = kex->session_id;
- session_id2_len = kex->session_id_len;
+ session_id2 = ssh->kex->session_id;
+ session_id2_len = ssh->kex->session_id_len;
#ifdef DEBUG_KEXDH
/* send 1st encrypted/maced/compressed message */
- 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("%s: %s", __func__, ssh_err(r));
#endif
}
@@ -269,7 +278,11 @@ struct cauthctxt {
struct cauthmethod *method;
sig_atomic_t success;
char *authlist;
- int attempt;
+#ifdef GSSAPI
+ /* gssapi */
+ gss_OID_set gss_supported_mechs;
+ u_int mech_tried;
+#endif
/* pubkey */
struct idlist keys;
int agent_fd;
@@ -279,48 +292,53 @@ struct cauthctxt {
const char *active_ktype;
/* kbd-interactive */
int info_req_seen;
+ int attempt_kbdint;
+ /* password */
+ int attempt_passwd;
/* generic */
void *methoddata;
};
struct cauthmethod {
char *name; /* string to compare against server's list */
- int (*userauth)(Authctxt *authctxt);
- void (*cleanup)(Authctxt *authctxt);
+ int (*userauth)(struct ssh *ssh);
+ void (*cleanup)(struct ssh *ssh);
int *enabled; /* flag in option struct that enables method */
int *batch_flag; /* flag in option struct that disables method */
};
-int input_userauth_success(int, u_int32_t, void *);
-int input_userauth_success_unexpected(int, u_int32_t, void *);
-int input_userauth_failure(int, u_int32_t, void *);
-int input_userauth_banner(int, u_int32_t, void *);
-int input_userauth_error(int, u_int32_t, void *);
-int input_userauth_info_req(int, u_int32_t, void *);
-int input_userauth_pk_ok(int, u_int32_t, void *);
-int input_userauth_passwd_changereq(int, u_int32_t, void *);
-
-int userauth_none(Authctxt *);
-int userauth_pubkey(Authctxt *);
-int userauth_passwd(Authctxt *);
-int userauth_kbdint(Authctxt *);
-int userauth_hostbased(Authctxt *);
+static int input_userauth_service_accept(int, u_int32_t, struct ssh *);
+static int input_userauth_ext_info(int, u_int32_t, struct ssh *);
+static int input_userauth_success(int, u_int32_t, struct ssh *);
+static int input_userauth_failure(int, u_int32_t, struct ssh *);
+static int input_userauth_banner(int, u_int32_t, struct ssh *);
+static int input_userauth_error(int, u_int32_t, struct ssh *);
+static int input_userauth_info_req(int, u_int32_t, struct ssh *);
+static int input_userauth_pk_ok(int, u_int32_t, struct ssh *);
+static int input_userauth_passwd_changereq(int, u_int32_t, struct ssh *);
+
+static int userauth_none(struct ssh *);
+static int userauth_pubkey(struct ssh *);
+static int userauth_passwd(struct ssh *);
+static int userauth_kbdint(struct ssh *);
+static int userauth_hostbased(struct ssh *);
#ifdef GSSAPI
-int userauth_gssapi(Authctxt *authctxt);
-int input_gssapi_response(int type, u_int32_t, void *);
-int input_gssapi_token(int type, u_int32_t, void *);
-int input_gssapi_hash(int type, u_int32_t, void *);
-int input_gssapi_error(int, u_int32_t, void *);
-int input_gssapi_errtok(int, u_int32_t, void *);
+static int userauth_gssapi(struct ssh *);
+static void userauth_gssapi_cleanup(struct ssh *);
+static int input_gssapi_response(int type, u_int32_t, struct ssh *);
+static int input_gssapi_token(int type, u_int32_t, struct ssh *);
+static int input_gssapi_error(int, u_int32_t, struct ssh *);
+static int input_gssapi_errtok(int, u_int32_t, struct ssh *);
#endif
-void userauth(Authctxt *, char *);
+void userauth(struct ssh *, char *);
-static int sign_and_send_pubkey(Authctxt *, Identity *);
+static void pubkey_cleanup(struct ssh *);
+static int sign_and_send_pubkey(struct ssh *ssh, Identity *);
static void pubkey_prepare(Authctxt *);
-static void pubkey_cleanup(Authctxt *);
-static Key *load_identity_file(char *, int);
+static void pubkey_reset(Authctxt *);
+static struct sshkey *load_identity_file(Identity *);
static Authmethod *authmethod_get(char *authlist);
static Authmethod *authmethod_lookup(const char *name);
@@ -330,7 +348,7 @@ Authmethod authmethods[] = {
#ifdef GSSAPI
{"gssapi-with-mic",
userauth_gssapi,
- NULL,
+ userauth_gssapi_cleanup,
&options.gss_authentication,
NULL},
#endif
@@ -363,39 +381,19 @@ Authmethod authmethods[] = {
};
void
-ssh_userauth2(const char *local_user, const char *server_user, char *host,
- Sensitive *sensitive)
+ssh_userauth2(struct ssh *ssh, const char *local_user,
+ const char *server_user, char *host, Sensitive *sensitive)
{
Authctxt authctxt;
- int type;
+ int r;
if (options.challenge_response_authentication)
options.kbd_interactive_authentication = 1;
-
- packet_start(SSH2_MSG_SERVICE_REQUEST);
- packet_put_cstring("ssh-userauth");
- packet_send();
- debug("SSH2_MSG_SERVICE_REQUEST sent");
- packet_write_wait();
- type = packet_read();
- if (type != SSH2_MSG_SERVICE_ACCEPT)
- fatal("Server denied authentication request: %d", type);
- if (packet_remaining() > 0) {
- char *reply = packet_get_string(NULL);
- debug2("service_accept: %s", reply);
- free(reply);
- } else {
- debug2("buggy server: service_accept w/o service");
- }
- packet_check_eom();
- debug("SSH2_MSG_SERVICE_ACCEPT received");
-
if (options.preferred_authentications == NULL)
options.preferred_authentications = authmethods_get();
/* setup authentication context */
memset(&authctxt, 0, sizeof(authctxt));
- pubkey_prepare(&authctxt);
authctxt.server_user = server_user;
authctxt.local_user = local_user;
authctxt.host = host;
@@ -407,30 +405,85 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
authctxt.sensitive = sensitive;
authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL;
authctxt.info_req_seen = 0;
+ authctxt.attempt_kbdint = 0;
+ authctxt.attempt_passwd = 0;
+#if GSSAPI
+ authctxt.gss_supported_mechs = NULL;
+ authctxt.mech_tried = 0;
+#endif
authctxt.agent_fd = -1;
- if (authctxt.method == NULL)
- fatal("ssh_userauth2: internal error: cannot send userauth none request");
+ pubkey_prepare(&authctxt);
+ if (authctxt.method == NULL) {
+ fatal("%s: internal error: cannot send userauth none request",
+ __func__);
+ }
- /* initial userauth request */
- userauth_none(&authctxt);
+ 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));
- dispatch_init(&input_userauth_error);
- dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
- dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
- dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
- dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
+ ssh->authctxt = &authctxt;
+ ssh_dispatch_init(ssh, &input_userauth_error);
+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info);
+ ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept);
+ ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */
+ pubkey_cleanup(ssh);
+ ssh->authctxt = NULL;
- pubkey_cleanup(&authctxt);
- dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL);
+ ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL);
+ if (!authctxt.success)
+ fatal("Authentication failed.");
debug("Authentication succeeded (%s).", authctxt.method->name);
}
+/* ARGSUSED */
+static int
+input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh)
+{
+ int r;
+
+ if (ssh_packet_remaining(ssh) > 0) {
+ char *reply;
+
+ if ((r = sshpkt_get_cstring(ssh, &reply, NULL)) != 0)
+ goto out;
+ debug2("service_accept: %s", reply);
+ free(reply);
+ } else {
+ debug2("buggy server: service_accept w/o service");
+ }
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ goto out;
+ debug("SSH2_MSG_SERVICE_ACCEPT received");
+
+ /* initial userauth request */
+ userauth_none(ssh);
+
+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_error);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
+ r = 0;
+ out:
+ return r;
+}
+
+/* ARGSUSED */
+static int
+input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh)
+{
+ return kex_input_ext_info(type, seqnr, ssh);
+}
+
void
-userauth(Authctxt *authctxt, char *authlist)
+userauth(struct ssh *ssh, char *authlist)
{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+
if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
- authctxt->method->cleanup(authctxt);
+ authctxt->method->cleanup(ssh);
free(authctxt->methoddata);
authctxt->methoddata = NULL;
@@ -443,15 +496,16 @@ userauth(Authctxt *authctxt, char *authlist)
for (;;) {
Authmethod *method = authmethod_get(authlist);
if (method == NULL)
- fatal("Permission denied (%s).", authlist);
+ fatal("%s@%s: Permission denied (%s).",
+ authctxt->server_user, authctxt->host, authlist);
authctxt->method = method;
/* reset the per method handler */
- dispatch_range(SSH2_MSG_USERAUTH_PER_METHOD_MIN,
+ ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_PER_METHOD_MIN,
SSH2_MSG_USERAUTH_PER_METHOD_MAX, NULL);
/* and try new method */
- if (method->userauth(authctxt) != 0) {
+ if (method->userauth(ssh) != 0) {
debug2("we sent a %s packet, wait for reply", method->name);
break;
} else {
@@ -462,59 +516,56 @@ userauth(Authctxt *authctxt, char *authlist)
}
/* ARGSUSED */
-int
-input_userauth_error(int type, u_int32_t seq, void *ctxt)
+static int
+input_userauth_error(int type, u_int32_t seq, struct ssh *ssh)
{
- fatal("input_userauth_error: bad message during authentication: "
- "type %d", type);
+ fatal("%s: bad message during authentication: type %d", __func__, type);
return 0;
}
/* ARGSUSED */
-int
-input_userauth_banner(int type, u_int32_t seq, void *ctxt)
+static int
+input_userauth_banner(int type, u_int32_t seq, struct ssh *ssh)
{
- char *msg, *raw, *lang;
- u_int len;
-
- debug3("input_userauth_banner");
- raw = packet_get_string(&len);
- lang = packet_get_string(NULL);
- if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) {
- if (len > 65536)
- len = 65536;
- msg = xmalloc(len * 4 + 1); /* max expansion from strnvis() */
- strnvis(msg, raw, len * 4 + 1, VIS_SAFE|VIS_OCTAL|VIS_NOSLASH);
- fprintf(stderr, "%s", msg);
- free(msg);
- }
- free(raw);
- free(lang);
- return 0;
+ char *msg = NULL;
+ size_t len;
+ int r;
+
+ debug3("%s", __func__);
+ if ((r = sshpkt_get_cstring(ssh, &msg, &len)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0)
+ goto out;
+ if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO)
+ fmprintf(stderr, "%s", msg);
+ r = 0;
+ out:
+ free(msg);
+ return r;
}
/* ARGSUSED */
-int
-input_userauth_success(int type, u_int32_t seq, void *ctxt)
+static int
+input_userauth_success(int type, u_int32_t seq, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
+ Authctxt *authctxt = ssh->authctxt;
if (authctxt == NULL)
- fatal("input_userauth_success: no authentication context");
+ fatal("%s: no authentication context", __func__);
free(authctxt->authlist);
authctxt->authlist = NULL;
if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
- authctxt->method->cleanup(authctxt);
+ authctxt->method->cleanup(ssh);
free(authctxt->methoddata);
authctxt->methoddata = NULL;
authctxt->success = 1; /* break out */
return 0;
}
-int
-input_userauth_success_unexpected(int type, u_int32_t seq, void *ctxt)
+#if 0
+static int
+input_userauth_success_unexpected(int type, u_int32_t seq, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
+ Authctxt *authctxt = ssh->authctxt;
if (authctxt == NULL)
fatal("%s: no authentication context", __func__);
@@ -523,71 +574,95 @@ input_userauth_success_unexpected(int type, u_int32_t seq, void *ctxt)
authctxt->method->name);
return 0;
}
+#endif
/* ARGSUSED */
-int
-input_userauth_failure(int type, u_int32_t seq, void *ctxt)
+static int
+input_userauth_failure(int type, u_int32_t seq, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
+ Authctxt *authctxt = ssh->authctxt;
char *authlist = NULL;
- int partial;
+ u_char partial;
if (authctxt == NULL)
fatal("input_userauth_failure: no authentication context");
- authlist = packet_get_string(NULL);
- partial = packet_get_char();
- packet_check_eom();
+ if (sshpkt_get_cstring(ssh, &authlist, NULL) != 0 ||
+ sshpkt_get_u8(ssh, &partial) != 0 ||
+ sshpkt_get_end(ssh) != 0)
+ goto out;
if (partial != 0) {
- logit("Authenticated with partial success.");
+ verbose("Authenticated with partial success.");
/* reset state */
- pubkey_cleanup(authctxt);
- pubkey_prepare(authctxt);
+ pubkey_reset(authctxt);
}
debug("Authentications that can continue: %s", authlist);
- userauth(authctxt, authlist);
+ userauth(ssh, authlist);
+ authlist = NULL;
+ out:
+ free(authlist);
return 0;
}
+/*
+ * Format an identity for logging including filename, key type, fingerprint
+ * and location (agent, etc.). Caller must free.
+ */
+static char *
+format_identity(Identity *id)
+{
+ char *fp = NULL, *ret = NULL;
+ const char *note = "";
+
+ if (id->key != NULL) {
+ fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
+ SSH_FP_DEFAULT);
+ }
+ if (id->key) {
+ if ((id->key->flags & SSHKEY_FLAG_EXT) != 0)
+ note = " token";
+ else if (sshkey_is_sk(id->key))
+ note = " authenticator";
+ }
+ xasprintf(&ret, "%s %s%s%s%s%s%s",
+ id->filename,
+ id->key ? sshkey_type(id->key) : "", id->key ? " " : "",
+ fp ? fp : "",
+ id->userprovided ? " explicit" : "", note,
+ id->agent_fd != -1 ? " agent" : "");
+ free(fp);
+ return ret;
+}
+
/* ARGSUSED */
-int
-input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
+static int
+input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
- Key *key = NULL;
+ Authctxt *authctxt = ssh->authctxt;
+ struct sshkey *key = NULL;
Identity *id = NULL;
- Buffer b;
- int pktype, sent = 0;
- u_int alen, blen;
- char *pkalg, *fp;
- u_char *pkblob;
+ int pktype, found = 0, sent = 0;
+ size_t blen;
+ char *pkalg = NULL, *fp = NULL, *ident = NULL;
+ u_char *pkblob = NULL;
+ int r;
if (authctxt == NULL)
fatal("input_userauth_pk_ok: no authentication context");
- if (datafellows & SSH_BUG_PKOK) {
- /* this is similar to SSH_BUG_PKAUTH */
- debug2("input_userauth_pk_ok: SSH_BUG_PKOK");
- pkblob = packet_get_string(&blen);
- buffer_init(&b);
- buffer_append(&b, pkblob, blen);
- pkalg = buffer_get_string(&b, &alen);
- buffer_free(&b);
- } else {
- pkalg = packet_get_string(&alen);
- pkblob = packet_get_string(&blen);
- }
- packet_check_eom();
- debug("Server accepts key: pkalg %s blen %u", pkalg, blen);
+ if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
+ (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ goto done;
- if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
- debug("unknown pkalg %s", pkalg);
+ if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) {
+ debug("%s: server sent unknown pkalg %s", __func__, pkalg);
goto done;
}
- if ((key = key_from_blob(pkblob, blen)) == NULL) {
- debug("no key from blob. pkalg %s", pkalg);
+ if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
+ debug("no key from blob. pkalg %s: %s", pkalg, ssh_err(r));
goto done;
}
if (key->type != pktype) {
@@ -596,11 +671,6 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
key->type, pktype);
goto done;
}
- if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
- SSH_FP_DEFAULT)) == NULL)
- goto done;
- debug2("input_userauth_pk_ok: fp %s", fp);
- free(fp);
/*
* search keys in the reverse order, because last candidate has been
@@ -608,128 +678,164 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
* duplicate keys
*/
TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) {
- if (key_equal(key, id->key)) {
- sent = sign_and_send_pubkey(authctxt, id);
+ if (sshkey_equal(key, id->key)) {
+ found = 1;
break;
}
}
-done:
- if (key != NULL)
- key_free(key);
+ if (!found || id == NULL) {
+ fp = sshkey_fingerprint(key, options.fingerprint_hash,
+ SSH_FP_DEFAULT);
+ error("%s: server replied with unknown key: %s %s", __func__,
+ sshkey_type(key), fp == NULL ? "<ERROR>" : fp);
+ goto done;
+ }
+ ident = format_identity(id);
+ debug("Server accepts key: %s", ident);
+ sent = sign_and_send_pubkey(ssh, id);
+ r = 0;
+ done:
+ sshkey_free(key);
+ free(ident);
+ free(fp);
free(pkalg);
free(pkblob);
/* try another method if we did not send a packet */
- if (sent == 0)
- userauth(authctxt, NULL);
- return 0;
+ if (r == 0 && sent == 0)
+ userauth(ssh, NULL);
+ return r;
}
#ifdef GSSAPI
-int
-userauth_gssapi(Authctxt *authctxt)
+static int
+userauth_gssapi(struct ssh *ssh)
{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
Gssctxt *gssctxt = NULL;
- static gss_OID_set gss_supported = NULL;
- static u_int mech = 0;
OM_uint32 min;
- int ok = 0;
+ int r, ok = 0;
+ gss_OID mech = NULL;
/* Try one GSSAPI method at a time, rather than sending them all at
* once. */
- if (gss_supported == NULL)
- gss_indicate_mechs(&min, &gss_supported);
+ if (authctxt->gss_supported_mechs == NULL)
+ gss_indicate_mechs(&min, &authctxt->gss_supported_mechs);
- /* Check to see if the mechanism is usable before we offer it */
- while (mech < gss_supported->count && !ok) {
+ /* Check to see whether the mechanism is usable before we offer it */
+ while (authctxt->mech_tried < authctxt->gss_supported_mechs->count &&
+ !ok) {
+ mech = &authctxt->gss_supported_mechs->
+ elements[authctxt->mech_tried];
/* My DER encoding requires length<128 */
- if (gss_supported->elements[mech].length < 128 &&
- ssh_gssapi_check_mechanism(&gssctxt,
- &gss_supported->elements[mech], authctxt->host)) {
+ if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt,
+ mech, authctxt->host)) {
ok = 1; /* Mechanism works */
} else {
- mech++;
+ authctxt->mech_tried++;
}
}
- if (!ok)
+ if (!ok || mech == NULL)
return 0;
authctxt->methoddata=(void *)gssctxt;
- packet_start(SSH2_MSG_USERAUTH_REQUEST);
- packet_put_cstring(authctxt->server_user);
- packet_put_cstring(authctxt->service);
- packet_put_cstring(authctxt->method->name);
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
+ (r = sshpkt_put_u32(ssh, 1)) != 0 ||
+ (r = sshpkt_put_u32(ssh, (mech->length) + 2)) != 0 ||
+ (r = sshpkt_put_u8(ssh, SSH_GSS_OIDTYPE)) != 0 ||
+ (r = sshpkt_put_u8(ssh, mech->length)) != 0 ||
+ (r = sshpkt_put(ssh, mech->elements, mech->length)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
- packet_put_int(1);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
- packet_put_int((gss_supported->elements[mech].length) + 2);
- packet_put_char(SSH_GSS_OIDTYPE);
- packet_put_char(gss_supported->elements[mech].length);
- packet_put_raw(gss_supported->elements[mech].elements,
- gss_supported->elements[mech].length);
+ authctxt->mech_tried++; /* Move along to next candidate */
- packet_send();
+ return 1;
+}
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error);
- dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
+static void
+userauth_gssapi_cleanup(struct ssh *ssh)
+{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+ Gssctxt *gssctxt = (Gssctxt *)authctxt->methoddata;
- mech++; /* Move along to next candidate */
+ ssh_gssapi_delete_ctx(&gssctxt);
+ authctxt->methoddata = NULL;
- return 1;
+ free(authctxt->gss_supported_mechs);
+ authctxt->gss_supported_mechs = NULL;
}
static OM_uint32
-process_gssapi_token(void *ctxt, gss_buffer_t recv_tok)
+process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok)
{
- Authctxt *authctxt = ctxt;
+ Authctxt *authctxt = ssh->authctxt;
Gssctxt *gssctxt = authctxt->methoddata;
gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
gss_buffer_desc gssbuf;
OM_uint32 status, ms, flags;
- Buffer b;
+ int r;
status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
recv_tok, &send_tok, &flags);
if (send_tok.length > 0) {
- if (GSS_ERROR(status))
- packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
- else
- packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
+ u_char type = GSS_ERROR(status) ?
+ SSH2_MSG_USERAUTH_GSSAPI_ERRTOK :
+ SSH2_MSG_USERAUTH_GSSAPI_TOKEN;
+
+ if ((r = sshpkt_start(ssh, type)) != 0 ||
+ (r = sshpkt_put_string(ssh, send_tok.value,
+ send_tok.length)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
- packet_put_string(send_tok.value, send_tok.length);
- packet_send();
gss_release_buffer(&ms, &send_tok);
}
if (status == GSS_S_COMPLETE) {
/* send either complete or MIC, depending on mechanism */
if (!(flags & GSS_C_INTEG_FLAG)) {
- packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
- packet_send();
+ if ((r = sshpkt_start(ssh,
+ SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
} else {
- ssh_gssapi_buildmic(&b, authctxt->server_user,
+ struct sshbuf *b;
+
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ ssh_gssapi_buildmic(b, authctxt->server_user,
authctxt->service, "gssapi-with-mic");
- gssbuf.value = buffer_ptr(&b);
- gssbuf.length = buffer_len(&b);
+ if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL)
+ fatal("%s: sshbuf_mutable_ptr failed", __func__);
+ gssbuf.length = sshbuf_len(b);
status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic);
if (!GSS_ERROR(status)) {
- packet_start(SSH2_MSG_USERAUTH_GSSAPI_MIC);
- packet_put_string(mic.value, mic.length);
-
- packet_send();
+ if ((r = sshpkt_start(ssh,
+ SSH2_MSG_USERAUTH_GSSAPI_MIC)) != 0 ||
+ (r = sshpkt_put_string(ssh, mic.value,
+ mic.length)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
}
- buffer_free(&b);
+ sshbuf_free(b);
gss_release_buffer(&ms, &mic);
}
}
@@ -738,100 +844,112 @@ process_gssapi_token(void *ctxt, gss_buffer_t recv_tok)
}
/* ARGSUSED */
-int
-input_gssapi_response(int type, u_int32_t plen, void *ctxt)
+static int
+input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
+ Authctxt *authctxt = ssh->authctxt;
Gssctxt *gssctxt;
- int oidlen;
- char *oidv;
+ size_t oidlen;
+ u_char *oidv = NULL;
+ int r;
if (authctxt == NULL)
fatal("input_gssapi_response: no authentication context");
gssctxt = authctxt->methoddata;
/* Setup our OID */
- oidv = packet_get_string(&oidlen);
+ if ((r = sshpkt_get_string(ssh, &oidv, &oidlen)) != 0)
+ goto done;
if (oidlen <= 2 ||
oidv[0] != SSH_GSS_OIDTYPE ||
oidv[1] != oidlen - 2) {
- free(oidv);
debug("Badly encoded mechanism OID received");
- userauth(authctxt, NULL);
- return 0;
+ userauth(ssh, NULL);
+ goto ok;
}
if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2))
fatal("Server returned different OID than expected");
- packet_check_eom();
-
- free(oidv);
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ goto done;
- if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) {
+ if (GSS_ERROR(process_gssapi_token(ssh, GSS_C_NO_BUFFER))) {
/* Start again with next method on list */
debug("Trying to start again");
- userauth(authctxt, NULL);
- return 0;
+ userauth(ssh, NULL);
+ goto ok;
}
- return 0;
+ ok:
+ r = 0;
+ done:
+ free(oidv);
+ return r;
}
/* ARGSUSED */
-int
-input_gssapi_token(int type, u_int32_t plen, void *ctxt)
+static int
+input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
+ Authctxt *authctxt = ssh->authctxt;
gss_buffer_desc recv_tok;
+ u_char *p = NULL;
+ size_t len;
OM_uint32 status;
- u_int slen;
+ int r;
if (authctxt == NULL)
fatal("input_gssapi_response: no authentication context");
- recv_tok.value = packet_get_string(&slen);
- recv_tok.length = slen; /* safe typecast */
-
- packet_check_eom();
-
- status = process_gssapi_token(ctxt, &recv_tok);
+ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ goto out;
- free(recv_tok.value);
+ recv_tok.value = p;
+ recv_tok.length = len;
+ status = process_gssapi_token(ssh, &recv_tok);
+ /* Start again with the next method in the list */
if (GSS_ERROR(status)) {
- /* Start again with the next method in the list */
- userauth(authctxt, NULL);
- return 0;
+ userauth(ssh, NULL);
+ /* ok */
}
- return 0;
+ r = 0;
+ out:
+ free(p);
+ return r;
}
/* ARGSUSED */
-int
-input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
+static int
+input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
+ Authctxt *authctxt = ssh->authctxt;
Gssctxt *gssctxt;
gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
gss_buffer_desc recv_tok;
OM_uint32 ms;
- u_int len;
+ u_char *p = NULL;
+ size_t len;
+ int r;
if (authctxt == NULL)
fatal("input_gssapi_response: no authentication context");
gssctxt = authctxt->methoddata;
- recv_tok.value = packet_get_string(&len);
- recv_tok.length = len;
-
- packet_check_eom();
+ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0) {
+ free(p);
+ return r;
+ }
/* Stick it into GSSAPI and see what it says */
+ recv_tok.value = p;
+ recv_tok.length = len;
(void)ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
&recv_tok, &send_tok, NULL);
-
- free(recv_tok.value);
+ free(p);
gss_release_buffer(&ms, &send_tok);
/* Server will be returning a failed packet after this one */
@@ -839,68 +957,75 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
}
/* ARGSUSED */
-int
-input_gssapi_error(int type, u_int32_t plen, void *ctxt)
+static int
+input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh)
{
- char *msg;
- char *lang;
-
- /* maj */(void)packet_get_int();
- /* min */(void)packet_get_int();
- msg=packet_get_string(NULL);
- lang=packet_get_string(NULL);
-
- packet_check_eom();
+ char *msg = NULL;
+ char *lang = NULL;
+ int r;
+ if ((r = sshpkt_get_u32(ssh, NULL)) != 0 || /* maj */
+ (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* min */
+ (r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0)
+ goto out;
+ r = sshpkt_get_end(ssh);
debug("Server GSSAPI Error:\n%s", msg);
+ out:
free(msg);
free(lang);
- return 0;
+ return r;
}
#endif /* GSSAPI */
-int
-userauth_none(Authctxt *authctxt)
+static int
+userauth_none(struct ssh *ssh)
{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+ int r;
+
/* initial userauth request */
- packet_start(SSH2_MSG_USERAUTH_REQUEST);
- packet_put_cstring(authctxt->server_user);
- packet_put_cstring(authctxt->service);
- packet_put_cstring(authctxt->method->name);
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
return 1;
}
-int
-userauth_passwd(Authctxt *authctxt)
+static int
+userauth_passwd(struct ssh *ssh)
{
- static int attempt = 0;
- char prompt[150];
- char *password;
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+ char *password, *prompt = NULL;
const char *host = options.host_key_alias ? options.host_key_alias :
authctxt->host;
+ int r;
- if (attempt++ >= options.number_of_password_prompts)
+ if (authctxt->attempt_passwd++ >= options.number_of_password_prompts)
return 0;
- if (attempt != 1)
+ if (authctxt->attempt_passwd != 1)
error("Permission denied, please try again.");
- snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
- authctxt->server_user, host);
+ xasprintf(&prompt, "%s@%s's password: ", authctxt->server_user, host);
password = read_passphrase(prompt, 0);
- packet_start(SSH2_MSG_USERAUTH_REQUEST);
- packet_put_cstring(authctxt->server_user);
- packet_put_cstring(authctxt->service);
- packet_put_cstring(authctxt->method->name);
- packet_put_char(0);
- packet_put_cstring(password);
- explicit_bzero(password, strlen(password));
- free(password);
- packet_add_padding(64);
- packet_send();
-
- dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
+ (r = sshpkt_put_u8(ssh, 0)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, password)) != 0 ||
+ (r = sshpkt_add_padding(ssh, 64)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+
+ free(prompt);
+ if (password != NULL)
+ freezero(password, strlen(password));
+
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
&input_userauth_passwd_changereq);
return 1;
@@ -910,39 +1035,42 @@ userauth_passwd(Authctxt *authctxt)
* parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST
*/
/* ARGSUSED */
-int
-input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
+static int
+input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
- char *info, *lang, *password = NULL, *retype = NULL;
- char prompt[150];
- const char *host = options.host_key_alias ? options.host_key_alias :
- authctxt->host;
+ Authctxt *authctxt = ssh->authctxt;
+ char *info = NULL, *lang = NULL, *password = NULL, *retype = NULL;
+ char prompt[256];
+ const char *host;
+ int r;
debug2("input_userauth_passwd_changereq");
if (authctxt == NULL)
fatal("input_userauth_passwd_changereq: "
"no authentication context");
+ host = options.host_key_alias ? options.host_key_alias : authctxt->host;
- info = packet_get_string(NULL);
- lang = packet_get_string(NULL);
+ if ((r = sshpkt_get_cstring(ssh, &info, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0)
+ goto out;
if (strlen(info) > 0)
logit("%s", info);
- free(info);
- free(lang);
- packet_start(SSH2_MSG_USERAUTH_REQUEST);
- packet_put_cstring(authctxt->server_user);
- packet_put_cstring(authctxt->service);
- packet_put_cstring(authctxt->method->name);
- packet_put_char(1); /* additional info */
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
+ (r = sshpkt_put_u8(ssh, 1)) != 0) /* additional info */
+ goto out;
+
snprintf(prompt, sizeof(prompt),
"Enter %.30s@%.128s's old password: ",
authctxt->server_user, host);
password = read_passphrase(prompt, 0);
- packet_put_cstring(password);
- explicit_bzero(password, strlen(password));
- free(password);
+ if ((r = sshpkt_put_cstring(ssh, password)) != 0)
+ goto out;
+
+ freezero(password, strlen(password));
password = NULL;
while (password == NULL) {
snprintf(prompt, sizeof(prompt),
@@ -951,194 +1079,387 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
password = read_passphrase(prompt, RP_ALLOW_EOF);
if (password == NULL) {
/* bail out */
- return 0;
+ r = 0;
+ goto out;
}
snprintf(prompt, sizeof(prompt),
"Retype %.30s@%.128s's new password: ",
authctxt->server_user, host);
retype = read_passphrase(prompt, 0);
if (strcmp(password, retype) != 0) {
- explicit_bzero(password, strlen(password));
- free(password);
+ freezero(password, strlen(password));
logit("Mismatch; try again, EOF to quit.");
password = NULL;
}
- explicit_bzero(retype, strlen(retype));
- free(retype);
+ freezero(retype, strlen(retype));
}
- packet_put_cstring(password);
- explicit_bzero(password, strlen(password));
- free(password);
- packet_add_padding(64);
- packet_send();
+ if ((r = sshpkt_put_cstring(ssh, password)) != 0 ||
+ (r = sshpkt_add_padding(ssh, 64)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ goto out;
- dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
&input_userauth_passwd_changereq);
- return 0;
+ r = 0;
+ out:
+ if (password)
+ freezero(password, strlen(password));
+ free(info);
+ free(lang);
+ return r;
+}
+
+/*
+ * Select an algorithm for publickey signatures.
+ * Returns algorithm (caller must free) or NULL if no mutual algorithm found.
+ *
+ * Call with ssh==NULL to ignore server-sig-algs extension list and
+ * only attempt with the key's base signature type.
+ */
+static char *
+key_sig_algorithm(struct ssh *ssh, const struct sshkey *key)
+{
+ char *allowed, *oallowed, *cp, *tmp, *alg = NULL;
+
+ /*
+ * The signature algorithm will only differ from the key algorithm
+ * for RSA keys/certs and when the server advertises support for
+ * newer (SHA2) algorithms.
+ */
+ if (ssh == NULL || ssh->kex->server_sig_algs == NULL ||
+ (key->type != KEY_RSA && key->type != KEY_RSA_CERT) ||
+ (key->type == KEY_RSA_CERT && (datafellows & SSH_BUG_SIGTYPE))) {
+ /* Filter base key signature alg against our configuration */
+ return match_list(sshkey_ssh_name(key),
+ options.pubkey_key_types, NULL);
+ }
+
+ /*
+ * For RSA keys/certs, since these might have a different sig type:
+ * find the first entry in PubkeyAcceptedKeyTypes of the right type
+ * that also appears in the supported signature algorithms list from
+ * the server.
+ */
+ oallowed = allowed = xstrdup(options.pubkey_key_types);
+ while ((cp = strsep(&allowed, ",")) != NULL) {
+ if (sshkey_type_from_name(cp) != key->type)
+ continue;
+ tmp = match_list(sshkey_sigalg_by_name(cp), ssh->kex->server_sig_algs, NULL);
+ if (tmp != NULL)
+ alg = xstrdup(cp);
+ free(tmp);
+ if (alg != NULL)
+ break;
+ }
+ free(oallowed);
+ return alg;
}
static int
identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, u_int compat)
+ const u_char *data, size_t datalen, u_int compat, const char *alg)
{
- Key *prv;
- int ret;
+ struct sshkey *sign_key = NULL, *prv = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ struct notifier_ctx *notifier = NULL;
+ char *fp = NULL;
+
+ *sigp = NULL;
+ *lenp = 0;
- /* the agent supports this key */
- if (id->agent_fd)
+ /* The agent supports this key. */
+ if (id->key != NULL && id->agent_fd != -1) {
return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp,
- data, datalen, compat);
+ data, datalen, alg, compat);
+ }
/*
- * we have already loaded the private key or
- * the private key is stored in external hardware
+ * We have already loaded the private key or the private key is
+ * stored in external hardware.
*/
- if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))
- return (sshkey_sign(id->key, sigp, lenp, data, datalen,
- compat));
- /* load the private key from the file */
- if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL)
- return (-1); /* XXX return decent error code */
- ret = sshkey_sign(prv, sigp, lenp, data, datalen, compat);
+ if (id->key != NULL &&
+ (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) {
+ sign_key = id->key;
+ } else {
+ /* Load the private key from the file. */
+ if ((prv = load_identity_file(id)) == NULL)
+ return SSH_ERR_KEY_NOT_FOUND;
+ if (id->key != NULL && !sshkey_equal_public(prv, id->key)) {
+ error("%s: private key %s contents do not match public",
+ __func__, 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 ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen,
+ alg, options.sk_provider, compat)) != 0) {
+ debug("%s: sshkey_sign: %s", __func__, ssh_err(r));
+ 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));
+ goto out;
+ }
+ /* success */
+ r = 0;
+ out:
+ notify_complete(notifier);
sshkey_free(prv);
- return (ret);
+ return r;
+}
+
+static int
+id_filename_matches(Identity *id, Identity *private_id)
+{
+ const char *suffixes[] = { ".pub", "-cert.pub", NULL };
+ size_t len = strlen(id->filename), plen = strlen(private_id->filename);
+ size_t i, slen;
+
+ if (strcmp(id->filename, private_id->filename) == 0)
+ return 1;
+ for (i = 0; suffixes[i]; i++) {
+ slen = strlen(suffixes[i]);
+ if (len > slen && plen == len - slen &&
+ strcmp(id->filename + (len - slen), suffixes[i]) == 0 &&
+ memcmp(id->filename, private_id->filename, plen) == 0)
+ return 1;
+ }
+ return 0;
}
static int
-sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
+sign_and_send_pubkey(struct ssh *ssh, Identity *id)
{
- Buffer b;
- u_char *blob, *signature;
- u_int bloblen;
- size_t slen;
- u_int skip = 0;
- int ret = -1;
- int have_sig = 1;
- char *fp;
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+ struct sshbuf *b = NULL;
+ Identity *private_id, *sign_id = NULL;
+ u_char *signature = NULL;
+ size_t slen = 0, skip = 0;
+ int r, fallback_sigtype, sent = 0;
+ char *alg = NULL, *fp = NULL;
+ const char *loc = "";
if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
return 0;
- debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
- free(fp);
- if (key_to_blob(id->key, &blob, &bloblen) == 0) {
- /* we cannot handle this key */
- debug3("sign_and_send_pubkey: cannot handle key");
- return 0;
- }
- /* data to be signed */
- buffer_init(&b);
- if (datafellows & SSH_OLD_SESSIONID) {
- buffer_append(&b, session_id2, session_id2_len);
- skip = session_id2_len;
- } else {
- buffer_put_string(&b, session_id2, session_id2_len);
- skip = buffer_len(&b);
- }
- buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
- buffer_put_cstring(&b, authctxt->server_user);
- buffer_put_cstring(&b,
- datafellows & SSH_BUG_PKSERVICE ?
- "ssh-userauth" :
- authctxt->service);
- if (datafellows & SSH_BUG_PKAUTH) {
- buffer_put_char(&b, have_sig);
- } else {
- buffer_put_cstring(&b, authctxt->method->name);
- buffer_put_char(&b, have_sig);
- buffer_put_cstring(&b, key_ssh_name(id->key));
- }
- buffer_put_string(&b, blob, bloblen);
-
- /* generate signature */
- ret = identity_sign(id, &signature, &slen,
- buffer_ptr(&b), buffer_len(&b), datafellows);
- if (ret != 0) {
- free(blob);
- buffer_free(&b);
- return 0;
+ debug3("%s: %s %s", __func__, sshkey_type(id->key), fp);
+
+ /*
+ * If the key is an certificate, try to find a matching private key
+ * and use it to complete the signature.
+ * If no such private key exists, fall back to trying the certificate
+ * key itself in case it has a private half already loaded.
+ * This will try to set sign_id to the private key that will perform
+ * the signature.
+ */
+ if (sshkey_is_cert(id->key)) {
+ TAILQ_FOREACH(private_id, &authctxt->keys, next) {
+ if (sshkey_equal_public(id->key, private_id->key) &&
+ id->key->type != private_id->key->type) {
+ sign_id = private_id;
+ break;
+ }
+ }
+ /*
+ * Exact key matches are preferred, but also allow
+ * filename matches for non-PKCS#11/agent keys that
+ * didn't load public keys. This supports the case
+ * of keeping just a private key file and public
+ * certificate on disk.
+ */
+ if (sign_id == NULL &&
+ !id->isprivate && id->agent_fd == -1 &&
+ (id->key->flags & SSHKEY_FLAG_EXT) == 0) {
+ TAILQ_FOREACH(private_id, &authctxt->keys, next) {
+ if (private_id->key == NULL &&
+ id_filename_matches(id, private_id)) {
+ sign_id = private_id;
+ break;
+ }
+ }
+ }
+ if (sign_id != NULL) {
+ debug2("%s: using private key \"%s\"%s for "
+ "certificate", __func__, id->filename,
+ id->agent_fd != -1 ? " from agent" : "");
+ } else {
+ debug("%s: no separate private key for certificate "
+ "\"%s\"", __func__, id->filename);
+ }
}
-#ifdef DEBUG_PK
- buffer_dump(&b);
-#endif
- if (datafellows & SSH_BUG_PKSERVICE) {
- buffer_clear(&b);
- buffer_append(&b, session_id2, session_id2_len);
- skip = session_id2_len;
- buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
- buffer_put_cstring(&b, authctxt->server_user);
- buffer_put_cstring(&b, authctxt->service);
- buffer_put_cstring(&b, authctxt->method->name);
- buffer_put_char(&b, have_sig);
- if (!(datafellows & SSH_BUG_PKAUTH))
- buffer_put_cstring(&b, key_ssh_name(id->key));
- buffer_put_string(&b, blob, bloblen);
+
+ /*
+ * If the above didn't select another identity to do the signing
+ * then default to the one we started with.
+ */
+ if (sign_id == NULL)
+ sign_id = id;
+
+ /* assemble and sign data */
+ for (fallback_sigtype = 0; fallback_sigtype <= 1; fallback_sigtype++) {
+ free(alg);
+ slen = 0;
+ signature = NULL;
+ if ((alg = key_sig_algorithm(fallback_sigtype ? NULL : ssh,
+ id->key)) == NULL) {
+ error("%s: no mutual signature supported", __func__);
+ goto out;
+ }
+ debug3("%s: signing using %s %s", __func__, 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));
+ }
+ } else {
+ if ((r = sshbuf_put_string(b, session_id2,
+ session_id2_len)) != 0) {
+ fatal("%s: sshbuf_put_string: %s",
+ __func__, ssh_err(r));
+ }
+ }
+ skip = sshbuf_len(b);
+ if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
+ (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 ||
+ (r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
+ (r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 ||
+ (r = sshbuf_put_u8(b, 1)) != 0 ||
+ (r = sshbuf_put_cstring(b, alg)) != 0 ||
+ (r = sshkey_puts(id->key, b)) != 0) {
+ fatal("%s: assemble signed data: %s",
+ __func__, ssh_err(r));
+ }
+
+ /* generate signature */
+ r = identity_sign(sign_id, &signature, &slen,
+ sshbuf_ptr(b), sshbuf_len(b), datafellows, alg);
+ if (r == 0)
+ break;
+ else if (r == SSH_ERR_KEY_NOT_FOUND)
+ goto out; /* soft failure */
+ else if (r == SSH_ERR_SIGN_ALG_UNSUPPORTED &&
+ !fallback_sigtype) {
+ if (sign_id->agent_fd != -1)
+ loc = "agent ";
+ else if ((sign_id->key->flags & SSHKEY_FLAG_EXT) != 0)
+ loc = "token ";
+ logit("%skey %s %s returned incorrect signature type",
+ loc, sshkey_type(id->key), fp);
+ continue;
+ }
+ error("%s: signing failed for %s \"%s\"%s: %s", __func__,
+ sshkey_type(sign_id->key), sign_id->filename,
+ id->agent_fd != -1 ? " from agent" : "", ssh_err(r));
+ goto out;
}
- free(blob);
+ if (slen == 0 || signature == NULL) /* shouldn't happen */
+ fatal("%s: no signature", __func__);
/* append signature */
- buffer_put_string(&b, signature, slen);
- free(signature);
+ if ((r = sshbuf_put_string(b, signature, slen)) != 0)
+ fatal("%s: append signature: %s", __func__, ssh_err(r));
+#ifdef DEBUG_PK
+ sshbuf_dump(b, stderr);
+#endif
/* skip session id and packet type */
- if (buffer_len(&b) < skip + 1)
- fatal("userauth_pubkey: internal error");
- buffer_consume(&b, skip + 1);
+ if ((r = sshbuf_consume(b, skip + 1)) != 0)
+ fatal("%s: consume: %s", __func__, ssh_err(r));
/* put remaining data from buffer into packet */
- packet_start(SSH2_MSG_USERAUTH_REQUEST);
- packet_put_raw(buffer_ptr(&b), buffer_len(&b));
- buffer_free(&b);
- packet_send();
+ 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));
- return 1;
+ /* success */
+ sent = 1;
+
+ out:
+ free(fp);
+ free(alg);
+ sshbuf_free(b);
+ freezero(signature, slen);
+ return sent;
}
static int
-send_pubkey_test(Authctxt *authctxt, Identity *id)
+send_pubkey_test(struct ssh *ssh, Identity *id)
{
- u_char *blob;
- u_int bloblen, have_sig = 0;
-
- debug3("send_pubkey_test");
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+ u_char *blob = NULL;
+ char *alg = NULL;
+ size_t bloblen;
+ u_int have_sig = 0;
+ int sent = 0, r;
+
+ if ((alg = key_sig_algorithm(ssh, id->key)) == NULL) {
+ debug("%s: no mutual signature algorithm", __func__);
+ goto out;
+ }
- if (key_to_blob(id->key, &blob, &bloblen) == 0) {
+ if ((r = sshkey_to_blob(id->key, &blob, &bloblen)) != 0) {
/* we cannot handle this key */
- debug3("send_pubkey_test: cannot handle key");
- return 0;
+ debug3("%s: cannot handle key", __func__);
+ goto out;
}
/* register callback for USERAUTH_PK_OK message */
- dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
-
- packet_start(SSH2_MSG_USERAUTH_REQUEST);
- packet_put_cstring(authctxt->server_user);
- packet_put_cstring(authctxt->service);
- packet_put_cstring(authctxt->method->name);
- packet_put_char(have_sig);
- if (!(datafellows & SSH_BUG_PKAUTH))
- packet_put_cstring(key_ssh_name(id->key));
- packet_put_string(blob, bloblen);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
+
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
+ (r = sshpkt_put_u8(ssh, have_sig)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, alg)) != 0 ||
+ (r = sshpkt_put_string(ssh, blob, bloblen)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+ sent = 1;
+
+ out:
+ free(alg);
free(blob);
- packet_send();
- return 1;
+ return sent;
}
-static Key *
-load_identity_file(char *filename, int userprovided)
+static struct sshkey *
+load_identity_file(Identity *id)
{
- Key *private;
- char prompt[300], *passphrase;
- int r, perm_ok = 0, quit = 0, i;
+ struct sshkey *private = NULL;
+ char prompt[300], *passphrase, *comment;
+ int r, quit = 0, i;
struct stat st;
- if (stat(filename, &st) < 0) {
- (userprovided ? logit : debug3)("no such identity: %s: %s",
- filename, strerror(errno));
+ if (stat(id->filename, &st) == -1) {
+ (id->userprovided ? logit : debug3)("no such identity: %s: %s",
+ id->filename, strerror(errno));
return NULL;
}
snprintf(prompt, sizeof prompt,
- "Enter passphrase for key '%.100s': ", filename);
+ "Enter passphrase for key '%.100s': ", id->filename);
for (i = 0; i <= options.number_of_password_prompts; i++) {
if (i == 0)
passphrase = "";
@@ -1150,8 +1471,8 @@ load_identity_file(char *filename, int userprovided)
break;
}
}
- switch ((r = sshkey_load_private_type(KEY_UNSPEC, filename,
- passphrase, &private, NULL, &perm_ok))) {
+ switch ((r = sshkey_load_private_type(KEY_UNSPEC, id->filename,
+ passphrase, &private, &comment))) {
case 0:
break;
case SSH_ERR_KEY_WRONG_PASSPHRASE:
@@ -1165,31 +1486,74 @@ load_identity_file(char *filename, int userprovided)
case SSH_ERR_SYSTEM_ERROR:
if (errno == ENOENT) {
debug2("Load key \"%s\": %s",
- filename, ssh_err(r));
+ id->filename, ssh_err(r));
quit = 1;
break;
}
/* FALLTHROUGH */
default:
- error("Load key \"%s\": %s", filename, ssh_err(r));
+ error("Load key \"%s\": %s", id->filename, ssh_err(r));
quit = 1;
break;
}
- if (i > 0) {
- explicit_bzero(passphrase, strlen(passphrase));
- free(passphrase);
+ if (private != NULL && sshkey_is_sk(private) &&
+ options.sk_provider == NULL) {
+ debug("key \"%s\" is an authenticator-hosted key, "
+ "but no provider specified", id->filename);
+ sshkey_free(private);
+ private = NULL;
+ quit = 1;
}
+ if (!quit && private != NULL && id->agent_fd == -1 &&
+ !(id->key && id->isprivate))
+ maybe_add_key_to_agent(id->filename, private, comment,
+ passphrase);
+ if (i > 0)
+ freezero(passphrase, strlen(passphrase));
+ free(comment);
if (private != NULL || quit)
break;
}
return private;
}
+static int
+key_type_allowed_by_config(struct sshkey *key)
+{
+ if (match_pattern_list(sshkey_ssh_name(key),
+ options.pubkey_key_types, 0) == 1)
+ return 1;
+
+ /* RSA keys/certs might be allowed by alternate signature types */
+ switch (key->type) {
+ case KEY_RSA:
+ if (match_pattern_list("rsa-sha2-512",
+ options.pubkey_key_types, 0) == 1)
+ return 1;
+ if (match_pattern_list("rsa-sha2-256",
+ options.pubkey_key_types, 0) == 1)
+ return 1;
+ break;
+ case KEY_RSA_CERT:
+ if (match_pattern_list("rsa-sha2-512-cert-v01@openssh.com",
+ options.pubkey_key_types, 0) == 1)
+ return 1;
+ if (match_pattern_list("rsa-sha2-256-cert-v01@openssh.com",
+ options.pubkey_key_types, 0) == 1)
+ return 1;
+ break;
+ }
+ return 0;
+}
+
+
/*
* try keys in the following order:
- * 1. agent keys that are found in the config file
- * 2. other agent keys
- * 3. keys that are only listed in the config file
+ * 1. certificates listed in the config file
+ * 2. other input certificates
+ * 3. agent keys that are found in the config file
+ * 4. other agent keys
+ * 5. keys that are only listed in the config file
*/
static void
pubkey_prepare(Authctxt *authctxt)
@@ -1197,9 +1561,10 @@ pubkey_prepare(Authctxt *authctxt)
struct identity *id, *id2, *tmp;
struct idlist agent, files, *preferred;
struct sshkey *key;
- int agent_fd, i, r, found;
+ int agent_fd = -1, i, r, found;
size_t j;
struct ssh_identitylist *idlist;
+ char *ident;
TAILQ_INIT(&agent); /* keys from the agent */
TAILQ_INIT(&files); /* keys from the config file */
@@ -1209,49 +1574,61 @@ pubkey_prepare(Authctxt *authctxt)
/* list of keys stored in the filesystem and PKCS#11 */
for (i = 0; i < options.num_identity_files; i++) {
key = options.identity_keys[i];
- if (key && key->type == KEY_RSA1)
+ 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]);
continue;
- if (key && key->cert && key->cert->type != SSH2_CERT_TYPE_USER)
+ }
+ if (key && sshkey_is_sk(key) && options.sk_provider == NULL) {
+ debug("%s: ignoring authenticator-hosted key %s as no "
+ "SecurityKeyProvider has been specified",
+ __func__, options.identity_files[i]);
continue;
+ }
options.identity_keys[i] = NULL;
id = xcalloc(1, sizeof(*id));
+ id->agent_fd = -1;
id->key = key;
id->filename = xstrdup(options.identity_files[i]);
id->userprovided = options.identity_file_userprovided[i];
TAILQ_INSERT_TAIL(&files, id, next);
}
- /* Prefer PKCS11 keys that are explicitly listed */
- TAILQ_FOREACH_SAFE(id, &files, next, tmp) {
- if (id->key == NULL || (id->key->flags & SSHKEY_FLAG_EXT) == 0)
+ /* list of certificates specified by user */
+ for (i = 0; i < options.num_certificate_files; i++) {
+ key = options.certificates[i];
+ if (!sshkey_is_cert(key) || key->cert == NULL ||
+ key->cert->type != SSH2_CERT_TYPE_USER) {
+ debug("%s: ignoring certificate %s: not a user "
+ "certificate", __func__,
+ options.identity_files[i]);
continue;
- found = 0;
- TAILQ_FOREACH(id2, &files, next) {
- if (id2->key == NULL ||
- (id2->key->flags & SSHKEY_FLAG_EXT) == 0)
- continue;
- if (sshkey_equal(id->key, id2->key)) {
- TAILQ_REMOVE(&files, id, next);
- TAILQ_INSERT_TAIL(preferred, id, next);
- found = 1;
- break;
- }
}
- /* If IdentitiesOnly set and key not found then don't use it */
- if (!found && options.identities_only) {
- TAILQ_REMOVE(&files, id, next);
- explicit_bzero(id, sizeof(*id));
- free(id);
+ if (key && sshkey_is_sk(key) && options.sk_provider == NULL) {
+ debug("%s: ignoring authenticator-hosted key "
+ "certificate %s as no "
+ "SecurityKeyProvider has been specified",
+ __func__, options.identity_files[i]);
+ continue;
}
+ id = xcalloc(1, sizeof(*id));
+ id->agent_fd = -1;
+ id->key = key;
+ id->filename = xstrdup(options.certificate_files[i]);
+ id->userprovided = options.certificate_file_userprovided[i];
+ TAILQ_INSERT_TAIL(preferred, id, next);
}
/* list of keys supported by the agent */
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
if (r != SSH_ERR_AGENT_NOT_PRESENT)
debug("%s: ssh_get_authentication_socket: %s",
__func__, ssh_err(r));
- } else if ((r = ssh_fetch_identitylist(agent_fd, 2, &idlist)) != 0) {
+ } else if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) {
if (r != SSH_ERR_AGENT_NO_IDENTITIES)
debug("%s: ssh_fetch_identitylist: %s",
__func__, ssh_err(r));
+ close(agent_fd);
} else {
for (j = 0; j < idlist->nkeys; j++) {
found = 0;
@@ -1287,39 +1664,104 @@ pubkey_prepare(Authctxt *authctxt)
}
authctxt->agent_fd = agent_fd;
}
+ /* Prefer PKCS11 keys that are explicitly listed */
+ TAILQ_FOREACH_SAFE(id, &files, next, tmp) {
+ if (id->key == NULL || (id->key->flags & SSHKEY_FLAG_EXT) == 0)
+ continue;
+ found = 0;
+ TAILQ_FOREACH(id2, &files, next) {
+ if (id2->key == NULL ||
+ (id2->key->flags & SSHKEY_FLAG_EXT) != 0)
+ continue;
+ if (sshkey_equal(id->key, id2->key)) {
+ TAILQ_REMOVE(&files, id, next);
+ TAILQ_INSERT_TAIL(preferred, id, next);
+ found = 1;
+ break;
+ }
+ }
+ /* If IdentitiesOnly set and key not found then don't use it */
+ if (!found && options.identities_only) {
+ TAILQ_REMOVE(&files, id, next);
+ freezero(id, sizeof(*id));
+ }
+ }
/* append remaining keys from the config file */
for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
TAILQ_REMOVE(&files, id, next);
TAILQ_INSERT_TAIL(preferred, id, next);
}
- TAILQ_FOREACH(id, preferred, next) {
- debug2("key: %s (%p),%s", id->filename, id->key,
- id->userprovided ? " explicit" : "");
+ /* finally, filter by PubkeyAcceptedKeyTypes */
+ TAILQ_FOREACH_SAFE(id, preferred, next, id2) {
+ if (id->key != NULL && !key_type_allowed_by_config(id->key)) {
+ debug("Skipping %s key %s - "
+ "not in PubkeyAcceptedKeyTypes",
+ sshkey_ssh_name(id->key), id->filename);
+ TAILQ_REMOVE(preferred, id, next);
+ sshkey_free(id->key);
+ free(id->filename);
+ memset(id, 0, sizeof(*id));
+ continue;
+ }
+ }
+ /* List the keys we plan on using */
+ TAILQ_FOREACH_SAFE(id, preferred, next, id2) {
+ ident = format_identity(id);
+ debug("Will attempt key: %s", ident);
+ free(ident);
}
+ debug2("%s: done", __func__);
}
static void
-pubkey_cleanup(Authctxt *authctxt)
+pubkey_cleanup(struct ssh *ssh)
{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
Identity *id;
- if (authctxt->agent_fd != -1)
+ if (authctxt->agent_fd != -1) {
ssh_close_authentication_socket(authctxt->agent_fd);
+ authctxt->agent_fd = -1;
+ }
for (id = TAILQ_FIRST(&authctxt->keys); id;
id = TAILQ_FIRST(&authctxt->keys)) {
TAILQ_REMOVE(&authctxt->keys, id, next);
- if (id->key)
- sshkey_free(id->key);
+ sshkey_free(id->key);
free(id->filename);
free(id);
}
}
-int
-userauth_pubkey(Authctxt *authctxt)
+static void
+pubkey_reset(Authctxt *authctxt)
{
Identity *id;
+
+ TAILQ_FOREACH(id, &authctxt->keys, next)
+ id->tried = 0;
+}
+
+static int
+try_identity(Identity *id)
+{
+ if (!id->key)
+ return (0);
+ if (sshkey_type_plain(id->key->type) == KEY_RSA &&
+ (datafellows & SSH_BUG_RSASIGMD5) != 0) {
+ debug("Skipped %s key %s for RSA/MD5 server",
+ sshkey_type(id->key), id->filename);
+ return (0);
+ }
+ return 1;
+}
+
+static int
+userauth_pubkey(struct ssh *ssh)
+{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+ Identity *id;
int sent = 0;
+ char *ident;
while ((id = TAILQ_FIRST(&authctxt->keys))) {
if (id->tried++)
@@ -1333,32 +1775,23 @@ userauth_pubkey(Authctxt *authctxt)
* private key instead
*/
if (id->key != NULL) {
- if (key_type_plain(id->key->type) == KEY_RSA &&
- (datafellows & SSH_BUG_RSASIGMD5) != 0) {
- debug("Skipped %s key %s for RSA/MD5 server",
- key_type(id->key), id->filename);
- } else if (id->key->type != KEY_RSA1) {
- debug("Offering %s public key: %s",
- key_type(id->key), id->filename);
- sent = send_pubkey_test(authctxt, id);
+ if (try_identity(id)) {
+ ident = format_identity(id);
+ debug("Offering public key: %s", ident);
+ free(ident);
+ sent = send_pubkey_test(ssh, id);
}
} else {
debug("Trying private key: %s", id->filename);
- id->key = load_identity_file(id->filename,
- id->userprovided);
+ id->key = load_identity_file(id);
if (id->key != NULL) {
- id->isprivate = 1;
- if (key_type_plain(id->key->type) == KEY_RSA &&
- (datafellows & SSH_BUG_RSASIGMD5) != 0) {
- debug("Skipped %s key %s for RSA/MD5 "
- "server", key_type(id->key),
- id->filename);
- } else {
- sent = sign_and_send_pubkey(
- authctxt, id);
+ if (try_identity(id)) {
+ id->isprivate = 1;
+ sent = sign_and_send_pubkey(ssh, id);
}
- key_free(id->key);
+ sshkey_free(id->key);
id->key = NULL;
+ id->isprivate = 0;
}
}
if (sent)
@@ -1370,44 +1803,48 @@ userauth_pubkey(Authctxt *authctxt)
/*
* Send userauth request message specifying keyboard-interactive method.
*/
-int
-userauth_kbdint(Authctxt *authctxt)
+static int
+userauth_kbdint(struct ssh *ssh)
{
- static int attempt = 0;
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+ int r;
- if (attempt++ >= options.number_of_password_prompts)
+ if (authctxt->attempt_kbdint++ >= options.number_of_password_prompts)
return 0;
/* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */
- if (attempt > 1 && !authctxt->info_req_seen) {
+ if (authctxt->attempt_kbdint > 1 && !authctxt->info_req_seen) {
debug3("userauth_kbdint: disable: no info_req_seen");
- dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, NULL);
return 0;
}
debug2("userauth_kbdint");
- packet_start(SSH2_MSG_USERAUTH_REQUEST);
- packet_put_cstring(authctxt->server_user);
- packet_put_cstring(authctxt->service);
- packet_put_cstring(authctxt->method->name);
- packet_put_cstring(""); /* lang */
- packet_put_cstring(options.kbd_interactive_devices ?
- options.kbd_interactive_devices : "");
- packet_send();
-
- dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 || /* lang */
+ (r = sshpkt_put_cstring(ssh, options.kbd_interactive_devices ?
+ options.kbd_interactive_devices : "")) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
return 1;
}
/*
* parse INFO_REQUEST, prompt user and send INFO_RESPONSE
*/
-int
-input_userauth_info_req(int type, u_int32_t seq, void *ctxt)
+static int
+input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh)
{
- Authctxt *authctxt = ctxt;
- char *name, *inst, *lang, *prompt, *response;
+ Authctxt *authctxt = ssh->authctxt;
+ char *name = NULL, *inst = NULL, *lang = NULL, *prompt = NULL;
+ char *response = NULL;
+ u_char echo = 0;
u_int num_prompts, i;
- int echo = 0;
+ int r;
debug2("input_userauth_info_req");
@@ -1416,61 +1853,70 @@ input_userauth_info_req(int type, u_int32_t seq, void *ctxt)
authctxt->info_req_seen = 1;
- name = packet_get_string(NULL);
- inst = packet_get_string(NULL);
- lang = packet_get_string(NULL);
+ if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &inst, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0)
+ goto out;
if (strlen(name) > 0)
logit("%s", name);
if (strlen(inst) > 0)
logit("%s", inst);
- free(name);
- free(inst);
- free(lang);
- num_prompts = packet_get_int();
+ if ((r = sshpkt_get_u32(ssh, &num_prompts)) != 0)
+ goto out;
/*
* Begin to build info response packet based on prompts requested.
* We commit to providing the correct number of responses, so if
* further on we run into a problem that prevents this, we have to
* be sure and clean this up and send a correct error response.
*/
- packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
- packet_put_int(num_prompts);
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE)) != 0 ||
+ (r = sshpkt_put_u32(ssh, num_prompts)) != 0)
+ goto out;
debug2("input_userauth_info_req: num_prompts %d", num_prompts);
for (i = 0; i < num_prompts; i++) {
- prompt = packet_get_string(NULL);
- echo = packet_get_char();
-
+ 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);
-
- packet_put_cstring(response);
- explicit_bzero(response, strlen(response));
- free(response);
+ if ((r = sshpkt_put_cstring(ssh, response)) != 0)
+ goto out;
+ freezero(response, strlen(response));
free(prompt);
+ response = prompt = NULL;
}
- packet_check_eom(); /* done with parsing incoming message. */
-
- packet_add_padding(64);
- packet_send();
- return 0;
+ /* done with parsing incoming message. */
+ if ((r = sshpkt_get_end(ssh)) != 0 ||
+ (r = sshpkt_add_padding(ssh, 64)) != 0)
+ goto out;
+ r = sshpkt_send(ssh);
+ out:
+ if (response)
+ freezero(response, strlen(response));
+ free(prompt);
+ free(name);
+ free(inst);
+ free(lang);
+ return r;
}
static int
-ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp,
+ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen)
{
struct sshbuf *b;
struct stat st;
pid_t pid;
- int i, r, to[2], from[2], status, sock = packet_get_connection_in();
+ int r, to[2], from[2], status;
+ int sock = ssh_packet_get_connection_in(ssh);
u_char rversion = 0, version = 2;
void (*osigchld)(int);
*sigp = NULL;
*lenp = 0;
- if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) {
+ if (stat(_PATH_SSH_KEY_SIGN, &st) == -1) {
error("%s: not installed: %s", __func__, strerror(errno));
return -1;
}
@@ -1478,48 +1924,49 @@ ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp,
error("%s: fflush: %s", __func__, strerror(errno));
return -1;
}
- if (pipe(to) < 0) {
+ if (pipe(to) == -1) {
error("%s: pipe: %s", __func__, strerror(errno));
return -1;
}
- if (pipe(from) < 0) {
+ if (pipe(from) == -1) {
error("%s: pipe: %s", __func__, strerror(errno));
return -1;
}
- if ((pid = fork()) < 0) {
+ if ((pid = fork()) == -1) {
error("%s: fork: %s", __func__, strerror(errno));
return -1;
}
- osigchld = signal(SIGCHLD, SIG_DFL);
+ osigchld = ssh_signal(SIGCHLD, SIG_DFL);
if (pid == 0) {
- /* keep the socket on exec */
- fcntl(sock, F_SETFD, 0);
- permanently_drop_suid(getuid());
close(from[0]);
- if (dup2(from[1], STDOUT_FILENO) < 0)
+ if (dup2(from[1], STDOUT_FILENO) == -1)
fatal("%s: dup2: %s", __func__, strerror(errno));
close(to[1]);
- if (dup2(to[0], STDIN_FILENO) < 0)
+ if (dup2(to[0], STDIN_FILENO) == -1)
fatal("%s: dup2: %s", __func__, strerror(errno));
close(from[1]);
close(to[0]);
- /* Close everything but stdio and the socket */
- for (i = STDERR_FILENO + 1; i < sock; i++)
- close(i);
+
+ if (dup2(sock, STDERR_FILENO + 1) == -1)
+ fatal("%s: dup2: %s", __func__, 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);
- execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0);
+ execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *)NULL);
fatal("%s: exec(%s): %s", __func__, _PATH_SSH_KEY_SIGN,
strerror(errno));
}
close(from[1]);
close(to[0]);
+ sock = STDERR_FILENO + 1;
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
/* send # of sock, data to be signed */
- if ((r = sshbuf_put_u32(b, sock) != 0) ||
+ if ((r = sshbuf_put_u32(b, sock)) != 0 ||
(r = sshbuf_put_string(b, data, datalen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (ssh_msg_send(to[1], version, b) == -1)
@@ -1534,7 +1981,7 @@ ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp,
}
errno = 0;
- while (waitpid(pid, &status, 0) < 0) {
+ while (waitpid(pid, &status, 0) == -1) {
if (errno != EINTR) {
error("%s: waitpid %ld: %s",
__func__, (long)pid, strerror(errno));
@@ -1561,23 +2008,22 @@ ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp,
if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) {
error("%s: buffer error: %s", __func__, ssh_err(r));
fail:
- signal(SIGCHLD, osigchld);
+ ssh_signal(SIGCHLD, osigchld);
sshbuf_free(b);
return -1;
}
- signal(SIGCHLD, osigchld);
+ ssh_signal(SIGCHLD, osigchld);
sshbuf_free(b);
return 0;
}
-int
-userauth_hostbased(Authctxt *authctxt)
+static int
+userauth_hostbased(struct ssh *ssh)
{
- struct ssh *ssh = active_state;
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
struct sshkey *private = NULL;
struct sshbuf *b = NULL;
- const char *service;
u_char *sig = NULL, *keyblob = NULL;
char *fp = NULL, *chost = NULL, *lname = NULL;
size_t siglen = 0, keylen = 0;
@@ -1605,13 +2051,11 @@ userauth_hostbased(Authctxt *authctxt)
private = NULL;
for (i = 0; i < authctxt->sensitive->nkeys; i++) {
if (authctxt->sensitive->keys[i] == NULL ||
- authctxt->sensitive->keys[i]->type == KEY_RSA1 ||
authctxt->sensitive->keys[i]->type == KEY_UNSPEC)
continue;
if (match_pattern_list(
sshkey_ssh_name(authctxt->sensitive->keys[i]),
- authctxt->active_ktype,
- strlen(authctxt->active_ktype), 0) != 1)
+ authctxt->active_ktype, 0) != 1)
continue;
/* we take and free the key */
private = authctxt->sensitive->keys[i];
@@ -1641,7 +2085,8 @@ userauth_hostbased(Authctxt *authctxt)
__func__, sshkey_ssh_name(private), fp);
/* figure out a name for the client host */
- if ((lname = get_local_name(packet_get_connection_in())) == NULL) {
+ lname = get_local_name(ssh_packet_get_connection_in(ssh));
+ if (lname == NULL) {
error("%s: cannot get local ipaddr/name", __func__);
goto out;
}
@@ -1650,9 +2095,6 @@ userauth_hostbased(Authctxt *authctxt)
xasprintf(&chost, "%s.", lname);
debug2("%s: chost %s", __func__, chost);
- service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
- authctxt->service;
-
/* construct data */
if ((b = sshbuf_new()) == NULL) {
error("%s: sshbuf_new failed", __func__);
@@ -1665,9 +2107,9 @@ userauth_hostbased(Authctxt *authctxt)
if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 ||
(r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 ||
- (r = sshbuf_put_cstring(b, service)) != 0 ||
+ (r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 ||
- (r = sshbuf_put_cstring(b, key_ssh_name(private))) != 0 ||
+ (r = sshbuf_put_cstring(b, sshkey_ssh_name(private))) != 0 ||
(r = sshbuf_put_string(b, keyblob, keylen)) != 0 ||
(r = sshbuf_put_cstring(b, chost)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) {
@@ -1678,13 +2120,8 @@ userauth_hostbased(Authctxt *authctxt)
#ifdef DEBUG_PK
sshbuf_dump(b, stderr);
#endif
- if (authctxt->sensitive->external_keysign)
- r = ssh_keysign(private, &sig, &siglen,
- sshbuf_ptr(b), sshbuf_len(b));
- else if ((r = sshkey_sign(private, &sig, &siglen,
- sshbuf_ptr(b), sshbuf_len(b), datafellows)) != 0)
- debug("%s: sshkey_sign: %s", __func__, ssh_err(r));
- if (r != 0) {
+ if ((r = ssh_keysign(ssh, private, &sig, &siglen,
+ sshbuf_ptr(b), sshbuf_len(b))) != 0) {
error("sign using hostkey %s %s failed",
sshkey_ssh_name(private), fp);
goto out;
@@ -1693,7 +2130,7 @@ userauth_hostbased(Authctxt *authctxt)
(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, key_ssh_name(private))) != 0 ||
+ (r = sshpkt_put_cstring(ssh, sshkey_ssh_name(private))) != 0 ||
(r = sshpkt_put_string(ssh, keyblob, keylen)) != 0 ||
(r = sshpkt_put_cstring(ssh, chost)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 ||
@@ -1705,10 +2142,8 @@ userauth_hostbased(Authctxt *authctxt)
success = 1;
out:
- if (sig != NULL) {
- explicit_bzero(sig, siglen);
- free(sig);
- }
+ if (sig != NULL)
+ freezero(sig, siglen);
free(keyblob);
free(lname);
free(fp);
@@ -1805,20 +2240,22 @@ static char *
authmethods_get(void)
{
Authmethod *method = NULL;
- Buffer b;
+ struct sshbuf *b;
char *list;
+ int r;
- buffer_init(&b);
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
for (method = authmethods; method->name != NULL; method++) {
if (authmethod_is_enabled(method)) {
- if (buffer_len(&b) > 0)
- buffer_append(&b, ",", 1);
- buffer_append(&b, method->name, strlen(method->name));
+ if ((r = sshbuf_putf(b, "%s%s",
+ sshbuf_len(b) ? "," : "", method->name)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
}
}
- buffer_append(&b, "\0", 1);
- list = xstrdup(buffer_ptr(&b));
- buffer_free(&b);
+ if ((list = sshbuf_dup_string(b)) == NULL)
+ fatal("%s: sshbuf_dup_string failed", __func__);
+ sshbuf_free(b);
return list;
}
-
diff --git a/sshd.0 b/sshd.0
deleted file mode 100644
index 442cd572..00000000
--- a/sshd.0
+++ /dev/null
@@ -1,634 +0,0 @@
-SSHD(8) System Manager's Manual SSHD(8)
-
-NAME
- sshd M-bM-^@M-^S OpenSSH SSH daemon
-
-SYNOPSIS
- sshd [-46DdeiqTt] [-b bits] [-C connection_spec]
- [-c host_certificate_file] [-E log_file] [-f config_file]
- [-g login_grace_time] [-h host_key_file] [-k key_gen_time]
- [-o option] [-p port] [-u len]
-
-DESCRIPTION
- sshd (OpenSSH Daemon) is the daemon program for ssh(1). Together these
- programs replace rlogin and rsh, and provide secure encrypted
- communications between two untrusted hosts over an insecure network.
-
- sshd listens for connections from clients. It is normally started at
- boot from /etc/rc. It forks a new daemon for each incoming connection.
- The forked daemons handle key exchange, encryption, authentication,
- command execution, and data exchange.
-
- sshd can be configured using command-line options or a configuration file
- (by default sshd_config(5)); command-line options override values
- specified in the configuration file. sshd rereads its configuration file
- when it receives a hangup signal, SIGHUP, by executing itself with the
- name and options it was started with, e.g. /usr/sbin/sshd.
-
- The options are as follows:
-
- -4 Forces sshd to use IPv4 addresses only.
-
- -6 Forces sshd to use IPv6 addresses only.
-
- -b bits
- Specifies the number of bits in the ephemeral protocol version 1
- server key (default 1024).
-
- -C connection_spec
- Specify the connection parameters to use for the -T extended test
- mode. If provided, any Match directives in the configuration
- file that would apply to the specified user, host, and address
- will be set before the configuration is written to standard
- output. The connection parameters are supplied as keyword=value
- pairs. The keywords are M-bM-^@M-^\userM-bM-^@M-^], M-bM-^@M-^\hostM-bM-^@M-^], M-bM-^@M-^\laddrM-bM-^@M-^], M-bM-^@M-^\lportM-bM-^@M-^], and
- M-bM-^@M-^\addrM-bM-^@M-^]. All are required and may be supplied in any order,
- either with multiple -C options or as a comma-separated list.
-
- -c host_certificate_file
- Specifies a path to a certificate file to identify sshd during
- key exchange. The certificate file must match a host key file
- specified using the -h option or the HostKey configuration
- directive.
-
- -D When this option is specified, sshd will not detach and does not
- become a daemon. This allows easy monitoring of sshd.
-
- -d Debug mode. The server sends verbose debug output to standard
- error, and does not put itself in the background. The server
- also will not fork and will only process one connection. This
- option is only intended for debugging for the server. Multiple
- -d options increase the debugging level. Maximum is 3.
-
- -E log_file
- Append debug logs to log_file instead of the system log.
-
- -e Write debug logs to standard error instead of the system log.
-
- -f config_file
- Specifies the name of the configuration file. The default is
- /etc/ssh/sshd_config. sshd refuses to start if there is no
- configuration file.
-
- -g login_grace_time
- Gives the grace time for clients to authenticate themselves
- (default 120 seconds). If the client fails to authenticate the
- user within this many seconds, the server disconnects and exits.
- A value of zero indicates no limit.
-
- -h host_key_file
- Specifies a file from which a host key is read. This option must
- be given if sshd is not run as root (as the normal host key files
- are normally not readable by anyone but root). The default is
- /etc/ssh/ssh_host_key for protocol version 1, and
- /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_ecdsa_key.
- /etc/ssh/ssh_host_ed25519_key and /etc/ssh/ssh_host_rsa_key for
- protocol version 2. It is possible to have multiple host key
- files for the different protocol versions and host key
- algorithms.
-
- -i Specifies that sshd is being run from inetd(8). sshd is normally
- not run from inetd because it needs to generate the server key
- before it can respond to the client, and this may take tens of
- seconds. Clients would have to wait too long if the key was
- regenerated every time. However, with small key sizes (e.g. 512)
- using sshd from inetd may be feasible.
-
- -k key_gen_time
- Specifies how often the ephemeral protocol version 1 server key
- is regenerated (default 3600 seconds, or one hour). The
- motivation for regenerating the key fairly often is that the key
- is not stored anywhere, and after about an hour it becomes
- impossible to recover the key for decrypting intercepted
- communications even if the machine is cracked into or physically
- seized. A value of zero indicates that the key will never be
- regenerated.
-
- -o option
- Can be used to give options in the format used in the
- configuration file. This is useful for specifying options for
- which there is no separate command-line flag. For full details
- of the options, and their values, see sshd_config(5).
-
- -p port
- Specifies the port on which the server listens for connections
- (default 22). Multiple port options are permitted. Ports
- specified in the configuration file with the Port option are
- ignored when a command-line port is specified. Ports specified
- using the ListenAddress option override command-line ports.
-
- -q Quiet mode. Nothing is sent to the system log. Normally the
- beginning, authentication, and termination of each connection is
- logged.
-
- -T Extended test mode. Check the validity of the configuration
- file, output the effective configuration to stdout and then exit.
- Optionally, Match rules may be applied by specifying the
- connection parameters using one or more -C options.
-
- -t Test mode. Only check the validity of the configuration file and
- sanity of the keys. This is useful for updating sshd reliably as
- configuration options may change.
-
- -u len This option is used to specify the size of the field in the utmp
- structure that holds the remote host name. If the resolved host
- name is longer than len, the dotted decimal value will be used
- instead. This allows hosts with very long host names that
- overflow this field to still be uniquely identified. Specifying
- -u0 indicates that only dotted decimal addresses should be put
- into the utmp file. -u0 may also be used to prevent sshd from
- making DNS requests unless the authentication mechanism or
- configuration requires it. Authentication mechanisms that may
- require DNS include RhostsRSAAuthentication,
- HostbasedAuthentication, and using a from="pattern-list" option
- in a key file. Configuration options that require DNS include
- using a USER@HOST pattern in AllowUsers or DenyUsers.
-
-AUTHENTICATION
- The OpenSSH SSH daemon supports SSH protocols 1 and 2. The default is to
- use protocol 2 only, though this can be changed via the Protocol option
- in sshd_config(5). Protocol 2 supports DSA, ECDSA, Ed25519 and RSA keys;
- protocol 1 only supports RSA keys. For both protocols, each host has a
- host-specific key, normally 2048 bits, used to identify the host.
-
- Forward security for protocol 1 is provided through an additional server
- key, normally 768 bits, generated when the server starts. This key is
- normally regenerated every hour if it has been used, and is never stored
- on disk. Whenever a client connects, the daemon responds with its public
- host and server keys. The client compares the RSA host key against its
- own database to verify that it has not changed. The client then
- generates a 256-bit random number. It encrypts this random number using
- both the host key and the server key, and sends the encrypted number to
- the server. Both sides then use this random number as a session key
- which is used to encrypt all further communications in the session. The
- rest of the session is encrypted using a conventional cipher, currently
- Blowfish or 3DES, with 3DES being used by default. The client selects
- the encryption algorithm to use from those offered by the server.
-
- For protocol 2, forward security is provided through a Diffie-Hellman key
- agreement. This key agreement results in a shared session key. The rest
- of the session is encrypted using a symmetric cipher, currently 128-bit
- AES, Blowfish, 3DES, CAST128, Arcfour, 192-bit AES, or 256-bit AES. The
- client selects the encryption algorithm to use from those offered by the
- server. Additionally, session integrity is provided through a
- cryptographic message authentication code (hmac-md5, hmac-sha1, umac-64,
- umac-128, hmac-ripemd160, hmac-sha2-256 or hmac-sha2-512).
-
- Finally, the server and the client enter an authentication dialog. The
- client tries to authenticate itself using host-based authentication,
- public key authentication, challenge-response authentication, or password
- authentication.
-
- Regardless of the authentication type, the account is checked to ensure
- that it is accessible. An account is not accessible if it is locked,
- listed in DenyUsers or its group is listed in DenyGroups . The
- definition of a locked account is system dependant. Some platforms have
- their own account database (eg AIX) and some modify the passwd field (
- M-bM-^@M-^X*LK*M-bM-^@M-^Y on Solaris and UnixWare, M-bM-^@M-^X*M-bM-^@M-^Y on HP-UX, containing M-bM-^@M-^XNologinM-bM-^@M-^Y on
- Tru64, a leading M-bM-^@M-^X*LOCKED*M-bM-^@M-^Y on FreeBSD and a leading M-bM-^@M-^X!M-bM-^@M-^Y on most
- Linuxes). If there is a requirement to disable password authentication
- for the account while allowing still public-key, then the passwd field
- should be set to something other than these values (eg M-bM-^@M-^XNPM-bM-^@M-^Y or M-bM-^@M-^X*NP*M-bM-^@M-^Y ).
-
- If the client successfully authenticates itself, a dialog for preparing
- the session is entered. At this time the client may request things like
- allocating a pseudo-tty, forwarding X11 connections, forwarding TCP
- connections, or forwarding the authentication agent connection over the
- secure channel.
-
- After this, the client either requests a shell or execution of a command.
- The sides then enter session mode. In this mode, either side may send
- data at any time, and such data is forwarded to/from the shell or command
- on the server side, and the user terminal in the client side.
-
- When the user program terminates and all forwarded X11 and other
- connections have been closed, the server sends command exit status to the
- client, and both sides exit.
-
-LOGIN PROCESS
- When a user successfully logs in, sshd does the following:
-
- 1. If the login is on a tty, and no command has been specified,
- prints last login time and /etc/motd (unless prevented in the
- configuration file or by ~/.hushlogin; see the FILES section).
-
- 2. If the login is on a tty, records login time.
-
- 3. Checks /etc/nologin; if it exists, prints contents and quits
- (unless root).
-
- 4. Changes to run with normal user privileges.
-
- 5. Sets up basic environment.
-
- 6. Reads the file ~/.ssh/environment, if it exists, and users are
- allowed to change their environment. See the
- PermitUserEnvironment option in sshd_config(5).
-
- 7. Changes to user's home directory.
-
- 8. If ~/.ssh/rc exists and the sshd_config(5) PermitUserRC option
- is set, runs it; else if /etc/ssh/sshrc exists, runs it;
- otherwise runs xauth. The M-bM-^@M-^\rcM-bM-^@M-^] files are given the X11
- authentication protocol and cookie in standard input. See
- SSHRC, below.
-
- 9. Runs user's shell or command.
-
-SSHRC
- If the file ~/.ssh/rc exists, sh(1) runs it after reading the environment
- files but before starting the user's shell or command. It must not
- produce any output on stdout; stderr must be used instead. If X11
- forwarding is in use, it will receive the "proto cookie" pair in its
- standard input (and DISPLAY in its environment). The script must call
- xauth(1) because sshd will not run xauth automatically to add X11
- cookies.
-
- The primary purpose of this file is to run any initialization routines
- which may be needed before the user's home directory becomes accessible;
- AFS is a particular example of such an environment.
-
- This file will probably contain some initialization code followed by
- something similar to:
-
- if read proto cookie && [ -n "$DISPLAY" ]; then
- if [ `echo $DISPLAY | cut -c1-10` = 'localhost:' ]; then
- # X11UseLocalhost=yes
- echo add unix:`echo $DISPLAY |
- cut -c11-` $proto $cookie
- else
- # X11UseLocalhost=no
- echo add $DISPLAY $proto $cookie
- fi | xauth -q -
- fi
-
- If this file does not exist, /etc/ssh/sshrc is run, and if that does not
- exist either, xauth is used to add the cookie.
-
-AUTHORIZED_KEYS FILE FORMAT
- AuthorizedKeysFile specifies the files containing public keys for public
- key authentication; if none is specified, the default is
- ~/.ssh/authorized_keys and ~/.ssh/authorized_keys2. Each line of the
- file contains one key (empty lines and lines starting with a M-bM-^@M-^X#M-bM-^@M-^Y are
- ignored as comments). Protocol 1 public keys consist of the following
- space-separated fields: options, bits, exponent, modulus, comment.
- Protocol 2 public key consist of: options, keytype, base64-encoded key,
- comment. The options field is optional; its presence is determined by
- whether the line starts with a number or not (the options field never
- starts with a number). The bits, exponent, modulus, and comment fields
- give the RSA key for protocol version 1; the comment field is not used
- for anything (but may be convenient for the user to identify the key).
- For protocol version 2 the keytype is M-bM-^@M-^\ecdsa-sha2-nistp256M-bM-^@M-^],
- M-bM-^@M-^\ecdsa-sha2-nistp384M-bM-^@M-^], M-bM-^@M-^\ecdsa-sha2-nistp521M-bM-^@M-^], M-bM-^@M-^\ssh-ed25519M-bM-^@M-^], M-bM-^@M-^\ssh-dssM-bM-^@M-^] or
- M-bM-^@M-^\ssh-rsaM-bM-^@M-^].
-
- Note that lines in this file are usually several hundred bytes long
- (because of the size of the public key encoding) up to a limit of 8
- kilobytes, which permits DSA keys up to 8 kilobits and RSA keys up to 16
- kilobits. You don't want to type them in; instead, copy the
- identity.pub, id_dsa.pub, id_ecdsa.pub, id_ed25519.pub, or the id_rsa.pub
- file and edit it.
-
- sshd enforces a minimum RSA key modulus size for protocol 1 and protocol
- 2 keys of 768 bits.
-
- The options (if present) consist of comma-separated option
- specifications. No spaces are permitted, except within double quotes.
- The following option specifications are supported (note that option
- keywords are case-insensitive):
-
- cert-authority
- Specifies that the listed key is a certification authority (CA)
- that is trusted to validate signed certificates for user
- authentication.
-
- Certificates may encode access restrictions similar to these key
- options. If both certificate restrictions and key options are
- present, the most restrictive union of the two is applied.
-
- command="command"
- Specifies that the command is executed whenever this key is used
- for authentication. The command supplied by the user (if any) is
- ignored. The command is run on a pty if the client requests a
- pty; otherwise it is run without a tty. If an 8-bit clean
- channel is required, one must not request a pty or should specify
- no-pty. A quote may be included in the command by quoting it
- with a backslash. This option might be useful to restrict
- certain public keys to perform just a specific operation. An
- example might be a key that permits remote backups but nothing
- else. Note that the client may specify TCP and/or X11 forwarding
- unless they are explicitly prohibited. The command originally
- supplied by the client is available in the SSH_ORIGINAL_COMMAND
- environment variable. Note that this option applies to shell,
- command or subsystem execution. Also note that this command may
- be superseded by either a sshd_config(5) ForceCommand directive
- or a command embedded in a certificate.
-
- environment="NAME=value"
- Specifies that the string is to be added to the environment when
- logging in using this key. Environment variables set this way
- override other default environment values. Multiple options of
- this type are permitted. Environment processing is disabled by
- default and is controlled via the PermitUserEnvironment option.
- This option is automatically disabled if UseLogin is enabled.
-
- from="pattern-list"
- Specifies that in addition to public key authentication, either
- the canonical name of the remote host or its IP address must be
- present in the comma-separated list of patterns. See PATTERNS in
- ssh_config(5) for more information on patterns.
-
- In addition to the wildcard matching that may be applied to
- hostnames or addresses, a from stanza may match IP addresses
- using CIDR address/masklen notation.
-
- The purpose of this option is to optionally increase security:
- public key authentication by itself does not trust the network or
- name servers or anything (but the key); however, if somebody
- somehow steals the key, the key permits an intruder to log in
- from anywhere in the world. This additional option makes using a
- stolen key more difficult (name servers and/or routers would have
- to be compromised in addition to just the key).
-
- no-agent-forwarding
- Forbids authentication agent forwarding when this key is used for
- authentication.
-
- no-port-forwarding
- Forbids TCP forwarding when this key is used for authentication.
- Any port forward requests by the client will return an error.
- This might be used, e.g. in connection with the command option.
-
- no-pty Prevents tty allocation (a request to allocate a pty will fail).
-
- no-user-rc
- Disables execution of ~/.ssh/rc.
-
- no-X11-forwarding
- Forbids X11 forwarding when this key is used for authentication.
- Any X11 forward requests by the client will return an error.
-
- permitopen="host:port"
- Limit local port forwarding with ssh(1) -L such that it may only
- connect to the specified host and port. IPv6 addresses can be
- specified by enclosing the address in square brackets. Multiple
- permitopen options may be applied separated by commas. No
- pattern matching is performed on the specified hostnames, they
- must be literal domains or addresses. A port specification of *
- matches any port.
-
- principals="principals"
- On a cert-authority line, specifies allowed principals for
- certificate authentication as a comma-separated list. At least
- one name from the list must appear in the certificate's list of
- principals for the certificate to be accepted. This option is
- ignored for keys that are not marked as trusted certificate
- signers using the cert-authority option.
-
- tunnel="n"
- Force a tun(4) device on the server. Without this option, the
- next available device will be used if the client requests a
- tunnel.
-
- An example authorized_keys file:
-
- # Comments allowed at start of line
- ssh-rsa AAAAB3Nza...LiPk== user@example.net
- from="*.sales.example.net,!pc.sales.example.net" ssh-rsa
- AAAAB2...19Q== john@example.net
- command="dump /home",no-pty,no-port-forwarding ssh-dss
- AAAAC3...51R== example.net
- permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-dss
- AAAAB5...21S==
- tunnel="0",command="sh /etc/netstart tun0" ssh-rsa AAAA...==
- jane@example.net
-
-SSH_KNOWN_HOSTS FILE FORMAT
- The /etc/ssh/ssh_known_hosts and ~/.ssh/known_hosts files contain host
- public keys for all known hosts. The global file should be prepared by
- the administrator (optional), and the per-user file is maintained
- automatically: whenever the user connects from an unknown host, its key
- is added to the per-user file.
-
- Each line in these files contains the following fields: markers
- (optional), hostnames, bits, exponent, modulus, comment. The fields are
- separated by spaces.
-
- The marker is optional, but if it is present then it must be one of
- M-bM-^@M-^\@cert-authorityM-bM-^@M-^], to indicate that the line contains a certification
- authority (CA) key, or M-bM-^@M-^\@revokedM-bM-^@M-^], to indicate that the key contained on
- the line is revoked and must not ever be accepted. Only one marker
- should be used on a key line.
-
- Hostnames is a comma-separated list of patterns (M-bM-^@M-^X*M-bM-^@M-^Y and M-bM-^@M-^X?M-bM-^@M-^Y act as
- wildcards); each pattern in turn is matched against the canonical host
- name (when authenticating a client) or against the user-supplied name
- (when authenticating a server). A pattern may also be preceded by M-bM-^@M-^X!M-bM-^@M-^Y to
- indicate negation: if the host name matches a negated pattern, it is not
- accepted (by that line) even if it matched another pattern on the line.
- A hostname or address may optionally be enclosed within M-bM-^@M-^X[M-bM-^@M-^Y and M-bM-^@M-^X]M-bM-^@M-^Y
- brackets then followed by M-bM-^@M-^X:M-bM-^@M-^Y and a non-standard port number.
-
- Alternately, hostnames may be stored in a hashed form which hides host
- names and addresses should the file's contents be disclosed. Hashed
- hostnames start with a M-bM-^@M-^X|M-bM-^@M-^Y character. Only one hashed hostname may
- appear on a single line and none of the above negation or wildcard
- operators may be applied.
-
- Bits, exponent, and modulus are taken directly from the RSA host key;
- they can be obtained, for example, from /etc/ssh/ssh_host_key.pub. The
- optional comment field continues to the end of the line, and is not used.
-
- Lines starting with M-bM-^@M-^X#M-bM-^@M-^Y and empty lines are ignored as comments.
-
- When performing host authentication, authentication is accepted if any
- matching line has the proper key; either one that matches exactly or, if
- the server has presented a certificate for authentication, the key of the
- certification authority that signed the certificate. For a key to be
- trusted as a certification authority, it must use the M-bM-^@M-^\@cert-authorityM-bM-^@M-^]
- marker described above.
-
- The known hosts file also provides a facility to mark keys as revoked,
- for example when it is known that the associated private key has been
- stolen. Revoked keys are specified by including the M-bM-^@M-^\@revokedM-bM-^@M-^] marker at
- the beginning of the key line, and are never accepted for authentication
- or as certification authorities, but instead will produce a warning from
- ssh(1) when they are encountered.
-
- It is permissible (but not recommended) to have several lines or
- different host keys for the same names. This will inevitably happen when
- short forms of host names from different domains are put in the file. It
- is possible that the files contain conflicting information;
- authentication is accepted if valid information can be found from either
- file.
-
- Note that the lines in these files are typically hundreds of characters
- long, and you definitely don't want to type in the host keys by hand.
- Rather, generate them by a script, ssh-keyscan(1) or by taking
- /etc/ssh/ssh_host_key.pub and adding the host names at the front.
- ssh-keygen(1) also offers some basic automated editing for
- ~/.ssh/known_hosts including removing hosts matching a host name and
- converting all host names to their hashed representations.
-
- An example ssh_known_hosts file:
-
- # Comments allowed at start of line
- closenet,...,192.0.2.53 1024 37 159...93 closenet.example.net
- cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....=
- # A hashed hostname
- |1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsa
- AAAA1234.....=
- # A revoked key
- @revoked * ssh-rsa AAAAB5W...
- # A CA key, accepted for any host in *.mydomain.com or *.mydomain.org
- @cert-authority *.mydomain.org,*.mydomain.com ssh-rsa AAAAB5W...
-
-FILES
- ~/.hushlogin
- This file is used to suppress printing the last login time and
- /etc/motd, if PrintLastLog and PrintMotd, respectively, are
- enabled. It does not suppress printing of the banner specified
- by Banner.
-
- ~/.rhosts
- This file is used for host-based authentication (see ssh(1) for
- more information). On some machines this file may need to be
- world-readable if the user's home directory is on an NFS
- partition, because sshd reads it as root. Additionally, this
- file must be owned by the user, and must not have write
- permissions for anyone else. The recommended permission for most
- machines is read/write for the user, and not accessible by
- others.
-
- ~/.shosts
- This file is used in exactly the same way as .rhosts, but allows
- host-based authentication without permitting login with
- rlogin/rsh.
-
- ~/.ssh/
- This directory is the default location for all user-specific
- configuration and authentication information. There is no
- general requirement to keep the entire contents of this directory
- secret, but the recommended permissions are read/write/execute
- for the user, and not accessible by others.
-
- ~/.ssh/authorized_keys
- Lists the public keys (DSA, ECDSA, Ed25519, RSA) that can be used
- for logging in as this user. The format of this file is
- described above. The content of the file is not highly
- sensitive, but the recommended permissions are read/write for the
- user, and not accessible by others.
-
- If this file, the ~/.ssh directory, or the user's home directory
- are writable by other users, then the file could be modified or
- replaced by unauthorized users. In this case, sshd will not
- allow it to be used unless the StrictModes option has been set to
- M-bM-^@M-^\noM-bM-^@M-^].
-
- ~/.ssh/environment
- This file is read into the environment at login (if it exists).
- It can only contain empty lines, comment lines (that start with
- M-bM-^@M-^X#M-bM-^@M-^Y), and assignment lines of the form name=value. The file
- should be writable only by the user; it need not be readable by
- anyone else. Environment processing is disabled by default and
- is controlled via the PermitUserEnvironment option.
-
- ~/.ssh/known_hosts
- Contains a list of host keys for all hosts the user has logged
- into that are not already in the systemwide list of known host
- keys. The format of this file is described above. This file
- should be writable only by root/the owner and can, but need not
- be, world-readable.
-
- ~/.ssh/rc
- Contains initialization routines to be run before the user's home
- directory becomes accessible. This file should be writable only
- by the user, and need not be readable by anyone else.
-
- /etc/hosts.equiv
- This file is for host-based authentication (see ssh(1)). It
- should only be writable by root.
-
- /etc/moduli
- Contains Diffie-Hellman groups used for the "Diffie-Hellman Group
- Exchange". The file format is described in moduli(5).
-
- /etc/motd
- See motd(5).
-
- /etc/nologin
- If this file exists, sshd refuses to let anyone except root log
- in. The contents of the file are displayed to anyone trying to
- log in, and non-root connections are refused. The file should be
- world-readable.
-
- /etc/shosts.equiv
- This file is used in exactly the same way as hosts.equiv, but
- allows host-based authentication without permitting login with
- rlogin/rsh.
-
- /etc/ssh/ssh_host_key
- /etc/ssh/ssh_host_dsa_key
- /etc/ssh/ssh_host_ecdsa_key
- /etc/ssh/ssh_host_ed25519_key
- /etc/ssh/ssh_host_rsa_key
- These files contain the private parts of the host keys. These
- files should only be owned by root, readable only by root, and
- not accessible to others. Note that sshd does not start if these
- files are group/world-accessible.
-
- /etc/ssh/ssh_host_key.pub
- /etc/ssh/ssh_host_dsa_key.pub
- /etc/ssh/ssh_host_ecdsa_key.pub
- /etc/ssh/ssh_host_ed25519_key.pub
- /etc/ssh/ssh_host_rsa_key.pub
- These files contain the public parts of the host keys. These
- files should be world-readable but writable only by root. Their
- contents should match the respective private parts. These files
- are not really used for anything; they are provided for the
- convenience of the user so their contents can be copied to known
- hosts files. These files are created using ssh-keygen(1).
-
- /etc/ssh/ssh_known_hosts
- Systemwide list of known host keys. This file should be prepared
- by the system administrator to contain the public host keys of
- all machines in the organization. The format of this file is
- described above. This file should be writable only by root/the
- owner and should be world-readable.
-
- /etc/ssh/sshd_config
- Contains configuration data for sshd. The file format and
- configuration options are described in sshd_config(5).
-
- /etc/ssh/sshrc
- Similar to ~/.ssh/rc, it can be used to specify machine-specific
- login-time initializations globally. This file should be
- writable only by root, and should be world-readable.
-
- /var/empty
- chroot(2) directory used by sshd during privilege separation in
- the pre-authentication phase. The directory should not contain
- any files and must be owned by root and not group or world-
- writable.
-
- /var/run/sshd.pid
- Contains the process ID of the sshd listening for connections (if
- there are several daemons running concurrently for different
- ports, this contains the process ID of the one started last).
- The content of this file is not sensitive; it can be world-
- readable.
-
-SEE ALSO
- scp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1),
- ssh-keyscan(1), chroot(2), login.conf(5), moduli(5), sshd_config(5),
- inetd(8), sftp-server(8)
-
-AUTHORS
- OpenSSH is a derivative of the original and free ssh 1.2.12 release by
- Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
- de Raadt and Dug Song removed many bugs, re-added newer features and
- created OpenSSH. Markus Friedl contributed the support for SSH protocol
- versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support
- for privilege separation.
-
-OpenBSD 5.7 November 15, 2014 OpenBSD 5.7
diff --git a/sshd.8 b/sshd.8
index 3c53f7cd..c5f8987d 100644
--- a/sshd.8
+++ b/sshd.8
@@ -33,25 +33,23 @@
.\" (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.278 2014/11/15 14:41:03 bentley Exp $
-.Dd $Mdocdate: November 15 2014 $
+.\" $OpenBSD: sshd.8,v 1.312 2020/01/25 06:03:10 djm Exp $
+.Dd $Mdocdate: January 25 2020 $
.Dt SSHD 8
.Os
.Sh NAME
.Nm sshd
-.Nd OpenSSH SSH daemon
+.Nd OpenSSH daemon
.Sh SYNOPSIS
.Nm sshd
.Bk -words
.Op Fl 46DdeiqTt
-.Op Fl b Ar bits
.Op Fl C Ar connection_spec
.Op Fl c Ar host_certificate_file
.Op Fl E Ar log_file
.Op Fl f Ar config_file
.Op Fl g Ar login_grace_time
.Op Fl h Ar host_key_file
-.Op Fl k Ar key_gen_time
.Op Fl o Ar option
.Op Fl p Ar port
.Op Fl u Ar len
@@ -96,29 +94,28 @@ to use IPv4 addresses only.
Forces
.Nm
to use IPv6 addresses only.
-.It Fl b Ar bits
-Specifies the number of bits in the ephemeral protocol version 1
-server key (default 1024).
.It Fl C Ar connection_spec
Specify the connection parameters to use for the
.Fl T
extended test mode.
If provided, any
.Cm Match
-directives in the configuration file
-that would apply to the specified user, host, and address will be set before
-the configuration is written to standard output.
-The connection parameters are supplied as keyword=value pairs.
+directives in the configuration file that would apply are applied before the
+configuration is written to standard output.
+The connection parameters are supplied as keyword=value pairs and may be
+supplied in any order, either with multiple
+.Fl C
+options or as a comma-separated list.
The keywords are
+.Dq addr,
.Dq user ,
.Dq host ,
.Dq laddr ,
.Dq lport ,
and
-.Dq addr .
-All are required and may be supplied in any order, either with multiple
-.Fl C
-options or as a comma-separated list.
+.Dq rdomain
+and correspond to source address, user, resolved source host name,
+local address, local port number and routing domain respectively.
.It Fl c Ar host_certificate_file
Specifies a path to a certificate file to identify
.Nm
@@ -169,39 +166,17 @@ This option must be given if
is not run as root (as the normal
host key files are normally not readable by anyone but root).
The default is
-.Pa /etc/ssh/ssh_host_key
-for protocol version 1, and
-.Pa /etc/ssh/ssh_host_dsa_key ,
-.Pa /etc/ssh/ssh_host_ecdsa_key .
+.Pa /etc/ssh/ssh_host_ecdsa_key ,
.Pa /etc/ssh/ssh_host_ed25519_key
and
-.Pa /etc/ssh/ssh_host_rsa_key
-for protocol version 2.
+.Pa /etc/ssh/ssh_host_rsa_key .
It is possible to have multiple host key files for
-the different protocol versions and host key algorithms.
+the different host key algorithms.
.It Fl i
Specifies that
.Nm
is being run from
.Xr inetd 8 .
-.Nm
-is normally not run
-from inetd because it needs to generate the server key before it can
-respond to the client, and this may take tens of seconds.
-Clients would have to wait too long if the key was regenerated every time.
-However, with small key sizes (e.g. 512) using
-.Nm
-from inetd may
-be feasible.
-.It Fl k Ar key_gen_time
-Specifies how often the ephemeral protocol version 1 server key is
-regenerated (default 3600 seconds, or one hour).
-The motivation for regenerating the key fairly
-often is that the key is not stored anywhere, and after about an hour
-it becomes impossible to recover the key for decrypting intercepted
-communications even if the machine is cracked into or physically
-seized.
-A value of zero indicates that the key will never be regenerated.
.It Fl o Ar option
Can be used to give options in the format used in the configuration file.
This is useful for specifying options for which there is no separate
@@ -260,8 +235,7 @@ may also be used to prevent
from making DNS requests unless the authentication
mechanism or configuration requires it.
Authentication mechanisms that may require DNS include
-.Cm RhostsRSAAuthentication ,
-.Cm HostbasedAuthentication ,
+.Cm HostbasedAuthentication
and using a
.Cm from="pattern-list"
option in a key file.
@@ -272,53 +246,20 @@ or
.Cm DenyUsers .
.El
.Sh AUTHENTICATION
-The OpenSSH SSH daemon supports SSH protocols 1 and 2.
-The default is to use protocol 2 only,
-though this can be changed via the
-.Cm Protocol
-option in
-.Xr sshd_config 5 .
-Protocol 2 supports DSA, ECDSA, Ed25519 and RSA keys;
-protocol 1 only supports RSA keys.
-For both protocols,
-each host has a host-specific key,
-normally 2048 bits,
+The OpenSSH SSH daemon supports SSH protocol 2 only.
+Each host has a host-specific key,
used to identify the host.
-.Pp
-Forward security for protocol 1 is provided through
-an additional server key,
-normally 768 bits,
-generated when the server starts.
-This key is normally regenerated every hour if it has been used, and
-is never stored on disk.
Whenever a client connects, the daemon responds with its public
-host and server keys.
+host key.
The client compares the
-RSA host key against its own database to verify that it has not changed.
-The client then generates a 256-bit random number.
-It encrypts this
-random number using both the host key and the server key, and sends
-the encrypted number to the server.
-Both sides then use this
-random number as a session key which is used to encrypt all further
-communications in the session.
-The rest of the session is encrypted
-using a conventional cipher, currently Blowfish or 3DES, with 3DES
-being used by default.
-The client selects the encryption algorithm
-to use from those offered by the server.
-.Pp
-For protocol 2,
-forward security is provided through a Diffie-Hellman key agreement.
+host key against its own database to verify that it has not changed.
+Forward secrecy is provided through a Diffie-Hellman key agreement.
This key agreement results in a shared session key.
-The rest of the session is encrypted using a symmetric cipher, currently
-128-bit AES, Blowfish, 3DES, CAST128, Arcfour, 192-bit AES, or 256-bit AES.
+The rest of the session is encrypted using a symmetric cipher.
The client selects the encryption algorithm
to use from those offered by the server.
Additionally, session integrity is provided
-through a cryptographic message authentication code
-(hmac-md5, hmac-sha1, umac-64, umac-128, hmac-ripemd160,
-hmac-sha2-256 or hmac-sha2-512).
+through a cryptographic message authentication code (MAC).
.Pp
Finally, the server and the client enter an authentication dialog.
The client tries to authenticate itself using
@@ -333,7 +274,7 @@ locked, listed in
.Cm DenyUsers
or its group is listed in
.Cm DenyGroups
-\&. The definition of a locked account is system dependant. Some platforms
+\&. The definition of a locked account is system dependent. Some platforms
have their own account database (eg AIX) and some modify the passwd field (
.Ql \&*LK\&*
on Solaris and UnixWare,
@@ -424,6 +365,8 @@ See
below.
.It
Runs user's shell or command.
+All commands are run under the user's login shell as specified in the
+system password database.
.El
.Sh SSHRC
If the file
@@ -471,7 +414,7 @@ does not exist either, xauth is used to add the cookie.
.Cm AuthorizedKeysFile
specifies the files containing public keys for
public key authentication;
-if none is specified, the default is
+if this option is not specified, the default is
.Pa ~/.ssh/authorized_keys
and
.Pa ~/.ssh/authorized_keys2 .
@@ -480,42 +423,48 @@ key (empty lines and lines starting with a
.Ql #
are ignored as
comments).
-Protocol 1 public keys consist of the following space-separated fields:
-options, bits, exponent, modulus, comment.
-Protocol 2 public key consist of:
+Public keys consist of the following space-separated fields:
options, keytype, base64-encoded key, comment.
-The options field is optional;
-its presence is determined by whether the line starts
-with a number or not (the options field never starts with a number).
-The bits, exponent, modulus, and comment fields give the RSA key for
-protocol version 1; the
-comment field is not used for anything (but may be convenient for the
+The options field is optional.
+The supported key types are:
+.Pp
+.Bl -item -compact -offset indent
+.It
+sk-ecdsa-sha2-nistp256@openssh.com
+.It
+ecdsa-sha2-nistp256
+.It
+ecdsa-sha2-nistp384
+.It
+ecdsa-sha2-nistp521
+.It
+sk-ssh-ed25519@openssh.com
+.It
+ssh-ed25519
+.It
+ssh-dss
+.It
+ssh-rsa
+.El
+.Pp
+The comment field is not used for anything (but may be convenient for the
user to identify the key).
-For protocol version 2 the keytype is
-.Dq ecdsa-sha2-nistp256 ,
-.Dq ecdsa-sha2-nistp384 ,
-.Dq ecdsa-sha2-nistp521 ,
-.Dq ssh-ed25519 ,
-.Dq ssh-dss
-or
-.Dq ssh-rsa .
.Pp
-Note that lines in this file are usually several hundred bytes long
+Note that lines in this file can be several hundred bytes long
(because of the size of the public key encoding) up to a limit of
-8 kilobytes, which permits DSA keys up to 8 kilobits and RSA
-keys up to 16 kilobits.
+8 kilobytes, which permits RSA keys up to 16 kilobits.
You don't want to type them in; instead, copy the
-.Pa identity.pub ,
.Pa id_dsa.pub ,
.Pa id_ecdsa.pub ,
+.Pa id_ecdsa_sk.pub ,
.Pa id_ed25519.pub ,
+.Pa id_ed25519_sk.pub ,
or the
.Pa id_rsa.pub
file and edit it.
.Pp
.Nm
-enforces a minimum RSA key modulus size for protocol 1
-and protocol 2 keys of 768 bits.
+enforces a minimum RSA key modulus size of 1024 bits.
.Pp
The options (if present) consist of comma-separated option
specifications.
@@ -523,6 +472,10 @@ No spaces are permitted, except within double quotes.
The following option specifications are supported (note
that option keywords are case-insensitive):
.Bl -tag -width Ds
+.It Cm agent-forwarding
+Enable authentication agent forwarding previously disabled by the
+.Cm restrict
+option.
.It Cm cert-authority
Specifies that the listed key is a certification authority (CA) that is
trusted to validate signed certificates for user authentication.
@@ -540,19 +493,27 @@ If an 8-bit clean channel is required,
one must not request a pty or should specify
.Cm no-pty .
A quote may be included in the command by quoting it with a backslash.
+.Pp
This option might be useful
to restrict certain public keys to perform just a specific operation.
An example might be a key that permits remote backups but nothing else.
Note that the client may specify TCP and/or X11
-forwarding unless they are explicitly prohibited.
+forwarding unless they are explicitly prohibited, e.g. using the
+.Cm restrict
+key option.
+.Pp
The command originally supplied by the client is available in the
.Ev SSH_ORIGINAL_COMMAND
environment variable.
Note that this option applies to shell, command or subsystem execution.
-Also note that this command may be superseded by either a
+Also note that this command may be superseded by a
.Xr sshd_config 5
.Cm ForceCommand
-directive or a command embedded in a certificate.
+directive.
+.Pp
+If a command is specified and a forced-command is embedded in a certificate
+used for authentication, then the certificate will be accepted only if the
+two commands are identical.
.It Cm environment="NAME=value"
Specifies that the string is to be added to the environment when
logging in using this key.
@@ -563,9 +524,10 @@ Environment processing is disabled by default and is
controlled via the
.Cm PermitUserEnvironment
option.
-This option is automatically disabled if
-.Cm UseLogin
-is enabled.
+.It Cm expiry-time="timespec"
+Specifies a time after which the key will not be accepted.
+The time may be specified as a YYYYMMDD date or a YYYYMMDDHHMM[SS] time
+in the system time-zone.
.It Cm from="pattern-list"
Specifies that in addition to public key authentication, either the canonical
name of the remote host or its IP address must be present in the
@@ -603,20 +565,50 @@ Disables execution of
.It Cm no-X11-forwarding
Forbids X11 forwarding when this key is used for authentication.
Any X11 forward requests by the client will return an error.
+.It Cm permitlisten="[host:]port"
+Limit remote port forwarding with the
+.Xr ssh 1
+.Fl R
+option such that it may only listen on the specified host (optional) and port.
+IPv6 addresses can be specified by enclosing the address in square brackets.
+Multiple
+.Cm permitlisten
+options may be applied separated by commas.
+Hostnames may include wildcards as described in the PATTERNS section in
+.Xr ssh_config 5 .
+A port specification of
+.Cm *
+matches any port.
+Note that the setting of
+.Cm GatewayPorts
+may further restrict listen addresses.
+Note that
+.Xr ssh 1
+will send a hostname of
+.Dq localhost
+if a listen host was not specified when the forwarding was requested, and
+that this name is treated differently to the explicit localhost addresses
+.Dq 127.0.0.1
+and
+.Dq ::1 .
.It Cm permitopen="host:port"
-Limit local port forwarding with
+Limit local port forwarding with the
.Xr ssh 1
.Fl L
-such that it may only connect to the specified host and port.
+option such that it may only connect to the specified host and port.
IPv6 addresses can be specified by enclosing the address in square brackets.
Multiple
.Cm permitopen
options may be applied separated by commas.
-No pattern matching is performed on the specified hostnames,
-they must be literal domains or addresses.
+No pattern matching or name lookup is performed on the
+specified hostnames, they must be literal host names and/or addresses.
A port specification of
.Cm *
matches any port.
+.It Cm port-forwarding
+Enable port forwarding previously disabled by the
+.Cm restrict
+option.
.It Cm principals="principals"
On a
.Cm cert-authority
@@ -628,12 +620,40 @@ This option is ignored for keys that are not marked as trusted certificate
signers using the
.Cm cert-authority
option.
+.It Cm pty
+Permits tty allocation previously disabled by the
+.Cm restrict
+option.
+.It Cm no-touch-required
+Do not require demonstration of user presence
+for signatures made using this key.
+This option only makes sense for the FIDO authenticator algorithms
+.Cm ecdsa-sk
+and
+.Cm ed25519-sk .
+.It Cm restrict
+Enable all restrictions, i.e. disable port, agent and X11 forwarding,
+as well as disabling PTY allocation
+and execution of
+.Pa ~/.ssh/rc .
+If any future restriction capabilities are added to authorized_keys files
+they will be included in this set.
.It Cm tunnel="n"
Force a
.Xr tun 4
device on the server.
Without this option, the next available device will be used if
the client requests a tunnel.
+.It Cm user-rc
+Enables execution of
+.Pa ~/.ssh/rc
+previously disabled by the
+.Cm restrict
+option.
+.It Cm X11-forwarding
+Permits X11 forwarding previously disabled by the
+.Cm restrict
+option.
.El
.Pp
An example authorized_keys file:
@@ -642,12 +662,20 @@ An example authorized_keys file:
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-dss
+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-dss
+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
.Ed
.Sh SSH_KNOWN_HOSTS FILE FORMAT
The
@@ -657,11 +685,11 @@ and
files contain host public keys for all known hosts.
The global file should
be prepared by the administrator (optional), and the per-user file is
-maintained automatically: whenever the user connects from an unknown host,
+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),
-hostnames, bits, exponent, modulus, comment.
+hostnames, keytype, base64-encoded key, comment.
The fields are separated by spaces.
.Pp
The marker is optional, but if it is present then it must be one of
@@ -678,9 +706,23 @@ Hostnames is a comma-separated list of patterns
and
.Ql \&?
act as
-wildcards); each pattern in turn is matched against the canonical host
-name (when authenticating a client) or against the user-supplied
-name (when authenticating a server).
+wildcards); each pattern in turn is matched against the host name.
+When
+.Nm sshd
+is authenticating a client, such as when using
+.Cm HostbasedAuthentication ,
+this will be the canonical client host name.
+When
+.Xr ssh 1
+is authenticating a server, this will be the host name
+given by the user, the value of the
+.Xr ssh 1
+.Cm HostkeyAlias
+if it was specified, or the canonical server hostname if the
+.Xr ssh 1
+.Cm CanonicalizeHostname
+option was used.
+.Pp
A pattern may also be preceded by
.Ql \&!
to indicate negation: if the host name matches a negated
@@ -702,9 +744,9 @@ character.
Only one hashed hostname may appear on a single line and none of the above
negation or wildcard operators may be applied.
.Pp
-Bits, exponent, and modulus are taken directly from the RSA host key; they
+The keytype and base64-encoded key are taken directly from the host key; they
can be obtained, for example, from
-.Pa /etc/ssh/ssh_host_key.pub .
+.Pa /etc/ssh/ssh_host_rsa_key.pub .
The optional comment field continues to the end of the line, and is not used.
.Pp
Lines starting with
@@ -743,8 +785,8 @@ Note that the lines in these files are typically hundreds of characters
long, and you definitely don't want to type in the host keys by hand.
Rather, generate them by a script,
.Xr ssh-keyscan 1
-or by taking
-.Pa /etc/ssh/ssh_host_key.pub
+or by taking, for example,
+.Pa /etc/ssh/ssh_host_rsa_key.pub
and adding the host names at the front.
.Xr ssh-keygen 1
also offers some basic automated editing for
@@ -857,9 +899,12 @@ This file is for host-based authentication (see
It should only be writable by root.
.Pp
.It Pa /etc/moduli
-Contains Diffie-Hellman groups used for the "Diffie-Hellman Group Exchange".
+Contains Diffie-Hellman groups used for the "Diffie-Hellman Group Exchange"
+key exchange method.
The file format is described in
.Xr moduli 5 .
+If no usable groups are found in this file then fixed internal groups will
+be used.
.Pp
.It Pa /etc/motd
See
@@ -880,8 +925,6 @@ This file is used in exactly the same way as
but allows host-based authentication without permitting login with
rlogin/rsh.
.Pp
-.It Pa /etc/ssh/ssh_host_key
-.It Pa /etc/ssh/ssh_host_dsa_key
.It Pa /etc/ssh/ssh_host_ecdsa_key
.It Pa /etc/ssh/ssh_host_ed25519_key
.It Pa /etc/ssh/ssh_host_rsa_key
@@ -892,8 +935,6 @@ Note that
.Nm
does not start if these files are group/world-accessible.
.Pp
-.It Pa /etc/ssh/ssh_host_key.pub
-.It Pa /etc/ssh/ssh_host_dsa_key.pub
.It Pa /etc/ssh/ssh_host_ecdsa_key.pub
.It Pa /etc/ssh/ssh_host_ed25519_key.pub
.It Pa /etc/ssh/ssh_host_rsa_key.pub
diff --git a/sshd.c b/sshd.c
index 54ea6c06..fba25e6b 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.444 2015/02/20 22:17:21 djm Exp $ */
+/* $OpenBSD: sshd.c,v 1.552 2020/03/13 04:01:57 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -87,20 +87,19 @@
#include "xmalloc.h"
#include "ssh.h"
-#include "ssh1.h"
#include "ssh2.h"
-#include "rsa.h"
#include "sshpty.h"
#include "packet.h"
#include "log.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "misc.h"
+#include "match.h"
#include "servconf.h"
#include "uidswap.h"
#include "compat.h"
#include "cipher.h"
#include "digest.h"
-#include "key.h"
+#include "sshkey.h"
#include "kex.h"
#include "myproposal.h"
#include "authfile.h"
@@ -114,20 +113,16 @@
#include "dispatch.h"
#include "channels.h"
#include "session.h"
-#include "monitor_mm.h"
#include "monitor.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
-#include "roaming.h"
#include "ssh-sandbox.h"
+#include "auth-options.h"
#include "version.h"
#include "ssherr.h"
-
-#ifndef O_NOCTTY
-#define O_NOCTTY 0
-#endif
+#include "sk-api.h"
/* Re-exec fds */
#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
@@ -151,46 +146,44 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE;
*/
int debug_flag = 0;
-/* Flag indicating that the daemon should only test the configuration and keys. */
-int test_flag = 0;
+/*
+ * Indicating that the daemon should only test the configuration and keys.
+ * If test_flag > 1 ("-T" flag), then sshd will also dump the effective
+ * configuration, optionally using connection information provided by the
+ * "-C" flag.
+ */
+static int test_flag = 0;
/* Flag indicating that the daemon is being started from inetd. */
-int inetd_flag = 0;
+static int inetd_flag = 0;
/* Flag indicating that sshd should not detach and become a daemon. */
-int no_daemon_flag = 0;
+static int no_daemon_flag = 0;
/* debug goes to stderr unless inetd_flag is set */
-int log_stderr = 0;
+static int log_stderr = 0;
/* Saved arguments to main(). */
-char **saved_argv;
-int saved_argc;
+static char **saved_argv;
+static int saved_argc;
/* re-exec */
-int rexeced_flag = 0;
-int rexec_flag = 1;
-int rexec_argc = 0;
-char **rexec_argv;
+static int rexeced_flag = 0;
+static int rexec_flag = 1;
+static int rexec_argc = 0;
+static char **rexec_argv;
/*
* The sockets that the server is listening; this is used in the SIGHUP
* signal handler.
*/
#define MAX_LISTEN_SOCKS 16
-int listen_socks[MAX_LISTEN_SOCKS];
-int num_listen_socks = 0;
-
-/*
- * the client's version string, passed by sshd2 in compat mode. if != NULL,
- * sshd will skip the version-number exchange
- */
-char *client_version_string = NULL;
-char *server_version_string = NULL;
+static int listen_socks[MAX_LISTEN_SOCKS];
+static int num_listen_socks = 0;
/* Daemon's agent connection */
int auth_sock = -1;
-int have_agent = 0;
+static int have_agent = 0;
/*
* Any really sensitive data in the application is contained in this
@@ -201,22 +194,12 @@ int have_agent = 0;
* not very useful. Currently, memory locking is not implemented.
*/
struct {
- Key *server_key; /* ephemeral server key */
- Key *ssh1_host_key; /* ssh1 host key */
- Key **host_keys; /* all private host keys */
- Key **host_pubkeys; /* all public host keys */
- Key **host_certificates; /* all public host certificates */
- int have_ssh1_key;
- int have_ssh2_key;
- u_char ssh1_cookie[SSH_SESSION_KEY_LENGTH];
+ struct sshkey **host_keys; /* all private host keys */
+ struct sshkey **host_pubkeys; /* all public host keys */
+ struct sshkey **host_certificates; /* all public host certificates */
+ int have_ssh2_key;
} sensitive_data;
-/*
- * Flag indicating whether the RSA server key needs to be regenerated.
- * Is set in the SIGALRM handler and cleared when the key is regenerated.
- */
-static volatile sig_atomic_t key_do_regen = 0;
-
/* This is set to true when a signal is received. */
static volatile sig_atomic_t received_sighup = 0;
static volatile sig_atomic_t received_sigterm = 0;
@@ -231,23 +214,48 @@ u_int session_id2_len = 0;
/* record remote hostname or ip */
u_int utmp_len = HOST_NAME_MAX+1;
-/* options.max_startup sized array of fd ints */
-int *startup_pipes = NULL;
-int startup_pipe; /* in child */
+/*
+ * startup_pipes/flags are used for tracking children of the listening sshd
+ * process early in their lifespans. This tracking is needed for three things:
+ *
+ * 1) Implementing the MaxStartups limit of concurrent unauthenticated
+ * connections.
+ * 2) Avoiding a race condition for SIGHUP processing, where child processes
+ * may have listen_socks open that could collide with main listener process
+ * after it restarts.
+ * 3) Ensuring that rexec'd sshd processes have received their initial state
+ * from the parent listen process before handling SIGHUP.
+ *
+ * Child processes signal that they have completed closure of the listen_socks
+ * and (if applicable) received their rexec state by sending a char over their
+ * sock. Child processes signal that authentication has completed by closing
+ * the sock (or by exiting).
+ */
+static int *startup_pipes = NULL;
+static int *startup_flags = NULL; /* Indicates child closed listener */
+static int startup_pipe = -1; /* in child */
/* variables used for privilege separation */
int use_privsep = -1;
struct monitor *pmonitor = NULL;
int privsep_is_preauth = 1;
+static int privsep_chroot = 1;
-/* global authentication context */
+/* global connection state and authentication contexts */
Authctxt *the_authctxt = NULL;
+struct ssh *the_active_state;
+
+/* global key/cert auth options. XXX move to permanent ssh->authctxt? */
+struct sshauthopt *auth_opts = NULL;
/* sshd_config buffer */
-Buffer cfg;
+struct sshbuf *cfg;
+
+/* Included files from the configuration file */
+struct include_list includes = TAILQ_HEAD_INITIALIZER(includes);
/* message to be displayed after login */
-Buffer loginmsg;
+struct sshbuf *loginmsg;
/* Unprivileged user */
struct passwd *privsep_pw = NULL;
@@ -255,11 +263,9 @@ struct passwd *privsep_pw = NULL;
/* Prototypes for various functions defined later in this file. */
void destroy_sensitive_data(void);
void demote_sensitive_data(void);
+static void do_ssh2_kex(struct ssh *);
-#ifdef WITH_SSH1
-static void do_ssh1_kex(void);
-#endif
-static void do_ssh2_kex(void);
+static char *listener_proctitle;
/*
* Close all listening sockets
@@ -295,11 +301,7 @@ close_startup_pipes(void)
static void
sighup_handler(int sig)
{
- int save_errno = errno;
-
received_sighup = 1;
- signal(SIGHUP, sighup_handler);
- errno = save_errno;
}
/*
@@ -310,11 +312,12 @@ static void
sighup_restart(void)
{
logit("Received SIGHUP; restarting.");
+ if (options.pid_file != NULL)
+ unlink(options.pid_file);
platform_pre_restart();
close_listen_socks();
close_startup_pipes();
- alarm(0); /* alarm timer persists across exec */
- signal(SIGHUP, SIG_IGN); /* will be restored after exec */
+ ssh_signal(SIGHUP, SIG_IGN); /* will be restored after exec */
execv(saved_argv[0], saved_argv);
logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0],
strerror(errno));
@@ -343,11 +346,11 @@ 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 < 0 && errno == EINTR))
+ (pid == -1 && errno == EINTR))
;
-
- signal(SIGCHLD, main_sigchld_handler);
errno = save_errno;
}
@@ -366,248 +369,81 @@ grace_alarm_handler(int sig)
* keys command helpers.
*/
if (getpgid(0) == getpid()) {
- signal(SIGTERM, SIG_IGN);
+ ssh_signal(SIGTERM, SIG_IGN);
kill(0, SIGTERM);
}
+ /* XXX pre-format ipaddr/port so we don't need to access active_state */
/* Log error and exit. */
- sigdie("Timeout before authentication for %s", get_remote_ipaddr());
-}
-
-/*
- * Signal handler for the key regeneration alarm. Note that this
- * alarm only occurs in the daemon waiting for connections, and it does not
- * do anything with the private key or random state before forking.
- * Thus there should be no concurrency control/asynchronous execution
- * problems.
- */
-static void
-generate_ephemeral_server_key(void)
-{
- verbose("Generating %s%d bit RSA key.",
- sensitive_data.server_key ? "new " : "", options.server_key_bits);
- if (sensitive_data.server_key != NULL)
- key_free(sensitive_data.server_key);
- sensitive_data.server_key = key_generate(KEY_RSA1,
- options.server_key_bits);
- verbose("RSA key generation complete.");
-
- arc4random_buf(sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
-}
-
-/*ARGSUSED*/
-static void
-key_regeneration_alarm(int sig)
-{
- int save_errno = errno;
-
- signal(SIGALRM, SIG_DFL);
- errno = save_errno;
- key_do_regen = 1;
-}
-
-static void
-sshd_exchange_identification(int sock_in, int sock_out)
-{
- u_int i;
- int mismatch;
- int remote_major, remote_minor;
- int major, minor;
- char *s, *newline = "\n";
- char buf[256]; /* Must not be larger than remote_version. */
- char remote_version[256]; /* Must be at least as big as buf. */
-
- if ((options.protocol & SSH_PROTO_1) &&
- (options.protocol & SSH_PROTO_2)) {
- major = PROTOCOL_MAJOR_1;
- minor = 99;
- } else if (options.protocol & SSH_PROTO_2) {
- major = PROTOCOL_MAJOR_2;
- minor = PROTOCOL_MINOR_2;
- newline = "\r\n";
- } else {
- major = PROTOCOL_MAJOR_1;
- minor = PROTOCOL_MINOR_1;
- }
-
- xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s",
- major, minor, SSH_VERSION,
- *options.version_addendum == '\0' ? "" : " ",
- options.version_addendum, newline);
-
- /* Send our protocol version identification. */
- if (roaming_atomicio(vwrite, sock_out, server_version_string,
- strlen(server_version_string))
- != strlen(server_version_string)) {
- logit("Could not write ident string to %s", get_remote_ipaddr());
- cleanup_exit(255);
- }
-
- /* Read other sides version identification. */
- memset(buf, 0, sizeof(buf));
- for (i = 0; i < sizeof(buf) - 1; i++) {
- if (roaming_atomicio(read, sock_in, &buf[i], 1) != 1) {
- logit("Did not receive identification string from %s",
- get_remote_ipaddr());
- cleanup_exit(255);
- }
- if (buf[i] == '\r') {
- buf[i] = 0;
- /* Kludge for F-Secure Macintosh < 1.0.2 */
- if (i == 12 &&
- strncmp(buf, "SSH-1.5-W1.0", 12) == 0)
- break;
- continue;
- }
- if (buf[i] == '\n') {
- buf[i] = 0;
- break;
- }
- }
- buf[sizeof(buf) - 1] = 0;
- client_version_string = xstrdup(buf);
-
- /*
- * Check that the versions match. In future this might accept
- * several versions and set appropriate flags to handle them.
- */
- if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n",
- &remote_major, &remote_minor, remote_version) != 3) {
- s = "Protocol mismatch.\n";
- (void) atomicio(vwrite, sock_out, s, strlen(s));
- logit("Bad protocol version identification '%.100s' "
- "from %s port %d", client_version_string,
- get_remote_ipaddr(), get_remote_port());
- close(sock_in);
- close(sock_out);
- cleanup_exit(255);
- }
- debug("Client protocol version %d.%d; client software version %.100s",
- remote_major, remote_minor, remote_version);
-
- active_state->compat = compat_datafellows(remote_version);
-
- if ((datafellows & SSH_BUG_PROBE) != 0) {
- logit("probed from %s with %s. Don't panic.",
- get_remote_ipaddr(), client_version_string);
- cleanup_exit(255);
- }
- if ((datafellows & SSH_BUG_SCANNER) != 0) {
- logit("scanned from %s with %s. Don't panic.",
- get_remote_ipaddr(), client_version_string);
- cleanup_exit(255);
- }
- if ((datafellows & SSH_BUG_RSASIGMD5) != 0) {
- logit("Client version \"%.100s\" uses unsafe RSA signature "
- "scheme; disabling use of RSA keys", remote_version);
- }
- if ((datafellows & SSH_BUG_DERIVEKEY) != 0) {
- fatal("Client version \"%.100s\" uses unsafe key agreement; "
- "refusing connection", remote_version);
- }
-
- mismatch = 0;
- switch (remote_major) {
- case 1:
- if (remote_minor == 99) {
- if (options.protocol & SSH_PROTO_2)
- enable_compat20();
- else
- mismatch = 1;
- break;
- }
- if (!(options.protocol & SSH_PROTO_1)) {
- mismatch = 1;
- break;
- }
- if (remote_minor < 3) {
- packet_disconnect("Your ssh version is too old and "
- "is no longer supported. Please install a newer version.");
- } else if (remote_minor == 3) {
- /* note that this disables agent-forwarding */
- enable_compat13();
- }
- break;
- case 2:
- if (options.protocol & SSH_PROTO_2) {
- enable_compat20();
- break;
- }
- /* FALLTHROUGH */
- default:
- mismatch = 1;
- break;
- }
- chop(server_version_string);
- debug("Local version string %.200s", server_version_string);
-
- if (mismatch) {
- s = "Protocol major versions differ.\n";
- (void) atomicio(vwrite, sock_out, s, strlen(s));
- close(sock_in);
- close(sock_out);
- logit("Protocol major versions differ for %s: %.200s vs. %.200s",
- get_remote_ipaddr(),
- server_version_string, client_version_string);
- cleanup_exit(255);
- }
+ sigdie("Timeout before authentication for %s port %d",
+ ssh_remote_ipaddr(the_active_state),
+ ssh_remote_port(the_active_state));
}
/* Destroy the host and server keys. They will no longer be needed. */
void
destroy_sensitive_data(void)
{
- int i;
+ u_int i;
- if (sensitive_data.server_key) {
- key_free(sensitive_data.server_key);
- sensitive_data.server_key = NULL;
- }
for (i = 0; i < options.num_host_key_files; i++) {
if (sensitive_data.host_keys[i]) {
- key_free(sensitive_data.host_keys[i]);
+ sshkey_free(sensitive_data.host_keys[i]);
sensitive_data.host_keys[i] = NULL;
}
if (sensitive_data.host_certificates[i]) {
- key_free(sensitive_data.host_certificates[i]);
+ sshkey_free(sensitive_data.host_certificates[i]);
sensitive_data.host_certificates[i] = NULL;
}
}
- sensitive_data.ssh1_host_key = NULL;
- explicit_bzero(sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
}
/* Demote private to public keys for network child */
void
demote_sensitive_data(void)
{
- Key *tmp;
- int i;
-
- if (sensitive_data.server_key) {
- tmp = key_demote(sensitive_data.server_key);
- key_free(sensitive_data.server_key);
- sensitive_data.server_key = tmp;
- }
+ struct sshkey *tmp;
+ u_int i;
+ int r;
for (i = 0; i < options.num_host_key_files; i++) {
if (sensitive_data.host_keys[i]) {
- tmp = key_demote(sensitive_data.host_keys[i]);
- key_free(sensitive_data.host_keys[i]);
+ if ((r = sshkey_from_private(
+ sensitive_data.host_keys[i], &tmp)) != 0)
+ fatal("could not demote host %s key: %s",
+ sshkey_type(sensitive_data.host_keys[i]),
+ ssh_err(r));
+ sshkey_free(sensitive_data.host_keys[i]);
sensitive_data.host_keys[i] = tmp;
- if (tmp->type == KEY_RSA1)
- sensitive_data.ssh1_host_key = tmp;
}
/* Certs do not need demotion */
}
+}
+
+static void
+reseed_prngs(void)
+{
+ u_int32_t rnd[256];
- /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */
+#ifdef WITH_OPENSSL
+ RAND_poll();
+#endif
+ arc4random_stir(); /* noop on recent arc4random() implementations */
+ arc4random_buf(rnd, sizeof(rnd)); /* let arc4random notice PID change */
+
+#ifdef WITH_OPENSSL
+ RAND_seed(rnd, sizeof(rnd));
+ /* give libcrypto a chance to notice the PID change */
+ if ((RAND_bytes((u_char *)rnd, 1)) != 1)
+ fatal("%s: RAND_bytes failed", __func__);
+#endif
+
+ explicit_bzero(rnd, sizeof(rnd));
}
static void
privsep_preauth_child(void)
{
- u_int32_t rnd[256];
gid_t gidset[1];
/* Enable challenge-response authentication for privilege separation */
@@ -615,45 +451,35 @@ privsep_preauth_child(void)
#ifdef GSSAPI
/* Cache supported mechanism OIDs for later use */
- if (options.gss_authentication)
- ssh_gssapi_prepare_supported_oids();
+ ssh_gssapi_prepare_supported_oids();
#endif
- arc4random_stir();
- arc4random_buf(rnd, sizeof(rnd));
-#ifdef WITH_OPENSSL
- RAND_seed(rnd, sizeof(rnd));
- if ((RAND_bytes((u_char *)rnd, 1)) != 1)
- fatal("%s: RAND_bytes failed", __func__);
-#endif
- explicit_bzero(rnd, sizeof(rnd));
+ reseed_prngs();
/* Demote the private keys to public keys. */
demote_sensitive_data();
- /* Change our root directory */
- if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
- fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
- strerror(errno));
- if (chdir("/") == -1)
- fatal("chdir(\"/\"): %s", strerror(errno));
-
- /* Drop our privileges */
- debug3("privsep user:group %u:%u", (u_int)privsep_pw->pw_uid,
- (u_int)privsep_pw->pw_gid);
-#if 0
- /* XXX not ready, too heavy after chroot */
- do_setusercontext(privsep_pw);
-#else
- gidset[0] = privsep_pw->pw_gid;
- if (setgroups(1, gidset) < 0)
- fatal("setgroups: %.100s", strerror(errno));
- permanently_set_uid(privsep_pw);
-#endif
+ /* Demote the child */
+ if (privsep_chroot) {
+ /* Change our root directory */
+ if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
+ fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
+ strerror(errno));
+ if (chdir("/") == -1)
+ fatal("chdir(\"/\"): %s", strerror(errno));
+
+ /* Drop our privileges */
+ debug3("privsep user:group %u:%u", (u_int)privsep_pw->pw_uid,
+ (u_int)privsep_pw->pw_gid);
+ gidset[0] = privsep_pw->pw_gid;
+ if (setgroups(1, gidset) == -1)
+ fatal("setgroups: %.100s", strerror(errno));
+ permanently_set_uid(privsep_pw);
+ }
}
static int
-privsep_preauth(Authctxt *authctxt)
+privsep_preauth(struct ssh *ssh)
{
int status, r;
pid_t pid;
@@ -662,7 +488,7 @@ privsep_preauth(Authctxt *authctxt)
/* Set up unprivileged child process to deal with network data */
pmonitor = monitor_init();
/* Store a pointer to the kex for later rekeying */
- pmonitor->m_pkex = &active_state->kex;
+ pmonitor->m_pkex = &ssh->kex;
if (use_privsep == PRIVSEP_ON)
box = ssh_sandbox_init(pmonitor);
@@ -683,13 +509,10 @@ privsep_preauth(Authctxt *authctxt)
}
if (box != NULL)
ssh_sandbox_parent_preauth(box, pid);
- monitor_child_preauth(authctxt, pmonitor);
-
- /* Sync memory */
- monitor_sync(pmonitor);
+ monitor_child_preauth(ssh, pmonitor);
/* Wait for the child's exit status */
- while (waitpid(pid, &status, 0) < 0) {
+ while (waitpid(pid, &status, 0) == -1) {
if (errno == EINTR)
continue;
pmonitor->m_pid = -1;
@@ -715,9 +538,7 @@ privsep_preauth(Authctxt *authctxt)
/* Arrange for logging to be sent to the monitor */
set_log_handler(mm_log_handler, pmonitor);
- /* Demote the child */
- if (getuid() == 0 || geteuid() == 0)
- privsep_preauth_child();
+ privsep_preauth_child();
setproctitle("%s", "[net]");
if (box != NULL)
ssh_sandbox_child(box);
@@ -727,14 +548,12 @@ privsep_preauth(Authctxt *authctxt)
}
static void
-privsep_postauth(Authctxt *authctxt)
+privsep_postauth(struct ssh *ssh, Authctxt *authctxt)
{
- u_int32_t rnd[256];
-
#ifdef DISABLE_FD_PASSING
if (1) {
#else
- if (authctxt->pw->pw_uid == 0 || options.use_login) {
+ if (authctxt->pw->pw_uid == 0) {
#endif
/* File descriptor passing is broken or root login */
use_privsep = 0;
@@ -749,8 +568,9 @@ privsep_postauth(Authctxt *authctxt)
fatal("fork of unprivileged child failed");
else if (pmonitor->m_pid != 0) {
verbose("User child is on pid %ld", (long)pmonitor->m_pid);
- buffer_clear(&loginmsg);
- monitor_child_postauth(pmonitor);
+ sshbuf_reset(loginmsg);
+ monitor_clear_keystate(ssh, pmonitor);
+ monitor_child_postauth(ssh, pmonitor);
/* NEVERREACHED */
exit(0);
@@ -764,39 +584,46 @@ privsep_postauth(Authctxt *authctxt)
/* Demote the private keys to public keys. */
demote_sensitive_data();
- arc4random_stir();
- arc4random_buf(rnd, sizeof(rnd));
-#ifdef WITH_OPENSSL
- RAND_seed(rnd, sizeof(rnd));
- if ((RAND_bytes((u_char *)rnd, 1)) != 1)
- fatal("%s: RAND_bytes failed", __func__);
-#endif
- explicit_bzero(rnd, sizeof(rnd));
+ reseed_prngs();
/* Drop privileges */
do_setusercontext(authctxt->pw);
skip:
/* It is safe now to apply the key state */
- monitor_apply_keystate(pmonitor);
+ monitor_apply_keystate(ssh, pmonitor);
/*
* Tell the packet layer that authentication was successful, since
* this information is not part of the key state.
*/
- packet_set_authenticated();
+ ssh_packet_set_authenticated(ssh);
+}
+
+static void
+append_hostkey_type(struct sshbuf *b, const char *s)
+{
+ int r;
+
+ if (match_pattern_list(s, options.hostkeyalgorithms, 0) != 1) {
+ debug3("%s: %s key not permitted by HostkeyAlgorithms",
+ __func__, s);
+ return;
+ }
+ if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) > 0 ? "," : "", s)) != 0)
+ fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r));
}
static char *
list_hostkey_types(void)
{
- Buffer b;
- const char *p;
+ struct sshbuf *b;
+ struct sshkey *key;
char *ret;
- int i;
- Key *key;
+ u_int i;
- buffer_init(&b);
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
for (i = 0; i < options.num_host_key_files; i++) {
key = sensitive_data.host_keys[i];
if (key == NULL)
@@ -805,13 +632,17 @@ list_hostkey_types(void)
continue;
switch (key->type) {
case KEY_RSA:
+ /* for RSA we also support SHA2 signatures */
+ append_hostkey_type(b, "rsa-sha2-512");
+ append_hostkey_type(b, "rsa-sha2-256");
+ /* FALLTHROUGH */
case KEY_DSA:
case KEY_ECDSA:
case KEY_ED25519:
- if (buffer_len(&b) > 0)
- buffer_append(&b, ",", 1);
- p = key_ssh_name(key);
- buffer_append(&b, p, strlen(p));
+ case KEY_ECDSA_SK:
+ case KEY_ED25519_SK:
+ case KEY_XMSS:
+ append_hostkey_type(b, sshkey_ssh_name(key));
break;
}
/* If the private key has a cert peer, then list that too */
@@ -819,40 +650,45 @@ list_hostkey_types(void)
if (key == NULL)
continue;
switch (key->type) {
- case KEY_RSA_CERT_V00:
- case KEY_DSA_CERT_V00:
case KEY_RSA_CERT:
+ /* for RSA we also support SHA2 signatures */
+ append_hostkey_type(b,
+ "rsa-sha2-512-cert-v01@openssh.com");
+ append_hostkey_type(b,
+ "rsa-sha2-256-cert-v01@openssh.com");
+ /* FALLTHROUGH */
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_ED25519_CERT:
- if (buffer_len(&b) > 0)
- buffer_append(&b, ",", 1);
- p = key_ssh_name(key);
- buffer_append(&b, p, strlen(p));
+ case KEY_ECDSA_SK_CERT:
+ case KEY_ED25519_SK_CERT:
+ case KEY_XMSS_CERT:
+ append_hostkey_type(b, sshkey_ssh_name(key));
break;
}
}
- buffer_append(&b, "\0", 1);
- ret = xstrdup(buffer_ptr(&b));
- buffer_free(&b);
- debug("list_hostkey_types: %s", ret);
+ if ((ret = sshbuf_dup_string(b)) == NULL)
+ fatal("%s: sshbuf_dup_string failed", __func__);
+ sshbuf_free(b);
+ debug("%s: %s", __func__, ret);
return ret;
}
-static Key *
+static struct sshkey *
get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh)
{
- int i;
- Key *key;
+ u_int i;
+ struct sshkey *key;
for (i = 0; i < options.num_host_key_files; i++) {
switch (type) {
- case KEY_RSA_CERT_V00:
- case KEY_DSA_CERT_V00:
case KEY_RSA_CERT:
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_ED25519_CERT:
+ case KEY_ECDSA_SK_CERT:
+ case KEY_ED25519_SK_CERT:
+ case KEY_XMSS_CERT:
key = sensitive_data.host_certificates[i];
break;
default:
@@ -861,49 +697,59 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh)
key = sensitive_data.host_pubkeys[i];
break;
}
- if (key != NULL && key->type == type &&
- (key->type != KEY_ECDSA || key->ecdsa_nid == nid))
+ if (key == NULL || key->type != type)
+ continue;
+ switch (type) {
+ case KEY_ECDSA:
+ case KEY_ECDSA_SK:
+ case KEY_ECDSA_CERT:
+ case KEY_ECDSA_SK_CERT:
+ if (key->ecdsa_nid != nid)
+ continue;
+ /* FALLTHROUGH */
+ default:
return need_private ?
sensitive_data.host_keys[i] : key;
+ }
}
return NULL;
}
-Key *
+struct sshkey *
get_hostkey_public_by_type(int type, int nid, struct ssh *ssh)
{
return get_hostkey_by_type(type, nid, 0, ssh);
}
-Key *
+struct sshkey *
get_hostkey_private_by_type(int type, int nid, struct ssh *ssh)
{
return get_hostkey_by_type(type, nid, 1, ssh);
}
-Key *
+struct sshkey *
get_hostkey_by_index(int ind)
{
- if (ind < 0 || ind >= options.num_host_key_files)
+ if (ind < 0 || (u_int)ind >= options.num_host_key_files)
return (NULL);
return (sensitive_data.host_keys[ind]);
}
-Key *
+struct sshkey *
get_hostkey_public_by_index(int ind, struct ssh *ssh)
{
- if (ind < 0 || ind >= options.num_host_key_files)
+ if (ind < 0 || (u_int)ind >= options.num_host_key_files)
return (NULL);
return (sensitive_data.host_pubkeys[ind]);
}
int
-get_hostkey_index(Key *key, int compare, struct ssh *ssh)
+get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh)
{
- int i;
+ u_int i;
for (i = 0; i < options.num_host_key_files; i++) {
- if (key_is_cert(key)) {
+ if (sshkey_is_cert(key)) {
if (key == sensitive_data.host_certificates[i] ||
(compare && sensitive_data.host_certificates[i] &&
sshkey_equal(key,
@@ -929,15 +775,20 @@ notify_hostkeys(struct ssh *ssh)
{
struct sshbuf *buf;
struct sshkey *key;
- int i, nkeys, r;
+ u_int i, nkeys;
+ int r;
char *fp;
+ /* Some clients cannot cope with the hostkeys message, skip those. */
+ if (ssh->compat & SSH_BUG_HOSTKEYS)
+ return;
+
if ((buf = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
for (i = nkeys = 0; i < options.num_host_key_files; i++) {
key = get_hostkey_public_by_index(i, ssh);
if (key == NULL || key->type == KEY_UNSPEC ||
- key->type == KEY_RSA1 || sshkey_is_cert(key))
+ sshkey_is_cert(key))
continue;
fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
@@ -945,21 +796,29 @@ notify_hostkeys(struct ssh *ssh)
sshkey_ssh_name(key), fp);
free(fp);
if (nkeys == 0) {
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring("hostkeys-00@openssh.com");
- packet_put_char(0); /* want-reply */
+ /*
+ * Start building the request when we find the
+ * first usable key.
+ */
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "hostkeys-00@openssh.com")) != 0 ||
+ (r = sshpkt_put_u8(ssh, 0)) != 0) /* want reply */
+ sshpkt_fatal(ssh, r, "%s: start request", __func__);
}
+ /* Append the key to the request */
sshbuf_reset(buf);
if ((r = sshkey_putb(key, buf)) != 0)
fatal("%s: couldn't put hostkey %d: %s",
__func__, i, ssh_err(r));
- packet_put_string(sshbuf_ptr(buf), sshbuf_len(buf));
+ if ((r = sshpkt_put_stringb(ssh, buf)) != 0)
+ sshpkt_fatal(ssh, r, "%s: append key", __func__);
nkeys++;
}
- debug3("%s: sent %d hostkeys", __func__, nkeys);
+ debug3("%s: sent %u hostkeys", __func__, nkeys);
if (nkeys == 0)
fatal("%s: no hostkeys", __func__);
- packet_send();
+ if ((r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send", __func__);
sshbuf_free(buf);
}
@@ -997,115 +856,108 @@ usage(void)
fprintf(stderr, "%s, %s\n",
SSH_RELEASE,
#ifdef WITH_OPENSSL
- SSLeay_version(SSLEAY_VERSION)
+ OpenSSL_version(OPENSSL_VERSION)
#else
"without OpenSSL"
#endif
);
fprintf(stderr,
-"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"
+"usage: sshd [-46DdeiqTt] [-C connection_spec] [-c host_cert_file]\n"
" [-E log_file] [-f config_file] [-g login_grace_time]\n"
-" [-h host_key_file] [-k key_gen_time] [-o option] [-p port]\n"
-" [-u len]\n"
+" [-h host_key_file] [-o option] [-p port] [-u len]\n"
);
exit(1);
}
static void
-send_rexec_state(int fd, Buffer *conf)
+send_rexec_state(int fd, struct sshbuf *conf)
{
- Buffer m;
+ struct sshbuf *m = NULL, *inc = NULL;
+ struct include_item *item = NULL;
+ int r;
+
+ debug3("%s: entering fd = %d config len %zu", __func__, fd,
+ sshbuf_len(conf));
- debug3("%s: entering fd = %d config len %d", __func__, fd,
- buffer_len(conf));
+ if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+
+ /* 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));
+ }
/*
* Protocol from reexec master to child:
* string configuration
- * u_int ephemeral_key_follows
- * bignum e (only if ephemeral_key_follows == 1)
- * bignum n "
- * bignum d "
- * bignum iqmp "
- * bignum p "
- * bignum q "
- * string rngseed (only if OpenSSL is not self-seeded)
+ * string included_files[] {
+ * string selector
+ * string filename
+ * string contents
+ * }
+ * string rng_seed (if required)
*/
- buffer_init(&m);
- buffer_put_cstring(&m, buffer_ptr(conf));
-
-#ifdef WITH_SSH1
- if (sensitive_data.server_key != NULL &&
- sensitive_data.server_key->type == KEY_RSA1) {
- buffer_put_int(&m, 1);
- buffer_put_bignum(&m, sensitive_data.server_key->rsa->e);
- buffer_put_bignum(&m, sensitive_data.server_key->rsa->n);
- buffer_put_bignum(&m, sensitive_data.server_key->rsa->d);
- buffer_put_bignum(&m, sensitive_data.server_key->rsa->iqmp);
- buffer_put_bignum(&m, sensitive_data.server_key->rsa->p);
- buffer_put_bignum(&m, sensitive_data.server_key->rsa->q);
- } else
-#endif
- buffer_put_int(&m, 0);
-
+ if ((r = sshbuf_put_stringb(m, conf)) != 0 ||
+ (r = sshbuf_put_stringb(m, inc)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
#if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY)
- rexec_send_rng_seed(&m);
+ rexec_send_rng_seed(m);
#endif
-
- if (ssh_msg_send(fd, 0, &m) == -1)
+ if (ssh_msg_send(fd, 0, m) == -1)
fatal("%s: ssh_msg_send failed", __func__);
- buffer_free(&m);
+ sshbuf_free(m);
+ sshbuf_free(inc);
debug3("%s: done", __func__);
}
static void
-recv_rexec_state(int fd, Buffer *conf)
+recv_rexec_state(int fd, struct sshbuf *conf)
{
- Buffer m;
- char *cp;
- u_int len;
+ struct sshbuf *m, *inc;
+ u_char *cp, ver;
+ size_t len;
+ int r;
+ struct include_item *item;
debug3("%s: entering fd = %d", __func__, fd);
- buffer_init(&m);
-
- if (ssh_msg_recv(fd, &m) == -1)
+ if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if (ssh_msg_recv(fd, m) == -1)
fatal("%s: ssh_msg_recv failed", __func__);
- if (buffer_get_char(&m) != 0)
+ if ((r = sshbuf_get_u8(m, &ver)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (ver != 0)
fatal("%s: rexec version mismatch", __func__);
-
- cp = buffer_get_string(&m, &len);
- if (conf != NULL)
- buffer_append(conf, cp, len + 1);
- free(cp);
-
- if (buffer_get_int(&m)) {
-#ifdef WITH_SSH1
- if (sensitive_data.server_key != NULL)
- key_free(sensitive_data.server_key);
- sensitive_data.server_key = key_new_private(KEY_RSA1);
- buffer_get_bignum(&m, sensitive_data.server_key->rsa->e);
- buffer_get_bignum(&m, sensitive_data.server_key->rsa->n);
- buffer_get_bignum(&m, sensitive_data.server_key->rsa->d);
- buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp);
- buffer_get_bignum(&m, sensitive_data.server_key->rsa->p);
- buffer_get_bignum(&m, sensitive_data.server_key->rsa->q);
- if (rsa_generate_additional_parameters(
- sensitive_data.server_key->rsa) != 0)
- fatal("%s: rsa_generate_additional_parameters "
- "error", __func__);
-#else
- fatal("ssh1 not supported");
-#endif
- }
+ 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));
#if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY)
- rexec_recv_rng_seed(&m);
+ rexec_recv_rng_seed(m);
#endif
- buffer_free(&m);
+ if (conf != NULL && (r = sshbuf_put(conf, cp, len)))
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
+ while (sshbuf_len(inc) != 0) {
+ item = xcalloc(1, sizeof(*item));
+ if ((item->contents = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ 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));
+ TAILQ_INSERT_TAIL(&includes, item, entry);
+ }
+
+ free(cp);
+ sshbuf_free(m);
debug3("%s: done", __func__);
}
@@ -1116,14 +968,9 @@ server_accept_inetd(int *sock_in, int *sock_out)
{
int fd;
- startup_pipe = -1;
if (rexeced_flag) {
close(REEXEC_CONFIG_PASS_FD);
*sock_in = *sock_out = dup(STDIN_FILENO);
- if (!debug_flag) {
- startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
- close(REEXEC_STARTUP_PIPE_FD);
- }
} else {
*sock_in = dup(STDIN_FILENO);
*sock_out = dup(STDOUT_FILENO);
@@ -1148,13 +995,13 @@ server_accept_inetd(int *sock_in, int *sock_out)
* Listen for TCP connections
*/
static void
-server_listen(void)
+listen_on_addrs(struct listenaddr *la)
{
- int ret, listen_sock, on = 1;
+ int ret, listen_sock;
struct addrinfo *ai;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
- for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
+ for (ai = la->addrs; ai; ai = ai->ai_next) {
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
continue;
if (num_listen_socks >= MAX_LISTEN_SOCKS)
@@ -1170,7 +1017,7 @@ server_listen(void)
/* Create socket for listening. */
listen_sock = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
- if (listen_sock < 0) {
+ if (listen_sock == -1) {
/* kernel may not support ipv6 */
verbose("socket: %.100s", strerror(errno));
continue;
@@ -1179,13 +1026,18 @@ server_listen(void)
close(listen_sock);
continue;
}
- /*
- * Set socket options.
- * Allow local port reuse in TIME_WAIT.
- */
- if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
- &on, sizeof(on)) == -1)
- error("setsockopt SO_REUSEADDR: %s", strerror(errno));
+ if (fcntl(listen_sock, F_SETFD, FD_CLOEXEC) == -1) {
+ verbose("socket: CLOEXEC: %s", strerror(errno));
+ close(listen_sock);
+ continue;
+ }
+ /* Socket options */
+ set_reuseaddr(listen_sock);
+ if (la->rdomain != NULL &&
+ set_rdomain(listen_sock, la->rdomain) == -1) {
+ close(listen_sock);
+ continue;
+ }
/* Only communicate in IPv6 over AF_INET6 sockets. */
if (ai->ai_family == AF_INET6)
@@ -1194,7 +1046,7 @@ server_listen(void)
debug("Bind to port %s on %s.", strport, ntop);
/* Bind the socket to the desired port. */
- if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) {
+ if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) == -1) {
error("Bind to port %s on %s failed: %.200s.",
strport, ntop, strerror(errno));
close(listen_sock);
@@ -1204,12 +1056,31 @@ server_listen(void)
num_listen_socks++;
/* Start listening on the port. */
- if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0)
+ if (listen(listen_sock, SSH_LISTEN_BACKLOG) == -1)
fatal("listen on [%s]:%s: %.100s",
ntop, strport, strerror(errno));
- logit("Server listening on %s port %s.", ntop, strport);
+ logit("Server listening on %s port %s%s%s.",
+ ntop, strport,
+ la->rdomain == NULL ? "" : " rdomain ",
+ la->rdomain == NULL ? "" : la->rdomain);
+ }
+}
+
+static void
+server_listen(void)
+{
+ u_int i;
+
+ for (i = 0; i < options.num_listen_addrs; i++) {
+ listen_on_addrs(&options.listen_addrs[i]);
+ freeaddrinfo(options.listen_addrs[i].addrs);
+ free(options.listen_addrs[i].rdomain);
+ memset(&options.listen_addrs[i], 0,
+ sizeof(options.listen_addrs[i]));
}
- freeaddrinfo(options.listen_addrs);
+ free(options.listen_addrs);
+ options.listen_addrs = NULL;
+ options.num_listen_addrs = 0;
if (!num_listen_socks)
fatal("Cannot bind any address.");
@@ -1224,8 +1095,9 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
{
fd_set *fdset;
int i, j, ret, maxfd;
- int key_used = 0, startups = 0;
+ int ostartups = -1, startups = 0, listening = 0, lameduck = 0;
int startup_p[2] = { -1 , -1 };
+ char c = 0;
struct sockaddr_storage from;
socklen_t fromlen;
pid_t pid;
@@ -1237,8 +1109,9 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
for (i = 0; i < num_listen_socks; i++)
if (listen_socks[i] > maxfd)
maxfd = listen_socks[i];
- /* pipes connected to unauthenticated childs */
+ /* pipes connected to unauthenticated child sshd processes */
startup_pipes = xcalloc(options.max_startups, sizeof(int));
+ startup_flags = xcalloc(options.max_startups, sizeof(int));
for (i = 0; i < options.max_startups; i++)
startup_pipes[i] = -1;
@@ -1247,11 +1120,23 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
* the daemon is killed with a signal.
*/
for (;;) {
- if (received_sighup)
- sighup_restart();
- if (fdset != NULL)
- free(fdset);
- fdset = (fd_set *)xcalloc(howmany(maxfd + 1, NFDBITS),
+ if (ostartups != startups) {
+ setproctitle("%s [listener] %d of %d-%d startups",
+ listener_proctitle, startups,
+ options.max_startups_begin, options.max_startups);
+ ostartups = startups;
+ }
+ if (received_sighup) {
+ if (!lameduck) {
+ debug("Received SIGHUP; waiting for children");
+ close_listen_socks();
+ lameduck = 1;
+ }
+ if (listening <= 0)
+ sighup_restart();
+ }
+ free(fdset);
+ fdset = xcalloc(howmany(maxfd + 1, NFDBITS),
sizeof(fd_mask));
for (i = 0; i < num_listen_socks; i++)
@@ -1262,7 +1147,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
/* Wait in select until there is a connection. */
ret = select(maxfd+1, fdset, NULL, NULL, NULL);
- if (ret < 0 && errno != EINTR)
+ if (ret == -1 && errno != EINTR)
error("select: %.100s", strerror(errno));
if (received_sigterm) {
logit("Received signal %d; terminating.",
@@ -1272,34 +1157,47 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
unlink(options.pid_file);
exit(received_sigterm == SIGTERM ? 0 : 255);
}
- if (key_used && key_do_regen) {
- generate_ephemeral_server_key();
- key_used = 0;
- key_do_regen = 0;
- }
- if (ret < 0)
+ if (ret == -1)
continue;
- for (i = 0; i < options.max_startups; i++)
- if (startup_pipes[i] != -1 &&
- FD_ISSET(startup_pipes[i], fdset)) {
- /*
- * the read end of the pipe is ready
- * if the child has closed the pipe
- * after successful authentication
- * or if the child has died
- */
+ for (i = 0; i < options.max_startups; i++) {
+ if (startup_pipes[i] == -1 ||
+ !FD_ISSET(startup_pipes[i], fdset))
+ continue;
+ switch (read(startup_pipes[i], &c, sizeof(c))) {
+ case -1:
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ if (errno != EPIPE) {
+ error("%s: startup pipe %d (fd=%d): "
+ "read %s", __func__, i,
+ startup_pipes[i], strerror(errno));
+ }
+ /* FALLTHROUGH */
+ case 0:
+ /* child exited or completed auth */
close(startup_pipes[i]);
startup_pipes[i] = -1;
startups--;
+ if (startup_flags[i])
+ listening--;
+ break;
+ case 1:
+ /* child has finished preliminaries */
+ if (startup_flags[i]) {
+ listening--;
+ startup_flags[i] = 0;
+ }
+ break;
}
+ }
for (i = 0; i < num_listen_socks; i++) {
if (!FD_ISSET(listen_socks[i], fdset))
continue;
fromlen = sizeof(from);
*newsock = accept(listen_socks[i],
(struct sockaddr *)&from, &fromlen);
- if (*newsock < 0) {
+ if (*newsock == -1) {
if (errno != EINTR && errno != EWOULDBLOCK &&
errno != ECONNABORTED && errno != EAGAIN)
error("accept: %.100s",
@@ -1313,7 +1211,18 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
continue;
}
if (drop_connection(startups) == 1) {
- debug("drop connection #%d", startups);
+ 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;
}
@@ -1338,6 +1247,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
if (maxfd < startup_p[0])
maxfd = startup_p[0];
startups++;
+ startup_flags[j] = 1;
break;
}
@@ -1360,11 +1270,10 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
startup_pipe = -1;
pid = getpid();
if (rexec_flag) {
- send_rexec_state(config_s[0],
- &cfg);
+ send_rexec_state(config_s[0], cfg);
close(config_s[0]);
}
- break;
+ return;
}
/*
@@ -1373,13 +1282,14 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
* parent continues listening.
*/
platform_pre_fork();
+ listening++;
if ((pid = fork()) == 0) {
/*
* Child. Close the listening and
* max_startup sockets. Start using
* the accepted socket. Reinitialize
* logging (since our pid has changed).
- * We break out of the loop to handle
+ * We return from this function to handle
* the connection.
*/
platform_post_fork_child();
@@ -1394,12 +1304,23 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
log_stderr);
if (rexec_flag)
close(config_s[0]);
- break;
+ else {
+ /*
+ * Signal parent that the preliminaries
+ * for this child are complete. For the
+ * re-exec case, this happens after the
+ * child has received the rexec state
+ * from the server.
+ */
+ (void)atomicio(vwrite, startup_pipe,
+ "\0", 1);
+ }
+ return;
}
/* Parent. Stay in the loop. */
platform_post_fork_parent(pid);
- if (pid < 0)
+ if (pid == -1)
error("fork: %.100s", strerror(errno));
else
debug("Forked child %ld.", (long)pid);
@@ -1407,23 +1328,10 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
close(startup_p[1]);
if (rexec_flag) {
- send_rexec_state(config_s[0], &cfg);
+ send_rexec_state(config_s[0], cfg);
close(config_s[0]);
close(config_s[1]);
}
-
- /*
- * Mark that the key has been used (it
- * was "given" to the child).
- */
- if ((options.protocol & SSH_PROTO_1) &&
- key_used == 0) {
- /* Schedule server key regeneration alarm. */
- signal(SIGALRM, key_regeneration_alarm);
- alarm(options.key_regeneration_time);
- key_used = 1;
- }
-
close(*newsock);
/*
@@ -1439,13 +1347,138 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
#endif
explicit_bzero(rnd, sizeof(rnd));
}
+ }
+}
- /* child process check (or debug mode) */
- if (num_listen_socks < 0)
- break;
+/*
+ * If IP options are supported, make sure there are none (log and
+ * return an error if any are found). Basically we are worried about
+ * source routing; it can be used to pretend you are somebody
+ * (ip-address) you are not. That itself may be "almost acceptable"
+ * under certain circumstances, but rhosts authentication is useless
+ * if source routing is accepted. Notice also that if we just dropped
+ * source routing here, the other side could use IP spoofing to do
+ * rest of the interaction and could still bypass security. So we
+ * exit here if we detect any IP options.
+ */
+static void
+check_ip_options(struct ssh *ssh)
+{
+#ifdef IP_OPTIONS
+ int sock_in = ssh_packet_get_connection_in(ssh);
+ struct sockaddr_storage from;
+ u_char opts[200];
+ socklen_t i, option_size = sizeof(opts), fromlen = sizeof(from);
+ char text[sizeof(opts) * 3 + 1];
+
+ memset(&from, 0, sizeof(from));
+ if (getpeername(sock_in, (struct sockaddr *)&from,
+ &fromlen) == -1)
+ return;
+ if (from.ss_family != AF_INET)
+ return;
+ /* XXX IPv6 options? */
+
+ if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts,
+ &option_size) >= 0 && option_size != 0) {
+ text[0] = '\0';
+ for (i = 0; i < option_size; i++)
+ snprintf(text + i*3, sizeof(text) - i*3,
+ " %2.2x", opts[i]);
+ fatal("Connection from %.100s port %d with IP opts: %.800s",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), text);
+ }
+ return;
+#endif /* IP_OPTIONS */
+}
+
+/* Set the routing domain for this process */
+static void
+set_process_rdomain(struct ssh *ssh, const char *name)
+{
+#if defined(HAVE_SYS_SET_PROCESS_RDOMAIN)
+ if (name == NULL)
+ return; /* default */
+
+ if (strcmp(name, "%D") == 0) {
+ /* "expands" to routing domain of connection */
+ if ((name = ssh_packet_rdomain_in(ssh)) == NULL)
+ return;
+ }
+ /* NB. We don't pass 'ssh' to sys_set_process_rdomain() */
+ return sys_set_process_rdomain(name);
+#elif defined(__OpenBSD__)
+ int rtable, ortable = getrtable();
+ const char *errstr;
+
+ if (name == NULL)
+ return; /* default */
+
+ if (strcmp(name, "%D") == 0) {
+ /* "expands" to routing domain of connection */
+ if ((name = ssh_packet_rdomain_in(ssh)) == NULL)
+ return;
+ }
+
+ rtable = (int)strtonum(name, 0, 255, &errstr);
+ if (errstr != NULL) /* Shouldn't happen */
+ fatal("Invalid routing domain \"%s\": %s", name, errstr);
+ if (rtable != ortable && setrtable(rtable) != 0)
+ fatal("Unable to set routing domain %d: %s",
+ rtable, strerror(errno));
+ debug("%s: set routing domain %d (was %d)", __func__, rtable, ortable);
+#else /* defined(__OpenBSD__) */
+ fatal("Unable to set routing domain: not supported in this platform");
+#endif
+}
+
+static void
+accumulate_host_timing_secret(struct sshbuf *server_cfg,
+ struct sshkey *key)
+{
+ static struct ssh_digest_ctx *ctx;
+ u_char *hash;
+ size_t len;
+ struct sshbuf *buf;
+ int r;
+
+ if (ctx == NULL && (ctx = ssh_digest_start(SSH_DIGEST_SHA512)) == NULL)
+ fatal("%s: ssh_digest_start", __func__);
+ if (key == NULL) { /* finalize */
+ /* add server config in case we are using agent for host keys */
+ if (ssh_digest_update(ctx, sshbuf_ptr(server_cfg),
+ sshbuf_len(server_cfg)) != 0)
+ fatal("%s: ssh_digest_update", __func__);
+ len = ssh_digest_bytes(SSH_DIGEST_SHA512);
+ hash = xmalloc(len);
+ if (ssh_digest_final(ctx, hash, len) != 0)
+ fatal("%s: ssh_digest_final", __func__);
+ options.timing_secret = PEEK_U64(hash);
+ freezero(hash, len);
+ ssh_digest_free(ctx);
+ ctx = NULL;
+ return;
}
+ if ((buf = sshbuf_new()) == NULL)
+ fatal("%s could not allocate buffer", __func__);
+ if ((r = sshkey_private_serialize(key, buf)) != 0)
+ fatal("sshkey_private_serialize: %s", ssh_err(r));
+ if (ssh_digest_update(ctx, sshbuf_ptr(buf), sshbuf_len(buf)) != 0)
+ fatal("%s: ssh_digest_update", __func__);
+ sshbuf_reset(buf);
+ sshbuf_free(buf);
}
+static char *
+prepare_proctitle(int ac, char **av)
+{
+ char *ret = NULL;
+ int i;
+
+ for (i = 0; i < ac; i++)
+ xextendf(&ret, " ", "%s", av[i]);
+ return ret;
+}
/*
* Main program for the daemon.
@@ -1453,22 +1486,22 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
int
main(int ac, char **av)
{
+ struct ssh *ssh = NULL;
extern char *optarg;
extern int optind;
- int r, opt, i, j, on = 1;
+ int r, opt, on = 1, already_daemon, remote_port;
int sock_in = -1, sock_out = -1, newsock = -1;
- const char *remote_ip;
- int remote_port;
- char *fp, *line, *logfile = NULL;
+ const char *remote_ip, *rdomain;
+ char *fp, *line, *laddr, *logfile = NULL;
int config_s[2] = { -1 , -1 };
- u_int n;
+ u_int i, j;
u_int64_t ibytes, obytes;
mode_t new_umask;
- Key *key;
- Key *pubkey;
+ struct sshkey *key;
+ struct sshkey *pubkey;
int keytype;
Authctxt *authctxt;
- struct connection_info *connection_info = get_connection_info(0, 0);
+ struct connection_info *connection_info = NULL;
#ifdef HAVE_SECUREWARE
(void)set_auth_parameters(ac, av);
@@ -1479,7 +1512,7 @@ main(int ac, char **av)
saved_argc = ac;
rexec_argc = ac;
saved_argv = xcalloc(ac + 1, sizeof(*saved_argv));
- for (i = 0; i < ac; i++)
+ for (i = 0; (int)i < ac; i++)
saved_argv[i] = xstrdup(av[i]);
saved_argv[i] = NULL;
@@ -1495,11 +1528,14 @@ main(int ac, char **av)
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
+ seed_rng();
+
/* Initialize configuration options to their default values. */
initialize_server_options(&options);
/* Parse command-line arguments. */
- while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeE:iqrtQRT46")) != -1) {
+ while ((opt = getopt(ac, av,
+ "C:E:b:c:f:g:h:k:o:p:u:46DQRTdeiqrt")) != -1) {
switch (opt) {
case '4':
options.address_family = AF_INET;
@@ -1511,12 +1547,8 @@ main(int ac, char **av)
config_file_name = optarg;
break;
case 'c':
- if (options.num_host_cert_files >= MAX_HOSTCERTS) {
- fprintf(stderr, "too many host certificates.\n");
- exit(1);
- }
- options.host_cert_files[options.num_host_cert_files++] =
- derelativise_path(optarg);
+ servconf_add_hostcert("[command-line]", 0,
+ &options, optarg);
break;
case 'd':
if (debug_flag == 0) {
@@ -1529,7 +1561,7 @@ main(int ac, char **av)
no_daemon_flag = 1;
break;
case 'E':
- logfile = xstrdup(optarg);
+ logfile = optarg;
/* FALLTHROUGH */
case 'e':
log_stderr = 1;
@@ -1551,8 +1583,7 @@ main(int ac, char **av)
options.log_level = SYSLOG_LEVEL_QUIET;
break;
case 'b':
- options.server_key_bits = (int)strtonum(optarg, 256,
- 32768, NULL);
+ /* protocol 1, ignored */
break;
case 'p':
options.ports_from_cmdline = 1;
@@ -1573,18 +1604,11 @@ main(int ac, char **av)
}
break;
case 'k':
- if ((options.key_regeneration_time = convtime(optarg)) == -1) {
- fprintf(stderr, "Invalid key regeneration interval.\n");
- exit(1);
- }
+ /* protocol 1, ignored */
break;
case 'h':
- if (options.num_host_key_files >= MAX_HOSTKEYS) {
- fprintf(stderr, "too many host keys.\n");
- exit(1);
- }
- options.host_key_files[options.num_host_key_files++] =
- derelativise_path(optarg);
+ servconf_add_hostkey("[command-line]", 0,
+ &options, optarg, 1);
break;
case 't':
test_flag = 1;
@@ -1593,6 +1617,7 @@ main(int ac, char **av)
test_flag = 2;
break;
case 'C':
+ connection_info = get_connection_info(ssh, 0, 0);
if (parse_server_match_testspec(connection_info,
optarg) == -1)
exit(1);
@@ -1607,7 +1632,7 @@ main(int ac, char **av)
case 'o':
line = xstrdup(optarg);
if (process_server_config_line(&options, line,
- "command-line", 0, NULL, NULL) != 0)
+ "command-line", 0, NULL, NULL, &includes) != 0)
exit(1);
free(line);
break;
@@ -1619,22 +1644,16 @@ main(int ac, char **av)
}
if (rexeced_flag || inetd_flag)
rexec_flag = 0;
- if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/')))
+ if (!test_flag && rexec_flag && !path_absolute(av[0]))
fatal("sshd re-exec requires execution with an absolute path");
if (rexeced_flag)
closefrom(REEXEC_MIN_FREE_FD);
else
closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
-#endif
-
/* If requested, redirect the logs to the specified logfile. */
- if (logfile != NULL) {
+ if (logfile != NULL)
log_redirect_stderr_to(logfile);
- free(logfile);
- }
/*
* Force logging to stderr until we have loaded the private host
* key (unless started from inetd)
@@ -1644,7 +1663,7 @@ main(int ac, char **av)
SYSLOG_LEVEL_INFO : options.log_level,
options.log_facility == SYSLOG_FACILITY_NOT_SET ?
SYSLOG_FACILITY_AUTH : options.log_facility,
- log_stderr || !inetd_flag);
+ log_stderr || !inetd_flag || debug_flag);
/*
* Unset KRB5CCNAME, otherwise the user's session may inherit it from
@@ -1653,41 +1672,35 @@ main(int ac, char **av)
if (getenv("KRB5CCNAME") != NULL)
(void) unsetenv("KRB5CCNAME");
-#ifdef _UNICOS
- /* Cray can define user privs drop all privs now!
- * Not needed on PRIV_SU systems!
- */
- drop_cray_privs();
-#endif
-
- sensitive_data.server_key = NULL;
- sensitive_data.ssh1_host_key = NULL;
- sensitive_data.have_ssh1_key = 0;
sensitive_data.have_ssh2_key = 0;
/*
- * If we're doing an extended config test, make sure we have all of
- * the parameters we need. If we're not doing an extended test,
- * do not silently ignore connection test params.
+ * If we're not doing an extended test do not silently ignore connection
+ * test params.
*/
- if (test_flag >= 2 && server_match_spec_complete(connection_info) == 0)
- fatal("user, host and addr are all required when testing "
- "Match configs");
- if (test_flag < 2 && server_match_spec_complete(connection_info) >= 0)
+ if (test_flag < 2 && connection_info != NULL)
fatal("Config test connection parameter (-C) provided without "
"test mode (-T)");
/* Fetch our configuration */
- buffer_init(&cfg);
- if (rexeced_flag)
- recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg);
- else
- load_server_config(config_file_name, &cfg);
+ if ((cfg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if (rexeced_flag) {
+ recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg);
+ if (!debug_flag) {
+ startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
+ close(REEXEC_STARTUP_PIPE_FD);
+ /*
+ * Signal parent that this child is at a point where
+ * they can go away if they have a SIGHUP pending.
+ */
+ (void)atomicio(vwrite, startup_pipe, "\0", 1);
+ }
+ } else if (strcasecmp(config_file_name, "none") != 0)
+ load_server_config(config_file_name, cfg);
parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
- &cfg, NULL);
-
- seed_rng();
+ cfg, &includes, NULL);
/* Fill in default values for those options not explicitly set. */
fill_default_server_options(&options);
@@ -1702,6 +1715,11 @@ main(int ac, char **av)
strcasecmp(options.authorized_keys_command, "none") != 0))
fatal("AuthorizedKeysCommand set without "
"AuthorizedKeysCommandUser");
+ if (options.authorized_principals_command_user == NULL &&
+ (options.authorized_principals_command != NULL &&
+ strcasecmp(options.authorized_principals_command, "none") != 0))
+ fatal("AuthorizedPrincipalsCommand set without "
+ "AuthorizedPrincipalsCommandUser");
/*
* Check whether there is any path through configured auth methods.
@@ -1710,22 +1728,16 @@ main(int ac, char **av)
* and warns for trivial misconfigurations that could break login.
*/
if (options.num_auth_methods != 0) {
- if ((options.protocol & SSH_PROTO_1))
- fatal("AuthenticationMethods is not supported with "
- "SSH protocol 1");
- for (n = 0; n < options.num_auth_methods; n++) {
- if (auth2_methods_valid(options.auth_methods[n],
+ for (i = 0; i < options.num_auth_methods; i++) {
+ if (auth2_methods_valid(options.auth_methods[i],
1) == 0)
break;
}
- if (n >= options.num_auth_methods)
+ if (i >= options.num_auth_methods)
fatal("AuthenticationMethods cannot be satisfied by "
"enabled authentication methods");
}
- /* set default channel AF */
- channel_set_af(options.address_family);
-
/* Check that there are no remaining arguments. */
if (optind < ac) {
fprintf(stderr, "Extra argument %s.\n", av[optind]);
@@ -1734,26 +1746,21 @@ main(int ac, char **av)
debug("sshd version %s, %s", SSH_VERSION,
#ifdef WITH_OPENSSL
- SSLeay_version(SSLEAY_VERSION)
+ OpenSSL_version(OPENSSL_VERSION)
#else
"without OpenSSL"
#endif
);
/* Store privilege separation user for later use if required. */
+ privsep_chroot = use_privsep && (getuid() == 0 || geteuid() == 0);
if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {
- if (use_privsep || options.kerberos_authentication)
+ if (privsep_chroot || options.kerberos_authentication)
fatal("Privilege separation user %s does not exist",
SSH_PRIVSEP_USER);
} else {
- if (privsep_pw->pw_passwd != NULL) {
- explicit_bzero(privsep_pw->pw_passwd,
- strlen(privsep_pw->pw_passwd));
- }
privsep_pw = pwcopy(privsep_pw);
- if (privsep_pw->pw_passwd != NULL) {
- free(privsep_pw->pw_passwd);
- }
+ freezero(privsep_pw->pw_passwd, strlen(privsep_pw->pw_passwd));
privsep_pw->pw_passwd = xstrdup("*");
}
#if !defined(ANDROID)
@@ -1762,9 +1769,9 @@ main(int ac, char **av)
/* load host keys */
sensitive_data.host_keys = xcalloc(options.num_host_key_files,
- sizeof(Key *));
+ sizeof(struct sshkey *));
sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files,
- sizeof(Key *));
+ sizeof(struct sshkey *));
if (options.host_key_agent) {
if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME))
@@ -1778,24 +1785,48 @@ main(int ac, char **av)
}
for (i = 0; i < options.num_host_key_files; i++) {
+ int ll = options.host_key_file_userprovided[i] ?
+ SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_DEBUG1;
+
if (options.host_key_files[i] == NULL)
continue;
- key = key_load_private(options.host_key_files[i], "", NULL);
- pubkey = key_load_public(options.host_key_files[i], NULL);
+ if ((r = sshkey_load_private(options.host_key_files[i], "",
+ &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR)
+ do_log2(ll, "Unable to load host key \"%s\": %s",
+ options.host_key_files[i], ssh_err(r));
+ if (sshkey_is_sk(key) &&
+ key->sk_flags & SSH_SK_USER_PRESENCE_REQD) {
+ debug("host key %s requires user presence, ignoring",
+ options.host_key_files[i]);
+ key->sk_flags &= ~SSH_SK_USER_PRESENCE_REQD;
+ }
+ if (r == 0 && key != NULL &&
+ (r = sshkey_shield_private(key)) != 0) {
+ do_log2(ll, "Unable to shield host key \"%s\": %s",
+ options.host_key_files[i], ssh_err(r));
+ 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)
- pubkey = key_demote(key);
+ if ((r = sshkey_from_private(key, &pubkey)) != 0)
+ fatal("Could not demote key: \"%s\": %s",
+ options.host_key_files[i], ssh_err(r));
sensitive_data.host_keys[i] = key;
sensitive_data.host_pubkeys[i] = pubkey;
- if (key == NULL && pubkey != NULL && pubkey->type != KEY_RSA1 &&
- have_agent) {
+ if (key == NULL && pubkey != NULL && have_agent) {
debug("will rely on agent for hostkey %s",
options.host_key_files[i]);
keytype = pubkey->type;
} else if (key != NULL) {
keytype = key->type;
+ accumulate_host_timing_secret(cfg, key);
} else {
- error("Could not load host key: %s",
+ do_log2(ll, "Unable to load host key: %s",
options.host_key_files[i]);
sensitive_data.host_keys[i] = NULL;
sensitive_data.host_pubkeys[i] = NULL;
@@ -1803,14 +1834,13 @@ main(int ac, char **av)
}
switch (keytype) {
- case KEY_RSA1:
- sensitive_data.ssh1_host_key = key;
- sensitive_data.have_ssh1_key = 1;
- break;
case KEY_RSA:
case KEY_DSA:
case KEY_ECDSA:
case KEY_ED25519:
+ case KEY_ECDSA_SK:
+ case KEY_ED25519_SK:
+ case KEY_XMSS:
if (have_agent || key != NULL)
sensitive_data.have_ssh2_key = 1;
break;
@@ -1819,19 +1849,11 @@ main(int ac, char **av)
SSH_FP_DEFAULT)) == NULL)
fatal("sshkey_fingerprint failed");
debug("%s host key #%d: %s %s",
- key ? "private" : "agent", i, keytype == KEY_RSA1 ?
- sshkey_type(pubkey) : sshkey_ssh_name(pubkey), fp);
+ key ? "private" : "agent", i, sshkey_ssh_name(pubkey), fp);
free(fp);
}
- if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {
- logit("Disabling protocol version 1. Could not load host key");
- options.protocol &= ~SSH_PROTO_1;
- }
- if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
- logit("Disabling protocol version 2. Could not load host key");
- options.protocol &= ~SSH_PROTO_2;
- }
- if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
+ accumulate_host_timing_secret(cfg, NULL);
+ if (!sensitive_data.have_ssh2_key) {
logit("sshd: no hostkeys available -- exiting.");
exit(1);
}
@@ -1841,28 +1863,28 @@ main(int ac, char **av)
* indices to the public keys that they relate to.
*/
sensitive_data.host_certificates = xcalloc(options.num_host_key_files,
- sizeof(Key *));
+ sizeof(struct sshkey *));
for (i = 0; i < options.num_host_key_files; i++)
sensitive_data.host_certificates[i] = NULL;
for (i = 0; i < options.num_host_cert_files; i++) {
if (options.host_cert_files[i] == NULL)
continue;
- key = key_load_public(options.host_cert_files[i], NULL);
- if (key == NULL) {
- error("Could not load host certificate: %s",
- options.host_cert_files[i]);
+ if ((r = sshkey_load_public(options.host_cert_files[i],
+ &key, NULL)) != 0) {
+ error("Could not load host certificate \"%s\": %s",
+ options.host_cert_files[i], ssh_err(r));
continue;
}
- if (!key_is_cert(key)) {
+ if (!sshkey_is_cert(key)) {
error("Certificate file is not a certificate: %s",
options.host_cert_files[i]);
- key_free(key);
+ sshkey_free(key);
continue;
}
/* Find matching private key */
for (j = 0; j < options.num_host_key_files; j++) {
- if (key_equal_public(key,
+ if (sshkey_equal_public(key,
sensitive_data.host_keys[j])) {
sensitive_data.host_certificates[j] = key;
break;
@@ -1871,42 +1893,15 @@ main(int ac, char **av)
if (j >= options.num_host_key_files) {
error("No matching private key for certificate: %s",
options.host_cert_files[i]);
- key_free(key);
+ sshkey_free(key);
continue;
}
sensitive_data.host_certificates[j] = key;
- debug("host certificate: #%d type %d %s", j, key->type,
- key_type(key));
- }
-
-#ifdef WITH_SSH1
- /* Check certain values for sanity. */
- if (options.protocol & SSH_PROTO_1) {
- if (options.server_key_bits < 512 ||
- options.server_key_bits > 32768) {
- fprintf(stderr, "Bad server key size.\n");
- exit(1);
- }
- /*
- * Check that server and host key lengths differ sufficiently. This
- * is necessary to make double encryption work with rsaref. Oh, I
- * hate software patents. I dont know if this can go? Niels
- */
- if (options.server_key_bits >
- BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) -
- SSH_KEY_BITS_RESERVED && options.server_key_bits <
- BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
- SSH_KEY_BITS_RESERVED) {
- options.server_key_bits =
- BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
- SSH_KEY_BITS_RESERVED;
- debug("Forcing server key to %d bits to make it differ from host key.",
- options.server_key_bits);
- }
+ debug("host certificate: #%u type %d %s", j, key->type,
+ sshkey_type(key));
}
-#endif
- if (use_privsep) {
+ if (privsep_chroot) {
struct stat st;
if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) ||
@@ -1926,8 +1921,14 @@ main(int ac, char **av)
}
if (test_flag > 1) {
- if (server_match_spec_complete(connection_info) == 1)
- parse_server_match_config(&options, connection_info);
+ /*
+ * If no connection info was provided by -C then use
+ * use a blank one that will cause no predicate to match.
+ */
+ if (connection_info == NULL)
+ connection_info = get_connection_info(ssh, 0, 0);
+ connection_info->test = 1;
+ parse_server_match_config(&options, &includes, connection_info);
dump_config(&options);
}
@@ -1946,14 +1947,17 @@ main(int ac, char **av)
debug("setgroups() failed: %.200s", strerror(errno));
if (rexec_flag) {
+ if (rexec_argc < 0)
+ fatal("rexec_argc %d < 0", rexec_argc);
rexec_argv = xcalloc(rexec_argc + 2, sizeof(char *));
- for (i = 0; i < rexec_argc; i++) {
+ for (i = 0; i < (u_int)rexec_argc; i++) {
debug("rexec_argv[%d]='%s'", i, saved_argv[i]);
rexec_argv[i] = saved_argv[i];
}
rexec_argv[rexec_argc] = "-R";
rexec_argv[rexec_argc + 1] = NULL;
}
+ listener_proctitle = prepare_proctitle(ac, av);
/* Ensure that umask disallows at least group and world write */
new_umask = umask(0077) | 0022;
@@ -1965,25 +1969,17 @@ main(int ac, char **av)
log_init(__progname, options.log_level, options.log_facility, log_stderr);
/*
- * If not in debugging mode, and not started from inetd, disconnect
- * from the controlling terminal, and fork. The original process
- * exits.
+ * If not in debugging mode, not started from inetd and not already
+ * daemonized (eg re-exec via SIGHUP), disconnect from the controlling
+ * terminal, and fork. The original process exits.
*/
- if (!(debug_flag || inetd_flag || no_daemon_flag)) {
-#ifdef TIOCNOTTY
- int fd;
-#endif /* TIOCNOTTY */
- if (daemon(0, 0) < 0)
+ already_daemon = daemonized();
+ if (!(debug_flag || inetd_flag || no_daemon_flag || already_daemon)) {
+
+ if (daemon(0, 0) == -1)
fatal("daemon() failed: %.200s", strerror(errno));
- /* Disconnect from the controlling tty. */
-#ifdef TIOCNOTTY
- fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
- if (fd >= 0) {
- (void) ioctl(fd, TIOCNOTTY, NULL);
- close(fd);
- }
-#endif /* TIOCNOTTY */
+ disconnect_controlling_tty();
}
/* Reinitialize the log (because of the fork above). */
log_init(__progname, options.log_level, options.log_facility, log_stderr);
@@ -1994,7 +1990,7 @@ main(int ac, char **av)
error("chdir(\"/\"): %s", strerror(errno));
/* ignore SIGPIPE */
- signal(SIGPIPE, SIG_IGN);
+ ssh_signal(SIGPIPE, SIG_IGN);
/* Get a connection, either from inetd or a listening TCP socket */
if (inetd_flag) {
@@ -2003,13 +1999,10 @@ main(int ac, char **av)
platform_pre_listen();
server_listen();
- if (options.protocol & SSH_PROTO_1)
- generate_ephemeral_server_key();
-
- signal(SIGHUP, sighup_handler);
- signal(SIGCHLD, main_sigchld_handler);
- signal(SIGTERM, sigterm_handler);
- signal(SIGQUIT, sigterm_handler);
+ ssh_signal(SIGHUP, sighup_handler);
+ ssh_signal(SIGCHLD, main_sigchld_handler);
+ ssh_signal(SIGTERM, sigterm_handler);
+ ssh_signal(SIGQUIT, sigterm_handler);
/*
* Write out the pid file after the sigterm handler
@@ -2046,7 +2039,7 @@ main(int ac, char **av)
* controlling terminal which will result in "could not set
* controlling tty" errors.
*/
- if (!debug_flag && !inetd_flag && setsid() < 0)
+ if (!debug_flag && !inetd_flag && setsid() == -1)
error("setsid: %.100s", strerror(errno));
#endif
@@ -2093,56 +2086,64 @@ main(int ac, char **av)
fcntl(sock_out, F_SETFD, FD_CLOEXEC);
fcntl(sock_in, F_SETFD, FD_CLOEXEC);
- /*
- * Disable the key regeneration alarm. We will not regenerate the
- * key since we are no longer in a position to give it to anyone. We
- * will not restart on SIGHUP since it no longer makes sense.
- */
- alarm(0);
- signal(SIGALRM, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGCHLD, SIG_DFL);
- signal(SIGINT, SIG_DFL);
+ /* We will not restart on SIGHUP since it no longer makes sense. */
+ ssh_signal(SIGALRM, SIG_DFL);
+ ssh_signal(SIGHUP, SIG_DFL);
+ ssh_signal(SIGTERM, SIG_DFL);
+ ssh_signal(SIGQUIT, SIG_DFL);
+ ssh_signal(SIGCHLD, SIG_DFL);
+ ssh_signal(SIGINT, SIG_DFL);
/*
* Register our connection. This turns encryption off because we do
* not have a key.
*/
- packet_set_connection(sock_in, sock_out);
- packet_set_server();
+ if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL)
+ fatal("Unable to create connection");
+ the_active_state = ssh;
+ ssh_packet_set_server(ssh);
+
+ check_ip_options(ssh);
+
+ /* Prepare the channels layer */
+ channel_init_channels(ssh);
+ channel_set_af(ssh, options.address_family);
+ process_permitopen(ssh, &options);
/* Set SO_KEEPALIVE if requested. */
- if (options.tcp_keep_alive && packet_connection_is_on_socket() &&
- setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
+ if (options.tcp_keep_alive && ssh_packet_connection_is_on_socket(ssh) &&
+ setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) == -1)
error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
- if ((remote_port = get_remote_port()) < 0) {
- debug("get_remote_port failed");
+ if ((remote_port = ssh_remote_port(ssh)) < 0) {
+ debug("ssh_remote_port failed");
cleanup_exit(255);
}
- /*
- * We use get_canonical_hostname with usedns = 0 instead of
- * get_remote_ipaddr here so IP options will be checked.
- */
- (void) get_canonical_hostname(0);
+ if (options.routing_domain != NULL)
+ set_process_rdomain(ssh, options.routing_domain);
+
/*
* The rest of the code depends on the fact that
- * get_remote_ipaddr() caches the remote ip, even if
+ * ssh_remote_ipaddr() caches the remote ip, even if
* the socket goes away.
*/
- remote_ip = get_remote_ipaddr();
+ remote_ip = ssh_remote_ipaddr(ssh);
#ifdef SSH_AUDIT_EVENTS
audit_connection_from(remote_ip, remote_port);
#endif
+ rdomain = ssh_packet_rdomain_in(ssh);
+
/* Log the connection. */
- verbose("Connection from %s port %d on %s port %d",
- remote_ip, remote_port,
- get_local_ipaddr(sock_in), get_local_port());
+ laddr = get_local_ipaddr(sock_in);
+ verbose("Connection from %s port %d on %s port %d%s%s%s",
+ remote_ip, remote_port, laddr, ssh_local_port(ssh),
+ rdomain == NULL ? "" : " rdomain \"",
+ rdomain == NULL ? "" : rdomain,
+ rdomain == NULL ? "" : "\"");
+ free(laddr);
/*
* We don't want to listen forever unless the other side
@@ -2152,34 +2153,38 @@ main(int ac, char **av)
* mode; it is just annoying to have the server exit just when you
* are about to discover the bug.
*/
- signal(SIGALRM, grace_alarm_handler);
+ ssh_signal(SIGALRM, grace_alarm_handler);
if (!debug_flag)
alarm(options.login_grace_time);
- sshd_exchange_identification(sock_in, sock_out);
-
- /* In inetd mode, generate ephemeral key only for proto 1 connections */
- if (!compat20 && inetd_flag && sensitive_data.server_key == NULL)
- generate_ephemeral_server_key();
+ if ((r = kex_exchange_identification(ssh, -1,
+ options.version_addendum)) != 0)
+ sshpkt_fatal(ssh, r, "banner exchange");
- packet_set_nonblocking();
+ ssh_packet_set_nonblocking(ssh);
/* allocate authentication context */
authctxt = xcalloc(1, sizeof(*authctxt));
+ ssh->authctxt = authctxt;
- authctxt->loginmsg = &loginmsg;
+ authctxt->loginmsg = loginmsg;
/* XXX global for cleanup, access from other modules */
the_authctxt = authctxt;
+ /* Set default key authentication options */
+ if ((auth_opts = sshauthopt_new_with_keys_defaults()) == NULL)
+ fatal("allocation failed");
+
/* prepare buffer to collect messages to display to user after login */
- buffer_init(&loginmsg);
+ if ((loginmsg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
auth_debug_reset();
if (use_privsep) {
- if (privsep_preauth(authctxt) == 1)
+ if (privsep_preauth(ssh) == 1)
goto authenticated;
- } else if (compat20 && have_agent) {
+ } else if (have_agent) {
if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) {
error("Unable to get agent socket: %s", ssh_err(r));
have_agent = 0;
@@ -2188,23 +2193,16 @@ main(int ac, char **av)
/* perform the key exchange */
/* authenticate user and start session */
- if (compat20) {
- do_ssh2_kex();
- do_authentication2(authctxt);
- } else {
-#ifdef WITH_SSH1
- do_ssh1_kex();
- do_authentication(authctxt);
-#else
- fatal("ssh1 not supported");
-#endif
- }
+ do_ssh2_kex(ssh);
+ do_authentication2(ssh);
+
/*
* If we use privilege separation, the unprivileged child transfers
* the current keystate and exits
*/
if (use_privsep) {
- mm_send_keystate(pmonitor);
+ mm_send_keystate(ssh, pmonitor);
+ ssh_packet_clear_keys(ssh);
exit(0);
}
@@ -2214,7 +2212,7 @@ main(int ac, char **av)
* authentication.
*/
alarm(0);
- signal(SIGALRM, SIG_DFL);
+ ssh_signal(SIGALRM, SIG_DFL);
authctxt->authenticated = 1;
if (startup_pipe != -1) {
close(startup_pipe);
@@ -2222,7 +2220,7 @@ main(int ac, char **av)
}
#ifdef SSH_AUDIT_EVENTS
- audit_event(SSH_AUTH_SUCCESS);
+ audit_event(ssh, SSH_AUTH_SUCCESS);
#endif
#ifdef GSSAPI
@@ -2235,7 +2233,7 @@ main(int ac, char **av)
#ifdef USE_PAM
if (options.use_pam) {
do_pam_setcred(1);
- do_pam_session();
+ do_pam_session(ssh);
}
#endif
@@ -2244,24 +2242,21 @@ main(int ac, char **av)
* file descriptor passing.
*/
if (use_privsep) {
- privsep_postauth(authctxt);
+ privsep_postauth(ssh, authctxt);
/* the monitor process [priv] will not return */
- if (!compat20)
- destroy_sensitive_data();
}
- packet_set_timeout(options.client_alive_interval,
+ ssh_packet_set_timeout(ssh, options.client_alive_interval,
options.client_alive_count_max);
/* Try to send all our hostkeys to the client */
- if (compat20)
- notify_hostkeys(active_state);
+ notify_hostkeys(ssh);
/* Start session. */
- do_authenticated(authctxt);
+ do_authenticated(ssh, authctxt);
/* The connection has been terminated. */
- packet_get_bytes(&ibytes, &obytes);
+ ssh_packet_get_bytes(ssh, &ibytes, &obytes);
verbose("Transferred: sent %llu, received %llu bytes",
(unsigned long long)obytes, (unsigned long long)ibytes);
@@ -2273,10 +2268,10 @@ main(int ac, char **av)
#endif /* USE_PAM */
#ifdef SSH_AUDIT_EVENTS
- PRIVSEP(audit_event(SSH_CONNECTION_CLOSE));
+ PRIVSEP(audit_event(ssh, SSH_CONNECTION_CLOSE));
#endif
- packet_close();
+ ssh_packet_close(ssh);
if (use_privsep)
mm_terminate();
@@ -2284,318 +2279,95 @@ main(int ac, char **av)
exit(0);
}
-#ifdef WITH_SSH1
-/*
- * Decrypt session_key_int using our private server key and private host key
- * (key with larger modulus first).
- */
int
-ssh1_session_key(BIGNUM *session_key_int)
+sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey,
+ struct sshkey *pubkey, u_char **signature, size_t *slenp,
+ const u_char *data, size_t dlen, const char *alg)
{
- int rsafail = 0;
-
- if (BN_cmp(sensitive_data.server_key->rsa->n,
- sensitive_data.ssh1_host_key->rsa->n) > 0) {
- /* Server key has bigger modulus. */
- if (BN_num_bits(sensitive_data.server_key->rsa->n) <
- BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
- SSH_KEY_BITS_RESERVED) {
- fatal("do_connection: %s: "
- "server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
- get_remote_ipaddr(),
- BN_num_bits(sensitive_data.server_key->rsa->n),
- BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
- SSH_KEY_BITS_RESERVED);
+ int r;
+
+ if (use_privsep) {
+ if (privkey) {
+ if (mm_sshkey_sign(ssh, privkey, signature, slenp,
+ data, dlen, alg, options.sk_provider,
+ ssh->compat) < 0)
+ fatal("%s: privkey sign failed", __func__);
+ } else {
+ if (mm_sshkey_sign(ssh, pubkey, signature, slenp,
+ data, dlen, alg, options.sk_provider,
+ ssh->compat) < 0)
+ fatal("%s: pubkey sign failed", __func__);
}
- if (rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.server_key->rsa) != 0)
- rsafail++;
- if (rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.ssh1_host_key->rsa) != 0)
- rsafail++;
} else {
- /* Host key has bigger modulus (or they are equal). */
- if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
- BN_num_bits(sensitive_data.server_key->rsa->n) +
- SSH_KEY_BITS_RESERVED) {
- fatal("do_connection: %s: "
- "host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
- get_remote_ipaddr(),
- BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
- BN_num_bits(sensitive_data.server_key->rsa->n),
- SSH_KEY_BITS_RESERVED);
+ if (privkey) {
+ if (sshkey_sign(privkey, signature, slenp, data, dlen,
+ alg, options.sk_provider, ssh->compat) < 0)
+ fatal("%s: privkey sign failed", __func__);
+ } else {
+ if ((r = ssh_agent_sign(auth_sock, pubkey,
+ signature, slenp, data, dlen, alg,
+ ssh->compat)) != 0) {
+ fatal("%s: agent sign failed: %s",
+ __func__, ssh_err(r));
+ }
}
- if (rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.ssh1_host_key->rsa) != 0)
- rsafail++;
- if (rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.server_key->rsa) != 0)
- rsafail++;
- }
- return (rsafail);
-}
-
-/*
- * SSH1 key exchange
- */
-static void
-do_ssh1_kex(void)
-{
- int i, len;
- int rsafail = 0;
- BIGNUM *session_key_int, *fake_key_int, *real_key_int;
- u_char session_key[SSH_SESSION_KEY_LENGTH];
- u_char fake_key_bytes[4096 / 8];
- size_t fake_key_len;
- u_char cookie[8];
- u_int cipher_type, auth_mask, protocol_flags;
-
- /*
- * Generate check bytes that the client must send back in the user
- * packet in order for it to be accepted; this is used to defy ip
- * spoofing attacks. Note that this only works against somebody
- * doing IP spoofing from a remote machine; any machine on the local
- * network can still see outgoing packets and catch the random
- * cookie. This only affects rhosts authentication, and this is one
- * of the reasons why it is inherently insecure.
- */
- arc4random_buf(cookie, sizeof(cookie));
-
- /*
- * Send our public key. We include in the packet 64 bits of random
- * data that must be matched in the reply in order to prevent IP
- * spoofing.
- */
- packet_start(SSH_SMSG_PUBLIC_KEY);
- for (i = 0; i < 8; i++)
- packet_put_char(cookie[i]);
-
- /* Store our public server RSA key. */
- packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));
- packet_put_bignum(sensitive_data.server_key->rsa->e);
- packet_put_bignum(sensitive_data.server_key->rsa->n);
-
- /* Store our public host RSA key. */
- packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
- packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);
- packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);
-
- /* Put protocol flags. */
- packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
-
- /* Declare which ciphers we support. */
- packet_put_int(cipher_mask_ssh1(0));
-
- /* Declare supported authentication types. */
- auth_mask = 0;
- if (options.rhosts_rsa_authentication)
- auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
- if (options.rsa_authentication)
- auth_mask |= 1 << SSH_AUTH_RSA;
- if (options.challenge_response_authentication == 1)
- auth_mask |= 1 << SSH_AUTH_TIS;
- if (options.password_authentication)
- auth_mask |= 1 << SSH_AUTH_PASSWORD;
- packet_put_int(auth_mask);
-
- /* Send the packet and wait for it to be sent. */
- packet_send();
- packet_write_wait();
-
- debug("Sent %d bit server key and %d bit host key.",
- BN_num_bits(sensitive_data.server_key->rsa->n),
- BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
-
- /* Read clients reply (cipher type and session key). */
- packet_read_expect(SSH_CMSG_SESSION_KEY);
-
- /* Get cipher type and check whether we accept this. */
- cipher_type = packet_get_char();
-
- if (!(cipher_mask_ssh1(0) & (1 << cipher_type)))
- packet_disconnect("Warning: client selects unsupported cipher.");
-
- /* Get check bytes from the packet. These must match those we
- sent earlier with the public key packet. */
- for (i = 0; i < 8; i++)
- if (cookie[i] != packet_get_char())
- packet_disconnect("IP Spoofing check bytes do not match.");
-
- debug("Encryption type: %.200s", cipher_name(cipher_type));
-
- /* Get the encrypted integer. */
- if ((real_key_int = BN_new()) == NULL)
- fatal("do_ssh1_kex: BN_new failed");
- packet_get_bignum(real_key_int);
-
- protocol_flags = packet_get_int();
- packet_set_protocol_flags(protocol_flags);
- packet_check_eom();
-
- /* Setup a fake key in case RSA decryption fails */
- if ((fake_key_int = BN_new()) == NULL)
- fatal("do_ssh1_kex: BN_new failed");
- fake_key_len = BN_num_bytes(real_key_int);
- if (fake_key_len > sizeof(fake_key_bytes))
- fake_key_len = sizeof(fake_key_bytes);
- arc4random_buf(fake_key_bytes, fake_key_len);
- if (BN_bin2bn(fake_key_bytes, fake_key_len, fake_key_int) == NULL)
- fatal("do_ssh1_kex: BN_bin2bn failed");
-
- /* Decrypt real_key_int using host/server keys */
- rsafail = PRIVSEP(ssh1_session_key(real_key_int));
- /* If decryption failed, use the fake key. Else, the real key. */
- if (rsafail)
- session_key_int = fake_key_int;
- else
- session_key_int = real_key_int;
-
- /*
- * Extract session key from the decrypted integer. The key is in the
- * least significant 256 bits of the integer; the first byte of the
- * key is in the highest bits.
- */
- (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8);
- len = BN_num_bytes(session_key_int);
- if (len < 0 || (u_int)len > sizeof(session_key)) {
- error("do_ssh1_kex: bad session key len from %s: "
- "session_key_int %d > sizeof(session_key) %lu",
- get_remote_ipaddr(), len, (u_long)sizeof(session_key));
- rsafail++;
- } else {
- explicit_bzero(session_key, sizeof(session_key));
- BN_bn2bin(session_key_int,
- session_key + sizeof(session_key) - len);
-
- derive_ssh1_session_id(
- sensitive_data.ssh1_host_key->rsa->n,
- sensitive_data.server_key->rsa->n,
- cookie, session_id);
- /*
- * Xor the first 16 bytes of the session key with the
- * session id.
- */
- for (i = 0; i < 16; i++)
- session_key[i] ^= session_id[i];
- }
-
- /* Destroy the private and public keys. No longer. */
- destroy_sensitive_data();
-
- if (use_privsep)
- mm_ssh1_session_id(session_id);
-
- /* Destroy the decrypted integer. It is no longer needed. */
- BN_clear_free(real_key_int);
- BN_clear_free(fake_key_int);
-
- /* Set the session key. From this on all communications will be encrypted. */
- packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type);
-
- /* Destroy our copy of the session key. It is no longer needed. */
- explicit_bzero(session_key, sizeof(session_key));
-
- debug("Received session key; encryption turned on.");
-
- /* Send an acknowledgment packet. Note that this packet is sent encrypted. */
- packet_start(SSH_SMSG_SUCCESS);
- packet_send();
- packet_write_wait();
-}
-#endif
-
-int
-sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, size_t *slen,
- const u_char *data, size_t dlen, u_int flag)
-{
- int r;
- u_int xxx_slen, xxx_dlen = dlen;
-
- if (privkey) {
- if (PRIVSEP(key_sign(privkey, signature, &xxx_slen, data, xxx_dlen) < 0))
- fatal("%s: key_sign failed", __func__);
- if (slen)
- *slen = xxx_slen;
- } else if (use_privsep) {
- if (mm_key_sign(pubkey, signature, &xxx_slen, data, xxx_dlen) < 0)
- fatal("%s: pubkey_sign failed", __func__);
- if (slen)
- *slen = xxx_slen;
- } else {
- if ((r = ssh_agent_sign(auth_sock, pubkey, signature, slen,
- data, dlen, datafellows)) != 0)
- fatal("%s: ssh_agent_sign failed: %s",
- __func__, ssh_err(r));
}
return 0;
}
-/*
- * SSH2 key exchange: diffie-hellman-group1-sha1
- */
+/* SSH2 key exchange */
static void
-do_ssh2_kex(void)
+do_ssh2_kex(struct ssh *ssh)
{
char *myproposal[PROPOSAL_MAX] = { KEX_SERVER };
struct kex *kex;
int r;
- if (options.ciphers != NULL) {
- myproposal[PROPOSAL_ENC_ALGS_CTOS] =
- myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
- }
- myproposal[PROPOSAL_ENC_ALGS_CTOS] =
- compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
- myproposal[PROPOSAL_ENC_ALGS_STOC] =
- compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
-
- if (options.macs != NULL) {
- myproposal[PROPOSAL_MAC_ALGS_CTOS] =
- myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
- }
+ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
+ options.kex_algorithms);
+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(
+ options.ciphers);
+ myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal(
+ options.ciphers);
+ myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+ myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+
if (options.compression == COMP_NONE) {
myproposal[PROPOSAL_COMP_ALGS_CTOS] =
- myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
- } else if (options.compression == COMP_DELAYED) {
- myproposal[PROPOSAL_COMP_ALGS_CTOS] =
- myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com";
+ myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
}
- if (options.kex_algorithms != NULL)
- myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
-
- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
- myproposal[PROPOSAL_KEX_ALGS]);
if (options.rekey_limit || options.rekey_interval)
- packet_set_rekey_limits((u_int32_t)options.rekey_limit,
- (time_t)options.rekey_interval);
+ ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
+ options.rekey_interval);
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
list_hostkey_types());
/* start key exchange */
- if ((r = kex_setup(active_state, myproposal)) != 0)
+ if ((r = kex_setup(ssh, myproposal)) != 0)
fatal("kex_setup: %s", ssh_err(r));
- kex = active_state->kex;
+ kex = ssh->kex;
#ifdef WITH_OPENSSL
- kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
- kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
+ kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
+ kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
+ kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
+ kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
+ kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
# ifdef OPENSSL_HAS_ECC
- kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+ kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
# endif
#endif
- kex->kex[KEX_C25519_SHA256] = kexc25519_server;
- kex->server = 1;
- kex->client_version_string=client_version_string;
- kex->server_version_string=server_version_string;
+ kex->kex[KEX_C25519_SHA256] = kex_gen_server;
+ kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
kex->load_host_public_key=&get_hostkey_public_by_type;
kex->load_host_private_key=&get_hostkey_private_by_type;
kex->host_key_index=&get_hostkey_index;
kex->sign = sshd_hostkey_sign;
- dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
+ ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done);
session_id2 = kex->session_id;
session_id2_len = kex->session_id_len;
@@ -2614,8 +2386,8 @@ do_ssh2_kex(void)
void
cleanup_exit(int i)
{
- if (the_authctxt) {
- do_cleanup(the_authctxt);
+ if (the_active_state != NULL && the_authctxt != NULL) {
+ do_cleanup(the_active_state, the_authctxt);
if (use_privsep && privsep_is_preauth &&
pmonitor != NULL && pmonitor->m_pid > 1) {
debug("Killing privsep child %d", pmonitor->m_pid);
@@ -2627,8 +2399,8 @@ cleanup_exit(int i)
}
#ifdef SSH_AUDIT_EVENTS
/* done after do_cleanup so it can cancel the PAM auth 'thread' */
- if (!use_privsep || mm_is_monitor())
- audit_event(SSH_CONNECTION_ABANDON);
+ if (the_active_state != NULL && (!use_privsep || mm_is_monitor()))
+ audit_event(the_active_state, SSH_CONNECTION_ABANDON);
#endif
_exit(i);
}
diff --git a/sshd_config b/sshd_config
index c9042ac3..19b7c91a 100644
--- a/sshd_config
+++ b/sshd_config
@@ -1,4 +1,4 @@
-# $OpenBSD: sshd_config,v 1.94 2015/02/02 01:57:44 deraadt Exp $
+# $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
@@ -15,38 +15,25 @@
#ListenAddress 0.0.0.0
#ListenAddress ::
-# The default requires explicit activation of protocol 1
-#Protocol 2
-
-# HostKey for protocol version 1
-#HostKey /etc/ssh/ssh_host_key
-# HostKeys for protocol version 2
#HostKey /etc/ssh/ssh_host_rsa_key
-#HostKey /etc/ssh/ssh_host_dsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key
-# Lifetime and size of ephemeral version 1 server key
-#KeyRegenerationInterval 1h
-#ServerKeyBits 1024
-
# Ciphers and keying
#RekeyLimit default none
# Logging
-# obsoletes QuietMode and FascistLogging
#SyslogFacility AUTH
#LogLevel INFO
# Authentication:
#LoginGraceTime 2m
-#PermitRootLogin yes
+#PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
-#RSAAuthentication yes
#PubkeyAuthentication yes
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
@@ -59,11 +46,9 @@ AuthorizedKeysFile .ssh/authorized_keys
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
-#RhostsRSAAuthentication no
-# similar for protocol version 2
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
-# RhostsRSAAuthentication and HostbasedAuthentication
+# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
@@ -106,8 +91,6 @@ AuthorizedKeysFile .ssh/authorized_keys
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
-#UseLogin no
-UsePrivilegeSeparation sandbox # Default for new installations.
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
diff --git a/sshd_config.0 b/sshd_config.0
deleted file mode 100644
index be48e136..00000000
--- a/sshd_config.0
+++ /dev/null
@@ -1,946 +0,0 @@
-SSHD_CONFIG(5) File Formats Manual SSHD_CONFIG(5)
-
-NAME
- sshd_config M-bM-^@M-^S OpenSSH SSH daemon configuration file
-
-SYNOPSIS
- /etc/ssh/sshd_config
-
-DESCRIPTION
- sshd(8) reads configuration data from /etc/ssh/sshd_config (or the file
- specified with -f on the command line). The file contains keyword-
- argument pairs, one per line. Lines starting with M-bM-^@M-^X#M-bM-^@M-^Y and empty lines
- are interpreted as comments. Arguments may optionally be enclosed in
- double quotes (") in order to represent arguments containing spaces.
-
- The possible keywords and their meanings are as follows (note that
- keywords are case-insensitive and arguments are case-sensitive):
-
- AcceptEnv
- Specifies what environment variables sent by the client will be
- copied into the session's environ(7). See SendEnv in
- ssh_config(5) for how to configure the client. Note that
- environment passing is only supported for protocol 2. Variables
- are specified by name, which may contain the wildcard characters
- M-bM-^@M-^X*M-bM-^@M-^Y and M-bM-^@M-^X?M-bM-^@M-^Y. Multiple environment variables may be separated by
- whitespace or spread across multiple AcceptEnv directives. Be
- warned that some environment variables could be used to bypass
- restricted user environments. For this reason, care should be
- taken in the use of this directive. The default is not to accept
- any environment variables.
-
- AddressFamily
- Specifies which address family should be used by sshd(8). Valid
- arguments are M-bM-^@M-^\anyM-bM-^@M-^], M-bM-^@M-^\inetM-bM-^@M-^] (use IPv4 only), or M-bM-^@M-^\inet6M-bM-^@M-^] (use IPv6
- only). The default is M-bM-^@M-^\anyM-bM-^@M-^].
-
- AllowAgentForwarding
- Specifies whether ssh-agent(1) forwarding is permitted. The
- default is M-bM-^@M-^\yesM-bM-^@M-^]. Note that disabling agent forwarding does not
- improve security unless users are also denied shell access, as
- they can always install their own forwarders.
-
- AllowGroups
- This keyword can be followed by a list of group name patterns,
- separated by spaces. If specified, login is allowed only for
- users whose primary group or supplementary group list matches one
- of the patterns. Only group names are valid; a numerical group
- ID is not recognized. By default, login is allowed for all
- groups. The allow/deny directives are processed in the following
- order: DenyUsers, AllowUsers, DenyGroups, and finally
- AllowGroups.
-
- See PATTERNS in ssh_config(5) for more information on patterns.
-
- AllowTcpForwarding
- Specifies whether TCP forwarding is permitted. The available
- options are M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\allM-bM-^@M-^] to allow TCP forwarding, M-bM-^@M-^\noM-bM-^@M-^] to
- prevent all TCP forwarding, M-bM-^@M-^\localM-bM-^@M-^] to allow local (from the
- perspective of ssh(1)) forwarding only or M-bM-^@M-^\remoteM-bM-^@M-^] to allow
- remote forwarding only. The default is M-bM-^@M-^\yesM-bM-^@M-^]. Note that
- disabling TCP forwarding does not improve security unless users
- are also denied shell access, as they can always install their
- own forwarders.
-
- AllowStreamLocalForwarding
- Specifies whether StreamLocal (Unix-domain socket) forwarding is
- permitted. The available options are M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\allM-bM-^@M-^] to allow
- StreamLocal forwarding, M-bM-^@M-^\noM-bM-^@M-^] to prevent all StreamLocal
- forwarding, M-bM-^@M-^\localM-bM-^@M-^] to allow local (from the perspective of
- ssh(1)) forwarding only or M-bM-^@M-^\remoteM-bM-^@M-^] to allow remote forwarding
- only. The default is M-bM-^@M-^\yesM-bM-^@M-^]. Note that disabling StreamLocal
- forwarding does not improve security unless users are also denied
- shell access, as they can always install their own forwarders.
-
- AllowUsers
- This keyword can be followed by a list of user name patterns,
- separated by spaces. If specified, login is allowed only for
- user names that match one of the patterns. Only user names are
- valid; a numerical user ID is not recognized. By default, login
- is allowed for all users. If the pattern takes the form
- USER@HOST then USER and HOST are separately checked, restricting
- logins to particular users from particular hosts. The allow/deny
- directives are processed in the following order: DenyUsers,
- AllowUsers, DenyGroups, and finally AllowGroups.
-
- See PATTERNS in ssh_config(5) for more information on patterns.
-
- AuthenticationMethods
- Specifies the authentication methods that must be successfully
- completed for a user to be granted access. This option must be
- followed by one or more comma-separated lists of authentication
- method names. Successful authentication requires completion of
- every method in at least one of these lists.
-
- For example, an argument of M-bM-^@M-^\publickey,password
- publickey,keyboard-interactiveM-bM-^@M-^] would require the user to
- complete public key authentication, followed by either password
- or keyboard interactive authentication. Only methods that are
- next in one or more lists are offered at each stage, so for this
- example, it would not be possible to attempt password or
- keyboard-interactive authentication before public key.
-
- For keyboard interactive authentication it is also possible to
- restrict authentication to a specific device by appending a colon
- followed by the device identifier M-bM-^@M-^\bsdauthM-bM-^@M-^], M-bM-^@M-^\pamM-bM-^@M-^], or M-bM-^@M-^\skeyM-bM-^@M-^],
- depending on the server configuration. For example,
- M-bM-^@M-^\keyboard-interactive:bsdauthM-bM-^@M-^] would restrict keyboard
- interactive authentication to the M-bM-^@M-^\bsdauthM-bM-^@M-^] device.
-
- If the M-bM-^@M-^\publickeyM-bM-^@M-^] method is listed more than once, sshd(8)
- verifies that keys that have been used successfully are not
- reused for subsequent authentications. For example, an
- AuthenticationMethods of M-bM-^@M-^\publickey,publickeyM-bM-^@M-^] will require
- successful authentication using two different public keys.
-
- This option is only available for SSH protocol 2 and will yield a
- fatal error if enabled if protocol 1 is also enabled. Note that
- each authentication method listed should also be explicitly
- enabled in the configuration. The default is not to require
- multiple authentication; successful completion of a single
- authentication method is sufficient.
-
- AuthorizedKeysCommand
- Specifies a program to be used to look up the user's public keys.
- The program must be owned by root and not writable by group or
- others. It will be invoked with a single argument of the
- username being authenticated, and should produce on standard
- output zero or more lines of authorized_keys output (see
- AUTHORIZED_KEYS in sshd(8)). If a key supplied by
- AuthorizedKeysCommand does not successfully authenticate and
- authorize the user then public key authentication continues using
- the usual AuthorizedKeysFile files. By default, no
- AuthorizedKeysCommand is run.
-
- AuthorizedKeysCommandUser
- Specifies the user under whose account the AuthorizedKeysCommand
- is run. It is recommended to use a dedicated user that has no
- other role on the host than running authorized keys commands. If
- AuthorizedKeysCommand is specified but AuthorizedKeysCommandUser
- is not, then sshd(8) will refuse to start.
-
- AuthorizedKeysFile
- Specifies the file that contains the public keys that can be used
- for user authentication. The format is described in the
- AUTHORIZED_KEYS FILE FORMAT section of sshd(8).
- AuthorizedKeysFile may contain tokens of the form %T which are
- substituted during connection setup. The following tokens are
- defined: %% is replaced by a literal '%', %h is replaced by the
- home directory of the user being authenticated, and %u is
- replaced by the username of that user. After expansion,
- AuthorizedKeysFile is taken to be an absolute path or one
- relative to the user's home directory. Multiple files may be
- listed, separated by whitespace. The default is
- M-bM-^@M-^\.ssh/authorized_keys .ssh/authorized_keys2M-bM-^@M-^].
-
- AuthorizedPrincipalsFile
- Specifies a file that lists principal names that are accepted for
- certificate authentication. When using certificates signed by a
- key listed in TrustedUserCAKeys, this file lists names, one of
- which must appear in the certificate for it to be accepted for
- authentication. Names are listed one per line preceded by key
- options (as described in AUTHORIZED_KEYS FILE FORMAT in sshd(8)).
- Empty lines and comments starting with M-bM-^@M-^X#M-bM-^@M-^Y are ignored.
-
- AuthorizedPrincipalsFile may contain tokens of the form %T which
- are substituted during connection setup. The following tokens
- are defined: %% is replaced by a literal '%', %h is replaced by
- the home directory of the user being authenticated, and %u is
- replaced by the username of that user. After expansion,
- AuthorizedPrincipalsFile is taken to be an absolute path or one
- relative to the user's home directory.
-
- The default is M-bM-^@M-^\noneM-bM-^@M-^], i.e. not to use a principals file M-bM-^@M-^S in
- this case, the username of the user must appear in a
- certificate's principals list for it to be accepted. Note that
- AuthorizedPrincipalsFile is only used when authentication
- proceeds using a CA listed in TrustedUserCAKeys and is not
- consulted for certification authorities trusted via
- ~/.ssh/authorized_keys, though the principals= key option offers
- a similar facility (see sshd(8) for details).
-
- Banner The contents of the specified file are sent to the remote user
- before authentication is allowed. If the argument is M-bM-^@M-^\noneM-bM-^@M-^] then
- no banner is displayed. This option is only available for
- protocol version 2. By default, no banner is displayed.
-
- ChallengeResponseAuthentication
- Specifies whether challenge-response authentication is allowed
- (e.g. via PAM or through authentication styles supported in
- login.conf(5)) The default is M-bM-^@M-^\yesM-bM-^@M-^].
-
- ChrootDirectory
- Specifies the pathname of a directory to chroot(2) to after
- authentication. At session startup sshd(8) checks that all
- components of the pathname are root-owned directories which are
- not writable by any other user or group. After the chroot,
- sshd(8) changes the working directory to the user's home
- directory.
-
- The pathname may contain the following tokens that are expanded
- at runtime once the connecting user has been authenticated: %% is
- replaced by a literal '%', %h is replaced by the home directory
- of the user being authenticated, and %u is replaced by the
- username of that user.
-
- The ChrootDirectory must contain the necessary files and
- directories to support the user's session. For an interactive
- session this requires at least a shell, typically sh(1), and
- basic /dev nodes such as null(4), zero(4), stdin(4), stdout(4),
- stderr(4), and tty(4) devices. For file transfer sessions using
- M-bM-^@M-^\sftpM-bM-^@M-^], no additional configuration of the environment is
- necessary if the in-process sftp server is used, though sessions
- which use logging may require /dev/log inside the chroot
- directory on some operating systems (see sftp-server(8) for
- details).
-
- For safety, it is very important that the directory hierarchy be
- prevented from modification by other processes on the system
- (especially those outside the jail). Misconfiguration can lead
- to unsafe environments which sshd(8) cannot detect.
-
- The default is not to chroot(2).
-
- Ciphers
- Specifies the ciphers allowed for protocol version 2. Multiple
- ciphers must be comma-separated. The supported ciphers are:
-
- 3des-cbc
- aes128-cbc
- aes192-cbc
- aes256-cbc
- aes128-ctr
- aes192-ctr
- aes256-ctr
- aes128-gcm@openssh.com
- aes256-gcm@openssh.com
- arcfour
- arcfour128
- arcfour256
- blowfish-cbc
- cast128-cbc
- chacha20-poly1305@openssh.com
-
- The default is:
-
- aes128-ctr,aes192-ctr,aes256-ctr,
- aes128-gcm@openssh.com,aes256-gcm@openssh.com,
- chacha20-poly1305@openssh.com
-
- The list of available ciphers may also be obtained using the -Q
- option of ssh(1) with an argument of M-bM-^@M-^\cipherM-bM-^@M-^].
-
- ClientAliveCountMax
- Sets the number of client alive messages (see below) which may be
- sent without sshd(8) receiving any messages back from the client.
- If this threshold is reached while client alive messages are
- being sent, sshd will disconnect the client, terminating the
- session. It is important to note that the use of client alive
- messages is very different from TCPKeepAlive (below). The client
- alive messages are sent through the encrypted channel and
- therefore will not be spoofable. The TCP keepalive option
- enabled by TCPKeepAlive is spoofable. The client alive mechanism
- is valuable when the client or server depend on knowing when a
- connection has become inactive.
-
- The default value is 3. If ClientAliveInterval (see below) is
- set to 15, and ClientAliveCountMax is left at the default,
- unresponsive SSH clients will be disconnected after approximately
- 45 seconds. This option applies to protocol version 2 only.
-
- ClientAliveInterval
- Sets a timeout interval in seconds after which if no data has
- been received from the client, sshd(8) will send a message
- through the encrypted channel to request a response from the
- client. The default is 0, indicating that these messages will
- not be sent to the client. This option applies to protocol
- version 2 only.
-
- Compression
- Specifies whether compression is allowed, or delayed until the
- user has authenticated successfully. The argument must be M-bM-^@M-^\yesM-bM-^@M-^],
- M-bM-^@M-^\delayedM-bM-^@M-^], or M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\delayedM-bM-^@M-^].
-
- DenyGroups
- This keyword can be followed by a list of group name patterns,
- separated by spaces. Login is disallowed for users whose primary
- group or supplementary group list matches one of the patterns.
- Only group names are valid; a numerical group ID is not
- recognized. By default, login is allowed for all groups. The
- allow/deny directives are processed in the following order:
- DenyUsers, AllowUsers, DenyGroups, and finally AllowGroups.
-
- See PATTERNS in ssh_config(5) for more information on patterns.
-
- DenyUsers
- This keyword can be followed by a list of user name patterns,
- separated by spaces. Login is disallowed for user names that
- match one of the patterns. Only user names are valid; a
- numerical user ID is not recognized. By default, login is
- allowed for all users. If the pattern takes the form USER@HOST
- then USER and HOST are separately checked, restricting logins to
- particular users from particular hosts. The allow/deny
- directives are processed in the following order: DenyUsers,
- AllowUsers, DenyGroups, and finally AllowGroups.
-
- See PATTERNS in ssh_config(5) for more information on patterns.
-
- FingerprintHash
- Specifies the hash algorithm used when logging key fingerprints.
- Valid options are: M-bM-^@M-^\md5M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The default is M-bM-^@M-^\sha256M-bM-^@M-^].
-
- ForceCommand
- Forces the execution of the command specified by ForceCommand,
- ignoring any command supplied by the client and ~/.ssh/rc if
- present. The command is invoked by using the user's login shell
- with the -c option. This applies to shell, command, or subsystem
- execution. It is most useful inside a Match block. The command
- originally supplied by the client is available in the
- SSH_ORIGINAL_COMMAND environment variable. Specifying a command
- of M-bM-^@M-^\internal-sftpM-bM-^@M-^] will force the use of an in-process sftp
- server that requires no support files when used with
- ChrootDirectory.
-
- GatewayPorts
- Specifies whether remote hosts are allowed to connect to ports
- forwarded for the client. By default, sshd(8) binds remote port
- forwardings to the loopback address. This prevents other remote
- hosts from connecting to forwarded ports. GatewayPorts can be
- used to specify that sshd should allow remote port forwardings to
- bind to non-loopback addresses, thus allowing other hosts to
- connect. The argument may be M-bM-^@M-^\noM-bM-^@M-^] to force remote port
- forwardings to be available to the local host only, M-bM-^@M-^\yesM-bM-^@M-^] to
- force remote port forwardings to bind to the wildcard address, or
- M-bM-^@M-^\clientspecifiedM-bM-^@M-^] to allow the client to select the address to
- which the forwarding is bound. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- GSSAPIAuthentication
- Specifies whether user authentication based on GSSAPI is allowed.
- The default is M-bM-^@M-^\noM-bM-^@M-^]. Note that this option applies to protocol
- version 2 only.
-
- GSSAPICleanupCredentials
- Specifies whether to automatically destroy the user's credentials
- cache on logout. The default is M-bM-^@M-^\yesM-bM-^@M-^]. Note that this option
- applies to protocol version 2 only.
-
- HostbasedAcceptedKeyTypes
- Specifies the key types that will be accepted for hostbased
- authentication as a comma-separated pattern list. The default
- M-bM-^@M-^\*M-bM-^@M-^] will allow all key types. The -Q option of ssh(1) may be
- used to list supported key types.
-
- HostbasedAuthentication
- Specifies whether rhosts or /etc/hosts.equiv authentication
- together with successful public key client host authentication is
- allowed (host-based authentication). This option is similar to
- RhostsRSAAuthentication and applies to protocol version 2 only.
- The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- HostbasedUsesNameFromPacketOnly
- Specifies whether or not the server will attempt to perform a
- reverse name lookup when matching the name in the ~/.shosts,
- ~/.rhosts, and /etc/hosts.equiv files during
- HostbasedAuthentication. A setting of M-bM-^@M-^\yesM-bM-^@M-^] means that sshd(8)
- uses the name supplied by the client rather than attempting to
- resolve the name from the TCP connection itself. The default is
- M-bM-^@M-^\noM-bM-^@M-^].
-
- HostCertificate
- Specifies a file containing a public host certificate. The
- certificate's public key must match a private host key already
- specified by HostKey. The default behaviour of sshd(8) is not to
- load any certificates.
-
- HostKey
- Specifies a file containing a private host key used by SSH. The
- default is /etc/ssh/ssh_host_key for protocol version 1, and
- /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_ecdsa_key,
- /etc/ssh/ssh_host_ed25519_key and /etc/ssh/ssh_host_rsa_key for
- protocol version 2. Note that sshd(8) will refuse to use a file
- if it is group/world-accessible. It is possible to have multiple
- host key files. M-bM-^@M-^\rsa1M-bM-^@M-^] keys are used for version 1 and M-bM-^@M-^\dsaM-bM-^@M-^],
- M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^] or M-bM-^@M-^\rsaM-bM-^@M-^] are used for version 2 of the SSH
- protocol. It is also possible to specify public host key files
- instead. In this case operations on the private key will be
- delegated to an ssh-agent(1).
-
- HostKeyAgent
- Identifies the UNIX-domain socket used to communicate with an
- agent that has access to the private host keys. If
- M-bM-^@M-^\SSH_AUTH_SOCKM-bM-^@M-^] is specified, the location of the socket will be
- read from the SSH_AUTH_SOCK environment variable.
-
- IgnoreRhosts
- Specifies that .rhosts and .shosts files will not be used in
- RhostsRSAAuthentication or HostbasedAuthentication.
-
- /etc/hosts.equiv and /etc/shosts.equiv are still used. The
- default is M-bM-^@M-^\yesM-bM-^@M-^].
-
- IgnoreUserKnownHosts
- Specifies whether sshd(8) should ignore the user's
- ~/.ssh/known_hosts during RhostsRSAAuthentication or
- HostbasedAuthentication. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- IPQoS Specifies the IPv4 type-of-service or DSCP class for the
- connection. Accepted values are M-bM-^@M-^\af11M-bM-^@M-^], M-bM-^@M-^\af12M-bM-^@M-^], M-bM-^@M-^\af13M-bM-^@M-^], M-bM-^@M-^\af21M-bM-^@M-^],
- M-bM-^@M-^\af22M-bM-^@M-^], M-bM-^@M-^\af23M-bM-^@M-^], M-bM-^@M-^\af31M-bM-^@M-^], M-bM-^@M-^\af32M-bM-^@M-^], M-bM-^@M-^\af33M-bM-^@M-^], M-bM-^@M-^\af41M-bM-^@M-^], M-bM-^@M-^\af42M-bM-^@M-^], M-bM-^@M-^\af43M-bM-^@M-^],
- M-bM-^@M-^\cs0M-bM-^@M-^], M-bM-^@M-^\cs1M-bM-^@M-^], M-bM-^@M-^\cs2M-bM-^@M-^], M-bM-^@M-^\cs3M-bM-^@M-^], M-bM-^@M-^\cs4M-bM-^@M-^], M-bM-^@M-^\cs5M-bM-^@M-^], M-bM-^@M-^\cs6M-bM-^@M-^], M-bM-^@M-^\cs7M-bM-^@M-^], M-bM-^@M-^\efM-bM-^@M-^],
- M-bM-^@M-^\lowdelayM-bM-^@M-^], M-bM-^@M-^\throughputM-bM-^@M-^], M-bM-^@M-^\reliabilityM-bM-^@M-^], or a numeric value.
- This option may take one or two arguments, separated by
- whitespace. If one argument is specified, it is used as the
- packet class unconditionally. If two values are specified, the
- first is automatically selected for interactive sessions and the
- second for non-interactive sessions. The default is M-bM-^@M-^\lowdelayM-bM-^@M-^]
- for interactive sessions and M-bM-^@M-^\throughputM-bM-^@M-^] for non-interactive
- sessions.
-
- KbdInteractiveAuthentication
- Specifies whether to allow keyboard-interactive authentication.
- The argument to this keyword must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default
- is to use whatever value ChallengeResponseAuthentication is set
- to (by default M-bM-^@M-^\yesM-bM-^@M-^]).
-
- KerberosAuthentication
- Specifies whether the password provided by the user for
- PasswordAuthentication will be validated through the Kerberos
- KDC. To use this option, the server needs a Kerberos servtab
- which allows the verification of the KDC's identity. The default
- is M-bM-^@M-^\noM-bM-^@M-^].
-
- KerberosGetAFSToken
- If AFS is active and the user has a Kerberos 5 TGT, attempt to
- acquire an AFS token before accessing the user's home directory.
- The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- KerberosOrLocalPasswd
- If password authentication through Kerberos fails then the
- password will be validated via any additional local mechanism
- such as /etc/passwd. The default is M-bM-^@M-^\yesM-bM-^@M-^].
-
- KerberosTicketCleanup
- Specifies whether to automatically destroy the user's ticket
- cache file on logout. The default is M-bM-^@M-^\yesM-bM-^@M-^].
-
- KexAlgorithms
- Specifies the available KEX (Key Exchange) algorithms. Multiple
- algorithms must be comma-separated. The supported algorithms
- are:
-
- curve25519-sha256@libssh.org
- diffie-hellman-group1-sha1
- diffie-hellman-group14-sha1
- diffie-hellman-group-exchange-sha1
- diffie-hellman-group-exchange-sha256
- ecdh-sha2-nistp256
- ecdh-sha2-nistp384
- ecdh-sha2-nistp521
-
- The default is:
-
- curve25519-sha256@libssh.org,
- ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
- diffie-hellman-group-exchange-sha256,
- diffie-hellman-group14-sha1
-
- The list of available key exchange algorithms may also be
- obtained using the -Q option of ssh(1) with an argument of M-bM-^@M-^\kexM-bM-^@M-^].
-
- KeyRegenerationInterval
- In protocol version 1, the ephemeral server key is automatically
- regenerated after this many seconds (if it has been used). The
- purpose of regeneration is to prevent decrypting captured
- sessions by later breaking into the machine and stealing the
- keys. The key is never stored anywhere. If the value is 0, the
- key is never regenerated. The default is 3600 (seconds).
-
- ListenAddress
- Specifies the local addresses sshd(8) should listen on. The
- following forms may be used:
-
- ListenAddress host|IPv4_addr|IPv6_addr
- ListenAddress host|IPv4_addr:port
- ListenAddress [host|IPv6_addr]:port
-
- If port is not specified, sshd will listen on the address and all
- prior Port options specified. The default is to listen on all
- local addresses. Multiple ListenAddress options are permitted.
- Additionally, any Port options must precede this option for non-
- port qualified addresses.
-
- LoginGraceTime
- The server disconnects after this time if the user has not
- successfully logged in. If the value is 0, there is no time
- limit. The default is 120 seconds.
-
- LogLevel
- Gives the verbosity level that is used when logging messages from
- sshd(8). The possible values are: QUIET, FATAL, ERROR, INFO,
- VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO.
- DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify
- higher levels of debugging output. Logging with a DEBUG level
- violates the privacy of users and is not recommended.
-
- MACs Specifies the available MAC (message authentication code)
- algorithms. The MAC algorithm is used in protocol version 2 for
- data integrity protection. Multiple algorithms must be comma-
- separated. The algorithms that contain M-bM-^@M-^\-etmM-bM-^@M-^] calculate the MAC
- after encryption (encrypt-then-mac). These are considered safer
- and their use recommended. The supported MACs are:
-
- hmac-md5
- hmac-md5-96
- hmac-ripemd160
- hmac-sha1
- hmac-sha1-96
- hmac-sha2-256
- hmac-sha2-512
- umac-64@openssh.com
- umac-128@openssh.com
- hmac-md5-etm@openssh.com
- hmac-md5-96-etm@openssh.com
- hmac-ripemd160-etm@openssh.com
- hmac-sha1-etm@openssh.com
- hmac-sha1-96-etm@openssh.com
- hmac-sha2-256-etm@openssh.com
- hmac-sha2-512-etm@openssh.com
- umac-64-etm@openssh.com
- umac-128-etm@openssh.com
-
- The default is:
-
- umac-64-etm@openssh.com,umac-128-etm@openssh.com,
- hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
- umac-64@openssh.com,umac-128@openssh.com,
- hmac-sha2-256,hmac-sha2-512
-
- The list of available MAC algorithms may also be obtained using
- the -Q option of ssh(1) with an argument of M-bM-^@M-^\macM-bM-^@M-^].
-
- Match Introduces a conditional block. If all of the criteria on the
- Match line are satisfied, the keywords on the following lines
- override those set in the global section of the config file,
- until either another Match line or the end of the file. If a
- keyword appears in multiple Match blocks that are satisfied, only
- the first instance of the keyword is applied.
-
- The arguments to Match are one or more criteria-pattern pairs or
- the single token All which matches all criteria. The available
- criteria are User, Group, Host, LocalAddress, LocalPort, and
- Address. The match patterns may consist of single entries or
- comma-separated lists and may use the wildcard and negation
- operators described in the PATTERNS section of ssh_config(5).
-
- The patterns in an Address criteria may additionally contain
- addresses to match in CIDR address/masklen format, e.g.
- M-bM-^@M-^\192.0.2.0/24M-bM-^@M-^] or M-bM-^@M-^\3ffe:ffff::/32M-bM-^@M-^]. Note that the mask length
- provided must be consistent with the address - it is an error to
- specify a mask length that is too long for the address or one
- with bits set in this host portion of the address. For example,
- M-bM-^@M-^\192.0.2.0/33M-bM-^@M-^] and M-bM-^@M-^\192.0.2.0/8M-bM-^@M-^] respectively.
-
- Only a subset of keywords may be used on the lines following a
- Match keyword. Available keywords are AcceptEnv,
- AllowAgentForwarding, AllowGroups, AllowStreamLocalForwarding,
- AllowTcpForwarding, AllowUsers, AuthenticationMethods,
- AuthorizedKeysCommand, AuthorizedKeysCommandUser,
- AuthorizedKeysFile, AuthorizedPrincipalsFile, Banner,
- ChrootDirectory, DenyGroups, DenyUsers, ForceCommand,
- GatewayPorts, GSSAPIAuthentication, HostbasedAcceptedKeyTypes,
- HostbasedAuthentication, HostbasedUsesNameFromPacketOnly, IPQoS,
- KbdInteractiveAuthentication, KerberosAuthentication,
- MaxAuthTries, MaxSessions, PasswordAuthentication,
- PermitEmptyPasswords, PermitOpen, PermitRootLogin, PermitTTY,
- PermitTunnel, PermitUserRC, PubkeyAcceptedKeyTypes,
- PubkeyAuthentication, RekeyLimit, RevokedKeys,
- RhostsRSAAuthentication, RSAAuthentication, StreamLocalBindMask,
- StreamLocalBindUnlink, TrustedUserCAKeys, X11DisplayOffset,
- X11Forwarding and X11UseLocalHost.
-
- MaxAuthTries
- Specifies the maximum number of authentication attempts permitted
- per connection. Once the number of failures reaches half this
- value, additional failures are logged. The default is 6.
-
- MaxSessions
- Specifies the maximum number of open sessions permitted per
- network connection. The default is 10.
-
- MaxStartups
- Specifies the maximum number of concurrent unauthenticated
- connections to the SSH daemon. Additional connections will be
- dropped until authentication succeeds or the LoginGraceTime
- expires for a connection. The default is 10:30:100.
-
- Alternatively, random early drop can be enabled by specifying the
- three colon separated values M-bM-^@M-^\start:rate:fullM-bM-^@M-^] (e.g. "10:30:60").
- sshd(8) will refuse connection attempts with a probability of
- M-bM-^@M-^\rate/100M-bM-^@M-^] (30%) if there are currently M-bM-^@M-^\startM-bM-^@M-^] (10)
- unauthenticated connections. The probability increases linearly
- and all connection attempts are refused if the number of
- unauthenticated connections reaches M-bM-^@M-^\fullM-bM-^@M-^] (60).
-
- PasswordAuthentication
- Specifies whether password authentication is allowed. The
- default is M-bM-^@M-^\yesM-bM-^@M-^].
-
- PermitEmptyPasswords
- When password authentication is allowed, it specifies whether the
- server allows login to accounts with empty password strings. The
- default is M-bM-^@M-^\noM-bM-^@M-^].
-
- PermitOpen
- Specifies the destinations to which TCP port forwarding is
- permitted. The forwarding specification must be one of the
- following forms:
-
- PermitOpen host:port
- PermitOpen IPv4_addr:port
- PermitOpen [IPv6_addr]:port
-
- Multiple forwards may be specified by separating them with
- whitespace. An argument of M-bM-^@M-^\anyM-bM-^@M-^] can be used to remove all
- restrictions and permit any forwarding requests. An argument of
- M-bM-^@M-^\noneM-bM-^@M-^] can be used to prohibit all forwarding requests. By
- default all port forwarding requests are permitted.
-
- PermitRootLogin
- Specifies whether root can log in using ssh(1). The argument
- must be M-bM-^@M-^\yesM-bM-^@M-^], M-bM-^@M-^\without-passwordM-bM-^@M-^], M-bM-^@M-^\forced-commands-onlyM-bM-^@M-^], or
- M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\yesM-bM-^@M-^].
-
- If this option is set to M-bM-^@M-^\without-passwordM-bM-^@M-^], password
- authentication is disabled for root.
-
- If this option is set to M-bM-^@M-^\forced-commands-onlyM-bM-^@M-^], root login with
- public key authentication will be allowed, but only if the
- command option has been specified (which may be useful for taking
- remote backups even if root login is normally not allowed). All
- other authentication methods are disabled for root.
-
- If this option is set to M-bM-^@M-^\noM-bM-^@M-^], root is not allowed to log in.
-
- PermitTunnel
- Specifies whether tun(4) device forwarding is allowed. The
- argument must be M-bM-^@M-^\yesM-bM-^@M-^], M-bM-^@M-^\point-to-pointM-bM-^@M-^] (layer 3), M-bM-^@M-^\ethernetM-bM-^@M-^]
- (layer 2), or M-bM-^@M-^\noM-bM-^@M-^]. Specifying M-bM-^@M-^\yesM-bM-^@M-^] permits both
- M-bM-^@M-^\point-to-pointM-bM-^@M-^] and M-bM-^@M-^\ethernetM-bM-^@M-^]. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- Independent of this setting, the permissions of the selected
- tun(4) device must allow access to the user.
-
- PermitTTY
- Specifies whether pty(4) allocation is permitted. The default is
- M-bM-^@M-^\yesM-bM-^@M-^].
-
- PermitUserEnvironment
- Specifies whether ~/.ssh/environment and environment= options in
- ~/.ssh/authorized_keys are processed by sshd(8). The default is
- M-bM-^@M-^\noM-bM-^@M-^]. Enabling environment processing may enable users to bypass
- access restrictions in some configurations using mechanisms such
- as LD_PRELOAD.
-
- PermitUserRC
- Specifies whether any ~/.ssh/rc file is executed. The default is
- M-bM-^@M-^\yesM-bM-^@M-^].
-
- PidFile
- Specifies the file that contains the process ID of the SSH
- daemon. The default is /var/run/sshd.pid.
-
- Port Specifies the port number that sshd(8) listens on. The default
- is 22. Multiple options of this type are permitted. See also
- ListenAddress.
-
- PrintLastLog
- Specifies whether sshd(8) should print the date and time of the
- last user login when a user logs in interactively. The default
- is M-bM-^@M-^\yesM-bM-^@M-^].
-
- PrintMotd
- Specifies whether sshd(8) should print /etc/motd when a user logs
- in interactively. (On some systems it is also printed by the
- shell, /etc/profile, or equivalent.) The default is M-bM-^@M-^\yesM-bM-^@M-^].
-
- Protocol
- Specifies the protocol versions sshd(8) supports. The possible
- values are M-bM-^@M-^X1M-bM-^@M-^Y and M-bM-^@M-^X2M-bM-^@M-^Y. Multiple versions must be comma-
- separated. The default is M-bM-^@M-^X2M-bM-^@M-^Y. Note that the order of the
- protocol list does not indicate preference, because the client
- selects among multiple protocol versions offered by the server.
- Specifying M-bM-^@M-^\2,1M-bM-^@M-^] is identical to M-bM-^@M-^\1,2M-bM-^@M-^].
-
- PubkeyAcceptedKeyTypes
- Specifies the key types that will be accepted for public key
- authentication as a comma-separated pattern list. The default
- M-bM-^@M-^\*M-bM-^@M-^] will allow all key types. The -Q option of ssh(1) may be
- used to list supported key types.
-
- PubkeyAuthentication
- Specifies whether public key authentication is allowed. The
- default is M-bM-^@M-^\yesM-bM-^@M-^]. Note that this option applies to protocol
- version 2 only.
-
- RekeyLimit
- Specifies the maximum amount of data that may be transmitted
- before the session key is renegotiated, optionally followed a
- maximum amount of time that may pass before the session key is
- renegotiated. The first argument is specified in bytes and may
- have a suffix of M-bM-^@M-^XKM-bM-^@M-^Y, M-bM-^@M-^XMM-bM-^@M-^Y, or M-bM-^@M-^XGM-bM-^@M-^Y to indicate Kilobytes,
- Megabytes, or Gigabytes, respectively. The default is between
- M-bM-^@M-^X1GM-bM-^@M-^Y and M-bM-^@M-^X4GM-bM-^@M-^Y, depending on the cipher. The optional second
- value is specified in seconds and may use any of the units
- documented in the TIME FORMATS section. The default value for
- RekeyLimit is M-bM-^@M-^\default noneM-bM-^@M-^], which means that rekeying is
- performed after the cipher's default amount of data has been sent
- or received and no time based rekeying is done. This option
- applies to protocol version 2 only.
-
- RevokedKeys
- Specifies revoked public keys. Keys listed in this file will be
- refused for public key authentication. Note that if this file is
- not readable, then public key authentication will be refused for
- all users. Keys may be specified as a text file, listing one
- public key per line, or as an OpenSSH Key Revocation List (KRL)
- as generated by ssh-keygen(1). For more information on KRLs, see
- the KEY REVOCATION LISTS section in ssh-keygen(1).
-
- RhostsRSAAuthentication
- Specifies whether rhosts or /etc/hosts.equiv authentication
- together with successful RSA host authentication is allowed. The
- default is M-bM-^@M-^\noM-bM-^@M-^]. This option applies to protocol version 1 only.
-
- RSAAuthentication
- Specifies whether pure RSA authentication is allowed. The
- default is M-bM-^@M-^\yesM-bM-^@M-^]. This option applies to protocol version 1
- only.
-
- ServerKeyBits
- Defines the number of bits in the ephemeral protocol version 1
- server key. The minimum value is 512, and the default is 1024.
-
- StreamLocalBindMask
- Sets the octal file creation mode mask (umask) used when creating
- a Unix-domain socket file for local or remote port forwarding.
- This option is only used for port forwarding to a Unix-domain
- socket file.
-
- The default value is 0177, which creates a Unix-domain socket
- file that is readable and writable only by the owner. Note that
- not all operating systems honor the file mode on Unix-domain
- socket files.
-
- StreamLocalBindUnlink
- Specifies whether to remove an existing Unix-domain socket file
- for local or remote port forwarding before creating a new one.
- If the socket file already exists and StreamLocalBindUnlink is
- not enabled, sshd will be unable to forward the port to the Unix-
- domain socket file. This option is only used for port forwarding
- to a Unix-domain socket file.
-
- The argument must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- StrictModes
- Specifies whether sshd(8) should check file modes and ownership
- of the user's files and home directory before accepting login.
- This is normally desirable because novices sometimes accidentally
- leave their directory or files world-writable. The default is
- M-bM-^@M-^\yesM-bM-^@M-^]. Note that this does not apply to ChrootDirectory, whose
- permissions and ownership are checked unconditionally.
-
- Subsystem
- Configures an external subsystem (e.g. file transfer daemon).
- Arguments should be a subsystem name and a command (with optional
- arguments) to execute upon subsystem request.
-
- The command sftp-server(8) implements the M-bM-^@M-^\sftpM-bM-^@M-^] file transfer
- subsystem.
-
- Alternately the name M-bM-^@M-^\internal-sftpM-bM-^@M-^] implements an in-process
- M-bM-^@M-^\sftpM-bM-^@M-^] server. This may simplify configurations using
- ChrootDirectory to force a different filesystem root on clients.
-
- By default no subsystems are defined. Note that this option
- applies to protocol version 2 only.
-
- SyslogFacility
- Gives the facility code that is used when logging messages from
- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0,
- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The
- default is AUTH.
-
- TCPKeepAlive
- Specifies whether the system should send TCP keepalive messages
- to the other side. If they are sent, death of the connection or
- crash of one of the machines will be properly noticed. However,
- this means that connections will die if the route is down
- temporarily, and some people find it annoying. On the other
- hand, if TCP keepalives are not sent, sessions may hang
- indefinitely on the server, leaving M-bM-^@M-^\ghostM-bM-^@M-^] users and consuming
- server resources.
-
- The default is M-bM-^@M-^\yesM-bM-^@M-^] (to send TCP keepalive messages), and the
- server will notice if the network goes down or the client host
- crashes. This avoids infinitely hanging sessions.
-
- To disable TCP keepalive messages, the value should be set to
- M-bM-^@M-^\noM-bM-^@M-^].
-
- TrustedUserCAKeys
- Specifies a file containing public keys of certificate
- authorities that are trusted to sign user certificates for
- authentication. Keys are listed one per line; empty lines and
- comments starting with M-bM-^@M-^X#M-bM-^@M-^Y are allowed. If a certificate is
- presented for authentication and has its signing CA key listed in
- this file, then it may be used for authentication for any user
- listed in the certificate's principals list. Note that
- certificates that lack a list of principals will not be permitted
- for authentication using TrustedUserCAKeys. For more details on
- certificates, see the CERTIFICATES section in ssh-keygen(1).
-
- UseDNS Specifies whether sshd(8) should look up the remote host name and
- check that the resolved host name for the remote IP address maps
- back to the very same IP address. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- UseLogin
- Specifies whether login(1) is used for interactive login
- sessions. The default is M-bM-^@M-^\noM-bM-^@M-^]. Note that login(1) is never used
- for remote command execution. Note also, that if this is
- enabled, X11Forwarding will be disabled because login(1) does not
- know how to handle xauth(1) cookies. If UsePrivilegeSeparation
- is specified, it will be disabled after authentication.
-
- UsePAM Enables the Pluggable Authentication Module interface. If set to
- M-bM-^@M-^\yesM-bM-^@M-^] this will enable PAM authentication using
- ChallengeResponseAuthentication and PasswordAuthentication in
- addition to PAM account and session module processing for all
- authentication types.
-
- Because PAM challenge-response authentication usually serves an
- equivalent role to password authentication, you should disable
- either PasswordAuthentication or ChallengeResponseAuthentication.
-
- If UsePAM is enabled, you will not be able to run sshd(8) as a
- non-root user. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- UsePrivilegeSeparation
- Specifies whether sshd(8) separates privileges by creating an
- unprivileged child process to deal with incoming network traffic.
- After successful authentication, another process will be created
- that has the privilege of the authenticated user. The goal of
- privilege separation is to prevent privilege escalation by
- containing any corruption within the unprivileged processes. The
- default is M-bM-^@M-^\yesM-bM-^@M-^]. If UsePrivilegeSeparation is set to M-bM-^@M-^\sandboxM-bM-^@M-^]
- then the pre-authentication unprivileged process is subject to
- additional restrictions.
-
- VersionAddendum
- Optionally specifies additional text to append to the SSH
- protocol banner sent by the server upon connection. The default
- is M-bM-^@M-^\noneM-bM-^@M-^].
-
- X11DisplayOffset
- Specifies the first display number available for sshd(8)'s X11
- forwarding. This prevents sshd from interfering with real X11
- servers. The default is 10.
-
- X11Forwarding
- Specifies whether X11 forwarding is permitted. The argument must
- be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The default is M-bM-^@M-^\noM-bM-^@M-^].
-
- When X11 forwarding is enabled, there may be additional exposure
- to the server and to client displays if the sshd(8) proxy display
- is configured to listen on the wildcard address (see
- X11UseLocalhost below), though this is not the default.
- Additionally, the authentication spoofing and authentication data
- verification and substitution occur on the client side. The
- security risk of using X11 forwarding is that the client's X11
- display server may be exposed to attack when the SSH client
- requests forwarding (see the warnings for ForwardX11 in
- ssh_config(5)). A system administrator may have a stance in
- which they want to protect clients that may expose themselves to
- attack by unwittingly requesting X11 forwarding, which can
- warrant a M-bM-^@M-^\noM-bM-^@M-^] setting.
-
- Note that disabling X11 forwarding does not prevent users from
- forwarding X11 traffic, as users can always install their own
- forwarders. X11 forwarding is automatically disabled if UseLogin
- is enabled.
-
- X11UseLocalhost
- Specifies whether sshd(8) should bind the X11 forwarding server
- to the loopback address or to the wildcard address. By default,
- sshd binds the forwarding server to the loopback address and sets
- the hostname part of the DISPLAY environment variable to
- M-bM-^@M-^\localhostM-bM-^@M-^]. This prevents remote hosts from connecting to the
- proxy display. However, some older X11 clients may not function
- with this configuration. X11UseLocalhost may be set to M-bM-^@M-^\noM-bM-^@M-^] to
- specify that the forwarding server should be bound to the
- wildcard address. The argument must be M-bM-^@M-^\yesM-bM-^@M-^] or M-bM-^@M-^\noM-bM-^@M-^]. The
- default is M-bM-^@M-^\yesM-bM-^@M-^].
-
- XAuthLocation
- Specifies the full pathname of the xauth(1) program. The default
- is /usr/X11R6/bin/xauth.
-
-TIME FORMATS
- sshd(8) command-line arguments and configuration file options that
- specify time may be expressed using a sequence of the form:
- time[qualifier], where time is a positive integer value and qualifier is
- one of the following:
-
- M-bM-^_M-(noneM-bM-^_M-) seconds
- s | S seconds
- m | M minutes
- h | H hours
- d | D days
- w | W weeks
-
- Each member of the sequence is added together to calculate the total time
- value.
-
- Time format examples:
-
- 600 600 seconds (10 minutes)
- 10m 10 minutes
- 1h30m 1 hour 30 minutes (90 minutes)
-
-FILES
- /etc/ssh/sshd_config
- Contains configuration data for sshd(8). This file should be
- writable by root only, but it is recommended (though not
- necessary) that it be world-readable.
-
-SEE ALSO
- sshd(8)
-
-AUTHORS
- OpenSSH is a derivative of the original and free ssh 1.2.12 release by
- Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
- de Raadt and Dug Song removed many bugs, re-added newer features and
- created OpenSSH. Markus Friedl contributed the support for SSH protocol
- versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support
- for privilege separation.
-
-OpenBSD 5.7 February 20, 2015 OpenBSD 5.7
diff --git a/sshd_config.5 b/sshd_config.5
index 6dce0c70..b294efc2 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -33,15 +33,13 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: sshd_config.5,v 1.194 2015/02/20 23:46:01 djm Exp $
-.Dd $Mdocdate: February 20 2015 $
+.\" $OpenBSD: sshd_config.5,v 1.311 2020/04/17 06:12:41 jmc Exp $
+.Dd $Mdocdate: April 17 2020 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
.Nm sshd_config
-.Nd OpenSSH SSH daemon configuration file
-.Sh SYNOPSIS
-.Nm /etc/ssh/sshd_config
+.Nd OpenSSH daemon configuration file
.Sh DESCRIPTION
.Xr sshd 8
reads configuration data from
@@ -50,6 +48,7 @@ reads configuration data from
.Fl f
on the command line).
The file contains keyword-argument pairs, one per line.
+For each keyword, the first obtained value will be used.
Lines starting with
.Ql #
and empty lines are interpreted as comments.
@@ -67,10 +66,15 @@ the session's
.Xr environ 7 .
See
.Cm SendEnv
+and
+.Cm SetEnv
in
.Xr ssh_config 5
for how to configure the client.
-Note that environment passing is only supported for protocol 2.
+The
+.Ev TERM
+environment variable is always accepted whenever the client
+requests a pseudo-terminal as it is required by the protocol.
Variables are specified by name, which may contain the wildcard characters
.Ql *
and
@@ -87,19 +91,18 @@ The default is not to accept any environment variables.
Specifies which address family should be used by
.Xr sshd 8 .
Valid arguments are
-.Dq any ,
-.Dq inet
+.Cm any
+(the default),
+.Cm inet
(use IPv4 only), or
-.Dq inet6
+.Cm inet6
(use IPv6 only).
-The default is
-.Dq any .
.It Cm AllowAgentForwarding
Specifies whether
.Xr ssh-agent 1
forwarding is permitted.
The default is
-.Dq yes .
+.Cm yes .
Note that disabling agent forwarding does not improve security
unless users are also denied shell access, as they can always install
their own forwarders.
@@ -110,54 +113,49 @@ If specified, login is allowed only for users whose primary
group or supplementary group list matches one of the patterns.
Only group names are valid; a numerical group ID is not recognized.
By default, login is allowed for all groups.
-The allow/deny directives are processed in the following order:
-.Cm DenyUsers ,
-.Cm AllowUsers ,
+The allow/deny groups directives are processed in the following order:
.Cm DenyGroups ,
-and finally
.Cm AllowGroups .
.Pp
See PATTERNS in
.Xr ssh_config 5
for more information on patterns.
-.It Cm AllowTcpForwarding
-Specifies whether TCP forwarding is permitted.
+.It Cm AllowStreamLocalForwarding
+Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted.
The available options are
-.Dq yes
+.Cm yes
+(the default)
or
-.Dq all
-to allow TCP forwarding,
-.Dq no
-to prevent all TCP forwarding,
-.Dq local
+.Cm all
+to allow StreamLocal forwarding,
+.Cm no
+to prevent all StreamLocal forwarding,
+.Cm local
to allow local (from the perspective of
.Xr ssh 1 )
forwarding only or
-.Dq remote
+.Cm remote
to allow remote forwarding only.
-The default is
-.Dq yes .
-Note that disabling TCP forwarding does not improve security unless
+Note that disabling StreamLocal forwarding does not improve security unless
users are also denied shell access, as they can always install their
own forwarders.
-.It Cm AllowStreamLocalForwarding
-Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted.
+.It Cm AllowTcpForwarding
+Specifies whether TCP forwarding is permitted.
The available options are
-.Dq yes
+.Cm yes
+(the default)
or
-.Dq all
-to allow StreamLocal forwarding,
-.Dq no
-to prevent all StreamLocal forwarding,
-.Dq local
+.Cm all
+to allow TCP forwarding,
+.Cm no
+to prevent all TCP forwarding,
+.Cm local
to allow local (from the perspective of
.Xr ssh 1 )
forwarding only or
-.Dq remote
+.Cm remote
to allow remote forwarding only.
-The default is
-.Dq yes .
-Note that disabling StreamLocal forwarding does not improve security unless
+Note that disabling TCP forwarding does not improve security unless
users are also denied shell access, as they can always install their
own forwarders.
.It Cm AllowUsers
@@ -170,12 +168,11 @@ By default, login is allowed for all users.
If the pattern takes the form USER@HOST then USER and HOST
are separately checked, restricting logins to particular
users from particular hosts.
-The allow/deny directives are processed in the following order:
+HOST criteria may additionally contain addresses to match in CIDR
+address/masklen format.
+The allow/deny users directives are processed in the following order:
.Cm DenyUsers ,
-.Cm AllowUsers ,
-.Cm DenyGroups ,
-and finally
-.Cm AllowGroups .
+.Cm AllowUsers .
.Pp
See PATTERNS in
.Xr ssh_config 5
@@ -183,65 +180,84 @@ for more information on patterns.
.It Cm AuthenticationMethods
Specifies the authentication methods that must be successfully completed
for a user to be granted access.
-This option must be followed by one or more comma-separated lists of
-authentication method names.
-Successful authentication requires completion of every method in at least
-one of these lists.
+This option must be followed by one or more lists of comma-separated
+authentication method names, or by the single string
+.Cm any
+to indicate the default behaviour of accepting any single authentication
+method.
+If the default is overridden, then successful authentication requires
+completion of every method in at least one of these lists.
.Pp
-For example, an argument of
-.Dq publickey,password publickey,keyboard-interactive
+For example,
+.Qq publickey,password publickey,keyboard-interactive
would require the user to complete public key authentication, followed by
either password or keyboard interactive authentication.
Only methods that are next in one or more lists are offered at each stage,
-so for this example, it would not be possible to attempt password or
+so for this example it would not be possible to attempt password or
keyboard-interactive authentication before public key.
.Pp
For keyboard interactive authentication it is also possible to
restrict authentication to a specific device by appending a
colon followed by the device identifier
-.Dq bsdauth ,
-.Dq pam ,
+.Cm bsdauth
or
-.Dq skey ,
+.Cm pam .
depending on the server configuration.
For example,
-.Dq keyboard-interactive:bsdauth
+.Qq keyboard-interactive:bsdauth
would restrict keyboard interactive authentication to the
-.Dq bsdauth
+.Cm bsdauth
device.
.Pp
-If the
-.Dq publickey
-method is listed more than once,
+If the publickey method is listed more than once,
.Xr sshd 8
verifies that keys that have been used successfully are not reused for
subsequent authentications.
-For example, an
-.Cm AuthenticationMethods
-of
-.Dq publickey,publickey
-will require successful authentication using two different public keys.
-.Pp
-This option is only available for SSH protocol 2 and will yield a fatal
-error if enabled if protocol 1 is also enabled.
+For example,
+.Qq publickey,publickey
+requires successful authentication using two different public keys.
+.Pp
Note that each authentication method listed should also be explicitly enabled
in the configuration.
-The default is not to require multiple authentication; successful completion
-of a single authentication method is sufficient.
+.Pp
+The available authentication methods are:
+.Qq gssapi-with-mic ,
+.Qq hostbased ,
+.Qq keyboard-interactive ,
+.Qq none
+(used for access to password-less accounts when
+.Cm PermitEmptyPasswords
+is enabled),
+.Qq password
+and
+.Qq publickey .
.It Cm AuthorizedKeysCommand
Specifies a program to be used to look up the user's public keys.
-The program must be owned by root and not writable by group or others.
-It will be invoked with a single argument of the username
-being authenticated, and should produce on standard output zero or
-more lines of authorized_keys output (see AUTHORIZED_KEYS in
+The program must be owned by root, not writable by group or others and
+specified by an absolute path.
+Arguments to
+.Cm AuthorizedKeysCommand
+accept the tokens described in the
+.Sx TOKENS
+section.
+If no arguments are specified then the username of the target user is used.
+.Pp
+The program should produce on standard output zero or
+more lines of authorized_keys output (see
+.Sx AUTHORIZED_KEYS
+in
.Xr sshd 8 ) .
-If a key supplied by AuthorizedKeysCommand does not successfully authenticate
-and authorize the user then public key authentication continues using the usual
+.Cm AuthorizedKeysCommand
+is tried after the usual
.Cm AuthorizedKeysFile
-files.
-By default, no AuthorizedKeysCommand is run.
+files and will not be executed if a matching key is found there.
+By default, no
+.Cm AuthorizedKeysCommand
+is run.
.It Cm AuthorizedKeysCommandUser
-Specifies the user under whose account the AuthorizedKeysCommand is run.
+Specifies the user under whose account the
+.Cm AuthorizedKeysCommand
+is run.
It is recommended to use a dedicated user that has no other role on the host
than running authorized keys commands.
If
@@ -252,25 +268,63 @@ is not, then
.Xr sshd 8
will refuse to start.
.It Cm AuthorizedKeysFile
-Specifies the file that contains the public keys that can be used
-for user authentication.
-The format is described in the
-AUTHORIZED_KEYS FILE FORMAT
-section of
+Specifies the file that contains the public keys used for user authentication.
+The format is described in the AUTHORIZED_KEYS FILE FORMAT section of
.Xr sshd 8 .
+Arguments to
.Cm AuthorizedKeysFile
-may contain tokens of the form %T which are substituted during connection
-setup.
-The following tokens are defined: %% is replaced by a literal '%',
-%h is replaced by the home directory of the user being authenticated, and
-%u is replaced by the username of that user.
+accept the tokens described in the
+.Sx TOKENS
+section.
After expansion,
.Cm AuthorizedKeysFile
is taken to be an absolute path or one relative to the user's home
directory.
Multiple files may be listed, separated by whitespace.
+Alternately this option may be set to
+.Cm none
+to skip checking for user keys in files.
The default is
-.Dq .ssh/authorized_keys .ssh/authorized_keys2 .
+.Qq .ssh/authorized_keys .ssh/authorized_keys2 .
+.It Cm AuthorizedPrincipalsCommand
+Specifies a program to be used to generate the list of allowed
+certificate principals as per
+.Cm AuthorizedPrincipalsFile .
+The program must be owned by root, not writable by group or others and
+specified by an absolute path.
+Arguments to
+.Cm AuthorizedPrincipalsCommand
+accept the tokens described in the
+.Sx TOKENS
+section.
+If no arguments are specified then the username of the target user is used.
+.Pp
+The program should produce on standard output zero or
+more lines of
+.Cm AuthorizedPrincipalsFile
+output.
+If either
+.Cm AuthorizedPrincipalsCommand
+or
+.Cm AuthorizedPrincipalsFile
+is specified, then certificates offered by the client for authentication
+must contain a principal that is listed.
+By default, no
+.Cm AuthorizedPrincipalsCommand
+is run.
+.It Cm AuthorizedPrincipalsCommandUser
+Specifies the user under whose account the
+.Cm AuthorizedPrincipalsCommand
+is run.
+It is recommended to use a dedicated user that has no other role on the host
+than running authorized principals commands.
+If
+.Cm AuthorizedPrincipalsCommand
+is specified but
+.Cm AuthorizedPrincipalsCommandUser
+is not, then
+.Xr sshd 8
+will refuse to start.
.It Cm AuthorizedPrincipalsFile
Specifies a file that lists principal names that are accepted for
certificate authentication.
@@ -278,29 +332,28 @@ When using certificates signed by a key listed in
.Cm TrustedUserCAKeys ,
this file lists names, one of which must appear in the certificate for it
to be accepted for authentication.
-Names are listed one per line preceded by key options (as described
-in AUTHORIZED_KEYS FILE FORMAT in
+Names are listed one per line preceded by key options (as described in
+.Sx AUTHORIZED_KEYS FILE FORMAT
+in
.Xr sshd 8 ) .
Empty lines and comments starting with
.Ql #
are ignored.
.Pp
+Arguments to
.Cm AuthorizedPrincipalsFile
-may contain tokens of the form %T which are substituted during connection
-setup.
-The following tokens are defined: %% is replaced by a literal '%',
-%h is replaced by the home directory of the user being authenticated, and
-%u is replaced by the username of that user.
+accept the tokens described in the
+.Sx TOKENS
+section.
After expansion,
.Cm AuthorizedPrincipalsFile
-is taken to be an absolute path or one relative to the user's home
-directory.
-.Pp
+is taken to be an absolute path or one relative to the user's home directory.
The default is
-.Dq none ,
+.Cm none ,
i.e. not to use a principals file \(en in this case, the username
of the user must appear in a certificate's principals list for it to be
accepted.
+.Pp
Note that
.Cm AuthorizedPrincipalsFile
is only used when authentication proceeds using a CA listed in
@@ -316,16 +369,26 @@ for details).
The contents of the specified file are sent to the remote user before
authentication is allowed.
If the argument is
-.Dq none
+.Cm none
then no banner is displayed.
-This option is only available for protocol version 2.
By default, no banner is displayed.
+.It Cm CASignatureAlgorithms
+Specifies which algorithms are allowed for signing of certificates
+by certificate authorities (CAs).
+The default is:
+.Bd -literal -offset indent
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
+.Ed
+.Pp
+Certificates signed using other algorithms will not be accepted for
+public key or host-based authentication.
.It Cm ChallengeResponseAuthentication
Specifies whether challenge-response authentication is allowed (e.g. via
PAM or through authentication styles supported in
.Xr login.conf 5 )
The default is
-.Dq yes .
+.Cm yes .
.It Cm ChrootDirectory
Specifies the pathname of a directory to
.Xr chroot 2
@@ -337,11 +400,11 @@ which are not writable by any other user or group.
After the chroot,
.Xr sshd 8
changes the working directory to the user's home directory.
-.Pp
-The pathname may contain the following tokens that are expanded at runtime once
-the connecting user has been authenticated: %% is replaced by a literal '%',
-%h is replaced by the home directory of the user being authenticated, and
-%u is replaced by the username of that user.
+Arguments to
+.Cm ChrootDirectory
+accept the tokens described in the
+.Sx TOKENS
+section.
.Pp
The
.Cm ChrootDirectory
@@ -360,10 +423,9 @@ nodes such as
and
.Xr tty 4
devices.
-For file transfer sessions using
-.Dq sftp ,
-no additional configuration of the environment is necessary if the
-in-process sftp server is used,
+For file transfer sessions using SFTP
+no additional configuration of the environment is necessary if the in-process
+sftp-server is used,
though sessions which use logging may require
.Pa /dev/log
inside the chroot directory on some operating systems (see
@@ -377,11 +439,26 @@ Misconfiguration can lead to unsafe environments which
.Xr sshd 8
cannot detect.
.Pp
-The default is not to
+The default is
+.Cm none ,
+indicating not to
.Xr chroot 2 .
.It Cm Ciphers
-Specifies the ciphers allowed for protocol version 2.
+Specifies the ciphers allowed.
Multiple ciphers must be comma-separated.
+If the specified list begins with a
+.Sq +
+character, then the specified ciphers will be appended to the default set
+instead of replacing them.
+If the specified list begins with a
+.Sq -
+character, then the specified ciphers (including wildcards) will be removed
+from the default set instead of replacing them.
+If the specified list begins with a
+.Sq ^
+character, then the specified ciphers will be placed at the head of the
+default set.
+.Pp
The supported ciphers are:
.Pp
.Bl -item -compact -offset indent
@@ -404,59 +481,45 @@ aes128-gcm@openssh.com
.It
aes256-gcm@openssh.com
.It
-arcfour
-.It
-arcfour128
-.It
-arcfour256
-.It
-blowfish-cbc
-.It
-cast128-cbc
-.It
chacha20-poly1305@openssh.com
.El
.Pp
The default is:
.Bd -literal -offset indent
+chacha20-poly1305@openssh.com,
aes128-ctr,aes192-ctr,aes256-ctr,
-aes128-gcm@openssh.com,aes256-gcm@openssh.com,
-chacha20-poly1305@openssh.com
+aes128-gcm@openssh.com,aes256-gcm@openssh.com
.Ed
.Pp
-The list of available ciphers may also be obtained using the
-.Fl Q
-option of
-.Xr ssh 1
-with an argument of
-.Dq cipher .
+The list of available ciphers may also be obtained using
+.Qq ssh -Q cipher .
.It Cm ClientAliveCountMax
-Sets the number of client alive messages (see below) which may be
-sent without
+Sets the number of client alive messages which may be sent without
.Xr sshd 8
receiving any messages back from the client.
If this threshold is reached while client alive messages are being sent,
sshd will disconnect the client, terminating the session.
It is important to note that the use of client alive messages is very
different from
-.Cm TCPKeepAlive
-(below).
+.Cm TCPKeepAlive .
The client alive messages are sent through the encrypted channel
and therefore will not be spoofable.
The TCP keepalive option enabled by
.Cm TCPKeepAlive
is spoofable.
The client alive mechanism is valuable when the client or
-server depend on knowing when a connection has become inactive.
+server depend on knowing when a connection has become unresponsive.
.Pp
The default value is 3.
If
.Cm ClientAliveInterval
-(see below) is set to 15, and
+is set to 15, and
.Cm ClientAliveCountMax
is left at the default, unresponsive SSH clients
will be disconnected after approximately 45 seconds.
-This option applies to protocol version 2 only.
+Setting a zero
+.Cm ClientAliveCountMax
+disables connection termination.
.It Cm ClientAliveInterval
Sets a timeout interval in seconds after which if no data has been received
from the client,
@@ -465,17 +528,18 @@ will send a message through the encrypted
channel to request a response from the client.
The default
is 0, indicating that these messages will not be sent to the client.
-This option applies to protocol version 2 only.
.It Cm Compression
-Specifies whether compression is allowed, or delayed until
+Specifies whether compression is enabled after
the user has authenticated successfully.
The argument must be
-.Dq yes ,
-.Dq delayed ,
+.Cm yes ,
+.Cm delayed
+(a legacy synonym for
+.Cm yes )
or
-.Dq no .
+.Cm no .
The default is
-.Dq delayed .
+.Cm yes .
.It Cm DenyGroups
This keyword can be followed by a list of group name patterns, separated
by spaces.
@@ -483,11 +547,8 @@ Login is disallowed for users whose primary group or supplementary
group list matches one of the patterns.
Only group names are valid; a numerical group ID is not recognized.
By default, login is allowed for all groups.
-The allow/deny directives are processed in the following order:
-.Cm DenyUsers ,
-.Cm AllowUsers ,
+The allow/deny groups directives are processed in the following order:
.Cm DenyGroups ,
-and finally
.Cm AllowGroups .
.Pp
See PATTERNS in
@@ -502,24 +563,37 @@ By default, login is allowed for all users.
If the pattern takes the form USER@HOST then USER and HOST
are separately checked, restricting logins to particular
users from particular hosts.
-The allow/deny directives are processed in the following order:
+HOST criteria may additionally contain addresses to match in CIDR
+address/masklen format.
+The allow/deny users directives are processed in the following order:
.Cm DenyUsers ,
-.Cm AllowUsers ,
-.Cm DenyGroups ,
-and finally
-.Cm AllowGroups .
+.Cm AllowUsers .
.Pp
See PATTERNS in
.Xr ssh_config 5
for more information on patterns.
+.It Cm DisableForwarding
+Disables all forwarding features, including X11,
+.Xr ssh-agent 1 ,
+TCP and StreamLocal.
+This option overrides all other forwarding-related options and may
+simplify restricted configurations.
+.It Cm ExposeAuthInfo
+Writes a temporary file containing a list of authentication methods and
+public credentials (e.g. keys) used to authenticate the user.
+The location of the file is exposed to the user session through the
+.Ev SSH_USER_AUTH
+environment variable.
+The default is
+.Cm no .
.It Cm FingerprintHash
Specifies the hash algorithm used when logging key fingerprints.
Valid options are:
-.Dq md5
+.Cm md5
and
-.Dq sha256 .
+.Cm sha256 .
The default is
-.Dq sha256 .
+.Cm sha256 .
.It Cm ForceCommand
Forces the execution of the command specified by
.Cm ForceCommand ,
@@ -535,10 +609,12 @@ The command originally supplied by the client is available in the
.Ev SSH_ORIGINAL_COMMAND
environment variable.
Specifying a command of
-.Dq internal-sftp
-will force the use of an in-process sftp server that requires no support
+.Cm internal-sftp
+will force the use of an in-process SFTP server that requires no support
files when used with
.Cm ChrootDirectory .
+The default is
+.Cm none .
.It Cm GatewayPorts
Specifies whether remote hosts are allowed to connect to ports
forwarded for the client.
@@ -551,45 +627,77 @@ can be used to specify that sshd
should allow remote port forwardings to bind to non-loopback addresses, thus
allowing other hosts to connect.
The argument may be
-.Dq no
+.Cm no
to force remote port forwardings to be available to the local host only,
-.Dq yes
+.Cm yes
to force remote port forwardings to bind to the wildcard address, or
-.Dq clientspecified
+.Cm clientspecified
to allow the client to select the address to which the forwarding is bound.
The default is
-.Dq no .
+.Cm no .
.It Cm GSSAPIAuthentication
Specifies whether user authentication based on GSSAPI is allowed.
The default is
-.Dq no .
-Note that this option applies to protocol version 2 only.
+.Cm no .
.It Cm GSSAPICleanupCredentials
Specifies whether to automatically destroy the user's credentials cache
on logout.
The default is
-.Dq yes .
-Note that this option applies to protocol version 2 only.
+.Cm yes .
+.It Cm GSSAPIStrictAcceptorCheck
+Determines whether to be strict about the identity of the GSSAPI acceptor
+a client authenticates against.
+If set to
+.Cm yes
+then the client must authenticate against the host
+service on the current hostname.
+If set to
+.Cm no
+then the client may authenticate against any service key stored in the
+machine's default store.
+This facility is provided to assist with operation on multi homed machines.
+The default is
+.Cm yes .
.It Cm HostbasedAcceptedKeyTypes
Specifies the key types that will be accepted for hostbased authentication
-as a comma-separated pattern list.
-The default
-.Dq *
-will allow all key types.
-The
-.Fl Q
-option of
-.Xr ssh 1
-may be used to list supported key types.
+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.
+If the specified list begins with a
+.Sq -
+character, then the specified key types (including wildcards) will be removed
+from the default set instead of replacing them.
+If the specified list begins with a
+.Sq ^
+character, then the specified key types will be placed at the head of the
+default set.
+The default for this option is:
+.Bd -literal -offset 3n
+ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ecdsa-sha2-nistp384-cert-v01@openssh.com,
+ecdsa-sha2-nistp521-cert-v01@openssh.com,
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ssh-ed25519-cert-v01@openssh.com,
+sk-ssh-ed25519-cert-v01@openssh.com,
+rsa-sha2-512-cert-v01@openssh.com,
+rsa-sha2-256-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+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 .
.It Cm HostbasedAuthentication
Specifies whether rhosts or /etc/hosts.equiv authentication together
with successful public key client host authentication is allowed
(host-based authentication).
-This option is similar to
-.Cm RhostsRSAAuthentication
-and applies to protocol version 2 only.
The default is
-.Dq no .
+.Cm no .
.It Cm HostbasedUsesNameFromPacketOnly
Specifies whether or not the server will attempt to perform a reverse
name lookup when matching the name in the
@@ -600,13 +708,13 @@ and
files during
.Cm HostbasedAuthentication .
A setting of
-.Dq yes
+.Cm yes
means that
.Xr sshd 8
uses the name supplied by the client rather than
attempting to resolve the name from the TCP connection itself.
The default is
-.Dq no .
+.Cm no .
.It Cm HostCertificate
Specifies a file containing a public host certificate.
The certificate's public key must match a private host key already specified
@@ -618,27 +726,21 @@ is not to load any certificates.
.It Cm HostKey
Specifies a file containing a private host key
used by SSH.
-The default is
-.Pa /etc/ssh/ssh_host_key
-for protocol version 1, and
-.Pa /etc/ssh/ssh_host_dsa_key ,
+The defaults are
.Pa /etc/ssh/ssh_host_ecdsa_key ,
.Pa /etc/ssh/ssh_host_ed25519_key
and
-.Pa /etc/ssh/ssh_host_rsa_key
-for protocol version 2.
+.Pa /etc/ssh/ssh_host_rsa_key .
+.Pp
Note that
.Xr sshd 8
-will refuse to use a file if it is group/world-accessible.
+will refuse to use a file if it is group/world-accessible
+and that the
+.Cm HostKeyAlgorithms
+option restricts which of the keys are actually used by
+.Xr sshd 8 .
+.Pp
It is possible to have multiple host key files.
-.Dq rsa1
-keys are used for version 1 and
-.Dq dsa ,
-.Dq ecdsa ,
-.Dq ed25519
-or
-.Dq rsa
-are used for version 2 of the SSH protocol.
It is also possible to specify public host key files instead.
In this case operations on the private key will be delegated
to an
@@ -646,86 +748,137 @@ to an
.It Cm HostKeyAgent
Identifies the UNIX-domain socket used to communicate
with an agent that has access to the private host keys.
-If
-.Dq SSH_AUTH_SOCK
+If the string
+.Qq SSH_AUTH_SOCK
is specified, the location of the socket will be read from the
.Ev SSH_AUTH_SOCK
environment variable.
+.It Cm HostKeyAlgorithms
+Specifies the host key algorithms
+that the server offers.
+The default for this option is:
+.Bd -literal -offset 3n
+ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ecdsa-sha2-nistp384-cert-v01@openssh.com,
+ecdsa-sha2-nistp521-cert-v01@openssh.com,
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ssh-ed25519-cert-v01@openssh.com,
+sk-ssh-ed25519-cert-v01@openssh.com,
+rsa-sha2-512-cert-v01@openssh.com,
+rsa-sha2-256-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+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 HostKeyAlgorithms .
.It Cm IgnoreRhosts
-Specifies that
+Specifies whether to ignore per-user
.Pa .rhosts
and
.Pa .shosts
-files will not be used in
-.Cm RhostsRSAAuthentication
-or
+files during
.Cm HostbasedAuthentication .
-.Pp
+The system-wide
.Pa /etc/hosts.equiv
and
.Pa /etc/shosts.equiv
-are still used.
-The default is
-.Dq yes .
+are still used regardless of this setting.
+.Pp
+Accepted values are
+.Cm yes
+(the default) to ignore all per-user files,
+.Cm shosts-only
+to allow the use of
+.Pa .shosts
+but to ignore
+.Pa .rhosts
+or
+.Cm no
+to allow both
+.Pa .shosts
+and
+.Pa rhosts .
.It Cm IgnoreUserKnownHosts
Specifies whether
.Xr sshd 8
should ignore the user's
.Pa ~/.ssh/known_hosts
during
-.Cm RhostsRSAAuthentication
-or
-.Cm HostbasedAuthentication .
+.Cm HostbasedAuthentication
+and use only the system-wide known hosts file
+.Pa /etc/ssh/known_hosts .
The default is
.Dq no .
+.It Cm Include
+Include the specified configuration file(s).
+Multiple pathnames may be specified and each pathname may contain
+.Xr glob 7
+wildcards.
+Files without absolute paths are assumed to be in
+.Pa /etc/ssh .
+An
+.Cm Include
+directive may appear inside a
+.Cm Match
+block
+to perform conditional inclusion.
.It Cm IPQoS
Specifies the IPv4 type-of-service or DSCP class for the connection.
Accepted values are
-.Dq af11 ,
-.Dq af12 ,
-.Dq af13 ,
-.Dq af21 ,
-.Dq af22 ,
-.Dq af23 ,
-.Dq af31 ,
-.Dq af32 ,
-.Dq af33 ,
-.Dq af41 ,
-.Dq af42 ,
-.Dq af43 ,
-.Dq cs0 ,
-.Dq cs1 ,
-.Dq cs2 ,
-.Dq cs3 ,
-.Dq cs4 ,
-.Dq cs5 ,
-.Dq cs6 ,
-.Dq cs7 ,
-.Dq ef ,
-.Dq lowdelay ,
-.Dq throughput ,
-.Dq reliability ,
-or a numeric value.
+.Cm af11 ,
+.Cm af12 ,
+.Cm af13 ,
+.Cm af21 ,
+.Cm af22 ,
+.Cm af23 ,
+.Cm af31 ,
+.Cm af32 ,
+.Cm af33 ,
+.Cm af41 ,
+.Cm af42 ,
+.Cm af43 ,
+.Cm cs0 ,
+.Cm cs1 ,
+.Cm cs2 ,
+.Cm cs3 ,
+.Cm cs4 ,
+.Cm cs5 ,
+.Cm cs6 ,
+.Cm cs7 ,
+.Cm ef ,
+.Cm le ,
+.Cm lowdelay ,
+.Cm throughput ,
+.Cm reliability ,
+a numeric value, or
+.Cm none
+to use the operating system default.
This option may take one or two arguments, separated by whitespace.
If one argument is specified, it is used as the packet class unconditionally.
If two values are specified, the first is automatically selected for
interactive sessions and the second for non-interactive sessions.
The default is
-.Dq lowdelay
+.Cm af21
+(Low-Latency Data)
for interactive sessions and
-.Dq throughput
+.Cm cs1
+(Lower Effort)
for non-interactive sessions.
.It Cm KbdInteractiveAuthentication
Specifies whether to allow keyboard-interactive authentication.
The argument to this keyword must be
-.Dq yes
+.Cm yes
or
-.Dq no .
+.Cm no .
The default is to use whatever value
.Cm ChallengeResponseAuthentication
is set to
(by default
-.Dq yes ) .
+.Cm yes ) .
.It Cm KerberosAuthentication
Specifies whether the password provided by the user for
.Cm PasswordAuthentication
@@ -733,37 +886,57 @@ will be validated through the Kerberos KDC.
To use this option, the server needs a
Kerberos servtab which allows the verification of the KDC's identity.
The default is
-.Dq no .
+.Cm no .
.It Cm KerberosGetAFSToken
If AFS is active and the user has a Kerberos 5 TGT, attempt to acquire
an AFS token before accessing the user's home directory.
The default is
-.Dq no .
+.Cm no .
.It Cm KerberosOrLocalPasswd
If password authentication through Kerberos fails then
the password will be validated via any additional local mechanism
such as
.Pa /etc/passwd .
The default is
-.Dq yes .
+.Cm yes .
.It Cm KerberosTicketCleanup
Specifies whether to automatically destroy the user's ticket cache
file on logout.
The default is
-.Dq yes .
+.Cm yes .
.It Cm KexAlgorithms
Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.
+Alternately if the specified list begins with a
+.Sq +
+character, then the specified methods 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
+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
+default set.
The supported algorithms are:
.Pp
.Bl -item -compact -offset indent
.It
+curve25519-sha256
+.It
curve25519-sha256@libssh.org
.It
diffie-hellman-group1-sha1
.It
diffie-hellman-group14-sha1
.It
+diffie-hellman-group14-sha256
+.It
+diffie-hellman-group16-sha512
+.It
+diffie-hellman-group18-sha512
+.It
diffie-hellman-group-exchange-sha1
.It
diffie-hellman-group-exchange-sha256
@@ -773,31 +946,21 @@ ecdh-sha2-nistp256
ecdh-sha2-nistp384
.It
ecdh-sha2-nistp521
+.It
+sntrup4591761x25519-sha512@tinyssh.org
.El
.Pp
The default is:
.Bd -literal -offset indent
-curve25519-sha256@libssh.org,
+curve25519-sha256,curve25519-sha256@libssh.org,
ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
diffie-hellman-group-exchange-sha256,
-diffie-hellman-group14-sha1
+diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,
+diffie-hellman-group14-sha256
.Ed
.Pp
-The list of available key exchange algorithms may also be obtained using the
-.Fl Q
-option of
-.Xr ssh 1
-with an argument of
-.Dq kex .
-.It Cm KeyRegenerationInterval
-In protocol version 1, the ephemeral server key is automatically regenerated
-after this many seconds (if it has been used).
-The purpose of regeneration is to prevent
-decrypting captured sessions by later breaking into the machine and
-stealing the keys.
-The key is never stored anywhere.
-If the value is 0, the key is never regenerated.
-The default is 3600 (seconds).
+The list of available key exchange algorithms may also be obtained using
+.Qq ssh -Q KexAlgorithms .
.It Cm ListenAddress
Specifies the local addresses
.Xr sshd 8
@@ -808,34 +971,47 @@ The following forms may be used:
.It
.Cm ListenAddress
.Sm off
-.Ar host | Ar IPv4_addr | Ar IPv6_addr
+.Ar hostname | address
.Sm on
+.Op Cm rdomain Ar domain
.It
.Cm ListenAddress
.Sm off
-.Ar host | Ar IPv4_addr : Ar port
+.Ar hostname : port
.Sm on
+.Op Cm rdomain Ar domain
.It
.Cm ListenAddress
.Sm off
-.Oo
-.Ar host | Ar IPv6_addr Oc : Ar port
+.Ar IPv4_address : port
.Sm on
+.Op Cm rdomain Ar domain
+.It
+.Cm ListenAddress
+.Sm off
+.Oo Ar hostname | address Oc : Ar port
+.Sm on
+.Op Cm rdomain Ar domain
.El
.Pp
+The optional
+.Cm rdomain
+qualifier requests
+.Xr sshd 8
+listen in an explicit routing domain.
If
.Ar port
is not specified,
-sshd will listen on the address and all prior
+sshd will listen on the address and all
.Cm Port
options specified.
-The default is to listen on all local addresses.
+The default is to listen on all local addresses on the current default
+routing domain.
Multiple
.Cm ListenAddress
options are permitted.
-Additionally, any
-.Cm Port
-options must precede this option for non-port qualified addresses.
+For more information on routing domains, see
+.Xr rdomain 4 .
.It Cm LoginGraceTime
The server disconnects after this time if the user has not
successfully logged in.
@@ -852,11 +1028,23 @@ DEBUG2 and DEBUG3 each specify higher levels of debugging output.
Logging with a DEBUG level violates the privacy of users and is not recommended.
.It Cm MACs
Specifies the available MAC (message authentication code) algorithms.
-The MAC algorithm is used in protocol version 2
-for data integrity protection.
+The MAC algorithm is used for data integrity protection.
Multiple algorithms must be comma-separated.
+If the specified list begins with a
+.Sq +
+character, then the specified algorithms will be appended to the default set
+instead of replacing them.
+If the specified list begins with a
+.Sq -
+character, then the specified algorithms (including wildcards) will be removed
+from the default set instead of replacing them.
+If the specified list begins with a
+.Sq ^
+character, then the specified algorithms will be placed at the head of the
+default set.
+.Pp
The algorithms that contain
-.Dq -etm
+.Qq -etm
calculate the MAC after encryption (encrypt-then-mac).
These are considered safer and their use recommended.
The supported MACs are:
@@ -867,8 +1055,6 @@ hmac-md5
.It
hmac-md5-96
.It
-hmac-ripemd160
-.It
hmac-sha1
.It
hmac-sha1-96
@@ -885,8 +1071,6 @@ hmac-md5-etm@openssh.com
.It
hmac-md5-96-etm@openssh.com
.It
-hmac-ripemd160-etm@openssh.com
-.It
hmac-sha1-etm@openssh.com
.It
hmac-sha1-96-etm@openssh.com
@@ -904,16 +1088,13 @@ The default is:
.Bd -literal -offset indent
umac-64-etm@openssh.com,umac-128-etm@openssh.com,
hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
+hmac-sha1-etm@openssh.com,
umac-64@openssh.com,umac-128@openssh.com,
-hmac-sha2-256,hmac-sha2-512
+hmac-sha2-256,hmac-sha2-512,hmac-sha1
.Ed
.Pp
-The list of available MAC algorithms may also be obtained using the
-.Fl Q
-option of
-.Xr ssh 1
-with an argument of
-.Dq mac .
+The list of available MAC algorithms may also be obtained using
+.Qq ssh -Q mac .
.It Cm Match
Introduces a conditional block.
If all of the criteria on the
@@ -938,28 +1119,30 @@ The available criteria are
.Cm Host ,
.Cm LocalAddress ,
.Cm LocalPort ,
+.Cm RDomain ,
and
-.Cm Address .
+.Cm Address
+(with
+.Cm RDomain
+representing the
+.Xr rdomain 4
+on which the connection was received).
+.Pp
The match patterns may consist of single entries or comma-separated
lists and may use the wildcard and negation operators described in the
-PATTERNS section of
+.Sx PATTERNS
+section of
.Xr ssh_config 5 .
.Pp
The patterns in an
.Cm Address
criteria may additionally contain addresses to match in CIDR
-address/masklen format, e.g.\&
-.Dq 192.0.2.0/24
-or
-.Dq 3ffe:ffff::/32 .
+address/masklen format,
+such as 192.0.2.0/24 or 2001:db8::/32.
Note that the mask length provided must be consistent with the address -
it is an error to specify a mask length that is too long for the address
or one with bits set in this host portion of the address.
-For example,
-.Dq 192.0.2.0/33
-and
-.Dq 192.0.2.0/8
-respectively.
+For example, 192.0.2.0/33 and 192.0.2.0/8, respectively.
.Pp
Only a subset of keywords may be used on the lines following a
.Cm Match
@@ -975,9 +1158,13 @@ Available keywords are
.Cm AuthorizedKeysCommand ,
.Cm AuthorizedKeysCommandUser ,
.Cm AuthorizedKeysFile ,
+.Cm AuthorizedPrincipalsCommand ,
+.Cm AuthorizedPrincipalsCommandUser ,
.Cm AuthorizedPrincipalsFile ,
.Cm Banner ,
.Cm ChrootDirectory ,
+.Cm ClientAliveCountMax ,
+.Cm ClientAliveInterval ,
.Cm DenyGroups ,
.Cm DenyUsers ,
.Cm ForceCommand ,
@@ -986,13 +1173,17 @@ Available keywords are
.Cm HostbasedAcceptedKeyTypes ,
.Cm HostbasedAuthentication ,
.Cm HostbasedUsesNameFromPacketOnly ,
+.Cm IgnoreRhosts ,
+.Cm Include ,
.Cm IPQoS ,
.Cm KbdInteractiveAuthentication ,
.Cm KerberosAuthentication ,
+.Cm LogLevel ,
.Cm MaxAuthTries ,
.Cm MaxSessions ,
.Cm PasswordAuthentication ,
.Cm PermitEmptyPasswords ,
+.Cm PermitListen ,
.Cm PermitOpen ,
.Cm PermitRootLogin ,
.Cm PermitTTY ,
@@ -1002,15 +1193,15 @@ Available keywords are
.Cm PubkeyAuthentication ,
.Cm RekeyLimit ,
.Cm RevokedKeys ,
-.Cm RhostsRSAAuthentication ,
-.Cm RSAAuthentication ,
+.Cm RDomain ,
+.Cm SetEnv ,
.Cm StreamLocalBindMask ,
.Cm StreamLocalBindUnlink ,
.Cm TrustedUserCAKeys ,
.Cm X11DisplayOffset ,
.Cm X11Forwarding
and
-.Cm X11UseLocalHost .
+.Cm X11UseLocalhost .
.It Cm MaxAuthTries
Specifies the maximum number of authentication attempts permitted per
connection.
@@ -1018,7 +1209,15 @@ Once the number of failures reaches half this value,
additional failures are logged.
The default is 6.
.It Cm MaxSessions
-Specifies the maximum number of open sessions permitted per network connection.
+Specifies the maximum number of open shell, login or subsystem (e.g. sftp)
+sessions permitted per network connection.
+Multiple sessions may be established by clients that support connection
+multiplexing.
+Setting
+.Cm MaxSessions
+to 1 will effectively disable session multiplexing, whereas setting it to 0
+will prevent all shell, login and subsystem sessions while still permitting
+forwarding.
The default is 10.
.It Cm MaxStartups
Specifies the maximum number of concurrent unauthenticated connections to the
@@ -1030,29 +1229,63 @@ The default is 10:30:100.
.Pp
Alternatively, random early drop can be enabled by specifying
the three colon separated values
-.Dq start:rate:full
-(e.g. "10:30:60").
+start:rate:full (e.g. "10:30:60").
.Xr sshd 8
-will refuse connection attempts with a probability of
-.Dq rate/100
-(30%)
-if there are currently
-.Dq start
-(10)
-unauthenticated connections.
+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
-.Dq full
-(60).
+are refused if the number of unauthenticated connections reaches full (60).
.It Cm PasswordAuthentication
Specifies whether password authentication is allowed.
The default is
-.Dq yes .
+.Cm yes .
.It Cm PermitEmptyPasswords
When password authentication is allowed, it specifies whether the
server allows login to accounts with empty password strings.
The default is
-.Dq no .
+.Cm no .
+.It Cm PermitListen
+Specifies the addresses/ports on which a remote TCP port forwarding may listen.
+The listen specification must be one of the following forms:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm PermitListen
+.Sm off
+.Ar port
+.Sm on
+.It
+.Cm PermitListen
+.Sm off
+.Ar host : port
+.Sm on
+.El
+.Pp
+Multiple permissions may be specified by separating them with whitespace.
+An argument of
+.Cm any
+can be used to remove all restrictions and permit any listen requests.
+An argument of
+.Cm none
+can be used to prohibit all listen requests.
+The host name may contain wildcards as described in the PATTERNS section in
+.Xr ssh_config 5 .
+The wildcard
+.Sq *
+can also be used in place of a port number to allow all ports.
+By default all port forwarding listen requests are permitted.
+Note that the
+.Cm GatewayPorts
+option may further restrict which addresses may be listened on.
+Note also that
+.Xr ssh 1
+will request a listen host of
+.Dq localhost
+if no listen host was specifically requested, and this name is
+treated differently to explicit localhost addresses of
+.Dq 127.0.0.1
+and
+.Dq ::1 .
.It Cm PermitOpen
Specifies the destinations to which TCP port forwarding is permitted.
The forwarding specification must be one of the following forms:
@@ -1077,30 +1310,37 @@ The forwarding specification must be one of the following forms:
.Pp
Multiple forwards may be specified by separating them with whitespace.
An argument of
-.Dq any
+.Cm any
can be used to remove all restrictions and permit any forwarding requests.
An argument of
-.Dq none
+.Cm none
can be used to prohibit all forwarding requests.
+The wildcard
+.Sq *
+can be used for host or port to allow all hosts or ports respectively.
+Otherwise, no pattern matching or address lookups are performed on supplied
+names.
By default all port forwarding requests are permitted.
.It Cm PermitRootLogin
Specifies whether root can log in using
.Xr ssh 1 .
The argument must be
-.Dq yes ,
-.Dq without-password ,
-.Dq forced-commands-only ,
+.Cm yes ,
+.Cm prohibit-password ,
+.Cm forced-commands-only ,
or
-.Dq no .
+.Cm no .
The default is
-.Dq yes .
+.Cm prohibit-password .
.Pp
If this option is set to
-.Dq without-password ,
-password authentication is disabled for root.
+.Cm prohibit-password
+(or its deprecated alias,
+.Cm without-password ) ,
+password and keyboard-interactive authentication are disabled for root.
.Pp
If this option is set to
-.Dq forced-commands-only ,
+.Cm forced-commands-only ,
root login with public key authentication will be allowed,
but only if the
.Ar command
@@ -1110,37 +1350,37 @@ normally not allowed).
All other authentication methods are disabled for root.
.Pp
If this option is set to
-.Dq no ,
+.Cm no ,
root is not allowed to log in.
+.It Cm PermitTTY
+Specifies whether
+.Xr pty 4
+allocation is permitted.
+The default is
+.Cm yes .
.It Cm PermitTunnel
Specifies whether
.Xr tun 4
device forwarding is allowed.
The argument must be
-.Dq yes ,
-.Dq point-to-point
+.Cm yes ,
+.Cm point-to-point
(layer 3),
-.Dq ethernet
+.Cm ethernet
(layer 2), or
-.Dq no .
+.Cm no .
Specifying
-.Dq yes
+.Cm yes
permits both
-.Dq point-to-point
+.Cm point-to-point
and
-.Dq ethernet .
+.Cm ethernet .
The default is
-.Dq no .
+.Cm no .
.Pp
Independent of this setting, the permissions of the selected
.Xr tun 4
device must allow access to the user.
-.It Cm PermitTTY
-Specifies whether
-.Xr pty 4
-allocation is permitted.
-The default is
-.Dq yes .
.It Cm PermitUserEnvironment
Specifies whether
.Pa ~/.ssh/environment
@@ -1150,8 +1390,14 @@ options in
.Pa ~/.ssh/authorized_keys
are processed by
.Xr sshd 8 .
+Valid options are
+.Cm yes ,
+.Cm no
+or a pattern-list specifying which environment variable names to accept
+(for example
+.Qq LANG,LC_* ) .
The default is
-.Dq no .
+.Cm no .
Enabling environment processing may enable users to bypass access
restrictions in some configurations using mechanisms such as
.Ev LD_PRELOAD .
@@ -1160,10 +1406,12 @@ Specifies whether any
.Pa ~/.ssh/rc
file is executed.
The default is
-.Dq yes .
+.Cm yes .
.It Cm PidFile
Specifies the file that contains the process ID of the
-SSH daemon.
+SSH daemon, or
+.Cm none
+to not write one.
The default is
.Pa /var/run/sshd.pid .
.It Cm Port
@@ -1180,7 +1428,7 @@ Specifies whether
should print the date and time of the last user login when a user logs
in interactively.
The default is
-.Dq yes .
+.Cm yes .
.It Cm PrintMotd
Specifies whether
.Xr sshd 8
@@ -1191,41 +1439,69 @@ when a user logs in interactively.
.Pa /etc/profile ,
or equivalent.)
The default is
-.Dq yes .
-.It Cm Protocol
-Specifies the protocol versions
-.Xr sshd 8
-supports.
-The possible values are
-.Sq 1
-and
-.Sq 2 .
-Multiple versions must be comma-separated.
-The default is
-.Sq 2 .
-Note that the order of the protocol list does not indicate preference,
-because the client selects among multiple protocol versions offered
-by the server.
-Specifying
-.Dq 2,1
-is identical to
-.Dq 1,2 .
+.Cm yes .
.It Cm PubkeyAcceptedKeyTypes
Specifies the key types that will be accepted for public key authentication
-as a comma-separated pattern list.
-The default
-.Dq *
-will allow all key types.
+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.
+If the specified list begins with a
+.Sq -
+character, then the specified key types (including wildcards) will be removed
+from the default set instead of replacing them.
+If the specified list begins with a
+.Sq ^
+character, then the specified key types will be placed at the head of the
+default set.
+The default for this option is:
+.Bd -literal -offset 3n
+ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ecdsa-sha2-nistp384-cert-v01@openssh.com,
+ecdsa-sha2-nistp521-cert-v01@openssh.com,
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ssh-ed25519-cert-v01@openssh.com,
+sk-ssh-ed25519-cert-v01@openssh.com,
+rsa-sha2-512-cert-v01@openssh.com,
+rsa-sha2-256-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+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 .
+.It Cm PubkeyAuthOptions
+Sets one or more public key authentication options.
+Two option keywords are currently supported:
+.Cm none
+(the default; indicating no additional options are enabled)
+and
+.Cm touch-required .
+.Pp
The
-.Fl Q
-option of
-.Xr ssh 1
-may be used to list supported key types.
+.Cm touch-required
+option causes public key authentication using a FIDO authenticator algorithm
+(i.e.\&
+.Cm ecdsa-sk
+or
+.Cm ed25519-sk )
+to always require the signature to attest that a physically present user
+explicitly confirmed the authentication (usually by touching the authenticator).
+By default,
+.Xr sshd 8
+requires user presence unless overridden with an authorized_keys option.
+The
+.Cm touch-required
+flag disables this override.
+This option has no effect for other, non-authenticator public key types.
.It Cm PubkeyAuthentication
Specifies whether public key authentication is allowed.
The default is
-.Dq yes .
-Note that this option applies to protocol version 2 only.
+.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
@@ -1248,12 +1524,13 @@ section.
The default value for
.Cm RekeyLimit
is
-.Dq default none ,
+.Cm default none ,
which means that rekeying is performed after the cipher's default amount
of data has been sent or received and no time based rekeying is done.
-This option applies to protocol version 2 only.
.It Cm RevokedKeys
-Specifies revoked public keys.
+Specifies revoked public keys file, or
+.Cm none
+to not use one.
Keys listed in this file will be refused for public key authentication.
Note that if this file is not readable, then public key authentication will
be refused for all users.
@@ -1262,20 +1539,34 @@ an OpenSSH Key Revocation List (KRL) as generated by
.Xr ssh-keygen 1 .
For more information on KRLs, see the KEY REVOCATION LISTS section in
.Xr ssh-keygen 1 .
-.It Cm RhostsRSAAuthentication
-Specifies whether rhosts or /etc/hosts.equiv authentication together
-with successful RSA host authentication is allowed.
-The default is
-.Dq no .
-This option applies to protocol version 1 only.
-.It Cm RSAAuthentication
-Specifies whether pure RSA authentication is allowed.
-The default is
-.Dq yes .
-This option applies to protocol version 1 only.
-.It Cm ServerKeyBits
-Defines the number of bits in the ephemeral protocol version 1 server key.
-The minimum value is 512, and the default is 1024.
+.It Cm RDomain
+Specifies an explicit routing domain that is applied after authentication
+has completed.
+The user session, as well and any forwarded or listening IP sockets,
+will be bound to this
+.Xr rdomain 4 .
+If the routing domain is set to
+.Cm \&%D ,
+then the domain in which the incoming connection was received will be applied.
+.It Cm SecurityKeyProvider
+Specifies a path to a library that will be used when loading
+FIDO authenticator-hosted keys, overriding the default of using
+the built-in USB HID support.
+.It Cm SetEnv
+Specifies one or more environment variables to set in child sessions started
+by
+.Xr sshd 8
+as
+.Dq NAME=VALUE .
+The environment value may be quoted (e.g. if it contains whitespace
+characters).
+Environment variables set by
+.Cm SetEnv
+override the default environment and any variables specified by the user
+via
+.Cm AcceptEnv
+or
+.Cm PermitUserEnvironment .
.It Cm StreamLocalBindMask
Sets the octal file creation mode mask
.Pq umask
@@ -1298,11 +1589,11 @@ will be unable to forward the port to the Unix-domain socket file.
This option is only used for port forwarding to a Unix-domain socket file.
.Pp
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
+.Cm no .
The default is
-.Dq no .
+.Cm no .
.It Cm StrictModes
Specifies whether
.Xr sshd 8
@@ -1311,7 +1602,7 @@ user's files and home directory before accepting login.
This is normally desirable because novices sometimes accidentally leave their
directory or files world-writable.
The default is
-.Dq yes .
+.Cm yes .
Note that this does not apply to
.Cm ChrootDirectory ,
whose permissions and ownership are checked unconditionally.
@@ -1321,22 +1612,17 @@ Arguments should be a subsystem name and a command (with optional arguments)
to execute upon subsystem request.
.Pp
The command
-.Xr sftp-server 8
-implements the
-.Dq sftp
-file transfer subsystem.
+.Cm sftp-server
+implements the SFTP file transfer subsystem.
.Pp
Alternately the name
-.Dq internal-sftp
-implements an in-process
-.Dq sftp
-server.
+.Cm internal-sftp
+implements an in-process SFTP server.
This may simplify configurations using
.Cm ChrootDirectory
to force a different filesystem root on clients.
.Pp
By default no subsystems are defined.
-Note that this option applies to protocol version 2 only.
.It Cm SyslogFacility
Gives the facility code that is used when logging messages from
.Xr sshd 8 .
@@ -1353,20 +1639,22 @@ connections will die if the route is down temporarily, and some people
find it annoying.
On the other hand, if TCP keepalives are not sent,
sessions may hang indefinitely on the server, leaving
-.Dq ghost
+.Qq ghost
users and consuming server resources.
.Pp
The default is
-.Dq yes
+.Cm yes
(to send TCP keepalive messages), and the server will notice
if the network goes down or the client host crashes.
This avoids infinitely hanging sessions.
.Pp
To disable TCP keepalive messages, the value should be set to
-.Dq no .
+.Cm no .
.It Cm TrustedUserCAKeys
Specifies a file containing public keys of certificate authorities that are
-trusted to sign user certificates for authentication.
+trusted to sign user certificates for authentication, or
+.Cm none
+to not use one.
Keys are listed one per line; empty lines and comments starting with
.Ql #
are allowed.
@@ -1381,34 +1669,24 @@ For more details on certificates, see the CERTIFICATES section in
.It Cm UseDNS
Specifies whether
.Xr sshd 8
-should look up the remote host name and check that
+should look up the remote host name, and to check that
the resolved host name for the remote IP address maps back to the
very same IP address.
-The default is
-.Dq no .
-.It Cm UseLogin
-Specifies whether
-.Xr login 1
-is used for interactive login sessions.
-The default is
-.Dq no .
-Note that
-.Xr login 1
-is never used for remote command execution.
-Note also, that if this is enabled,
-.Cm X11Forwarding
-will be disabled because
-.Xr login 1
-does not know how to handle
-.Xr xauth 1
-cookies.
-If
-.Cm UsePrivilegeSeparation
-is specified, it will be disabled after authentication.
+.Pp
+If this option is set to
+.Cm no
+(the default) then only addresses and not host names may be used in
+.Pa ~/.ssh/authorized_keys
+.Cm from
+and
+.Nm
+.Cm Match
+.Cm Host
+directives.
.It Cm UsePAM
Enables the Pluggable Authentication Module interface.
If set to
-.Dq yes
+.Cm yes
this will enable PAM authentication using
.Cm ChallengeResponseAuthentication
and
@@ -1428,29 +1706,12 @@ is enabled, you will not be able to run
.Xr sshd 8
as a non-root user.
The default is
-.Dq no .
-.It Cm UsePrivilegeSeparation
-Specifies whether
-.Xr sshd 8
-separates privileges by creating an unprivileged child process
-to deal with incoming network traffic.
-After successful authentication, another process will be created that has
-the privilege of the authenticated user.
-The goal of privilege separation is to prevent privilege
-escalation by containing any corruption within the unprivileged processes.
-The default is
-.Dq yes .
-If
-.Cm UsePrivilegeSeparation
-is set to
-.Dq sandbox
-then the pre-authentication unprivileged process is subject to additional
-restrictions.
+.Cm no .
.It Cm VersionAddendum
Optionally specifies additional text to append to the SSH protocol banner
sent by the server upon connection.
The default is
-.Dq none .
+.Cm none .
.It Cm X11DisplayOffset
Specifies the first display number available for
.Xr sshd 8 Ns 's
@@ -1460,18 +1721,18 @@ The default is 10.
.It Cm X11Forwarding
Specifies whether X11 forwarding is permitted.
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
+.Cm no .
The default is
-.Dq no .
+.Cm no .
.Pp
When X11 forwarding is enabled, there may be additional exposure to
the server and to client displays if the
.Xr sshd 8
proxy display is configured to listen on the wildcard address (see
-.Cm X11UseLocalhost
-below), though this is not the default.
+.Cm X11UseLocalhost ) ,
+though this is not the default.
Additionally, the authentication spoofing and authentication data
verification and substitution occur on the client side.
The security risk of using X11 forwarding is that the client's X11
@@ -1483,14 +1744,11 @@ in
A system administrator may have a stance in which they want to
protect clients that may expose themselves to attack by unwittingly
requesting X11 forwarding, which can warrant a
-.Dq no
+.Cm no
setting.
.Pp
Note that disabling X11 forwarding does not prevent users from
forwarding X11 traffic, as users can always install their own forwarders.
-X11 forwarding is automatically disabled if
-.Cm UseLogin
-is enabled.
.It Cm X11UseLocalhost
Specifies whether
.Xr sshd 8
@@ -1501,25 +1759,27 @@ sshd binds the forwarding server to the loopback address and sets the
hostname part of the
.Ev DISPLAY
environment variable to
-.Dq localhost .
+.Cm localhost .
This prevents remote hosts from connecting to the proxy display.
However, some older X11 clients may not function with this
configuration.
.Cm X11UseLocalhost
may be set to
-.Dq no
+.Cm no
to specify that the forwarding server should be bound to the wildcard
address.
The argument must be
-.Dq yes
+.Cm yes
or
-.Dq no .
+.Cm no .
The default is
-.Dq yes .
+.Cm yes .
.It Cm XAuthLocation
Specifies the full pathname of the
.Xr xauth 1
-program.
+program, or
+.Cm none
+to not use one.
The default is
.Pa /usr/X11R6/bin/xauth .
.El
@@ -1564,6 +1824,57 @@ Time format examples:
.It 1h30m
1 hour 30 minutes (90 minutes)
.El
+.Sh TOKENS
+Arguments to some keywords can make use of tokens,
+which are expanded at runtime:
+.Pp
+.Bl -tag -width XXXX -offset indent -compact
+.It %%
+A literal
+.Sq % .
+.It \&%D
+The routing domain in which the incoming connection was received.
+.It %F
+The fingerprint of the CA key.
+.It %f
+The fingerprint of the key or certificate.
+.It %h
+The home directory of the user.
+.It %i
+The key ID in the certificate.
+.It %K
+The base64-encoded CA key.
+.It %k
+The base64-encoded key or certificate for authentication.
+.It %s
+The serial number of the certificate.
+.It \&%T
+The type of the CA key.
+.It %t
+The key or certificate type.
+.It \&%U
+The numeric user ID of the target user.
+.It %u
+The username.
+.El
+.Pp
+.Cm AuthorizedKeysCommand
+accepts the tokens %%, %f, %h, %k, %t, %U, and %u.
+.Pp
+.Cm AuthorizedKeysFile
+accepts the tokens %%, %h, %U, and %u.
+.Pp
+.Cm AuthorizedPrincipalsCommand
+accepts the tokens %%, %F, %f, %h, %i, %K, %k, %s, %T, %t, %U, and %u.
+.Pp
+.Cm AuthorizedPrincipalsFile
+accepts the tokens %%, %h, %U, and %u.
+.Pp
+.Cm ChrootDirectory
+accepts the tokens %%, %h, %U, and %u.
+.Pp
+.Cm RoutingDomain
+accepts the token %D.
.Sh FILES
.Bl -tag -width Ds
.It Pa /etc/ssh/sshd_config
@@ -1573,15 +1884,22 @@ This file should be writable by root only, but it is recommended
(though not necessary) that it be world-readable.
.El
.Sh SEE ALSO
+.Xr sftp-server 8 ,
.Xr sshd 8
.Sh AUTHORS
+.An -nosplit
OpenSSH is a derivative of the original and free
-ssh 1.2.12 release by Tatu Ylonen.
-Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
-Theo de Raadt and Dug Song
+ssh 1.2.12 release by
+.An Tatu Ylonen .
+.An Aaron Campbell , Bob Beck , Markus Friedl , Niels Provos ,
+.An Theo de Raadt
+and
+.An Dug Song
removed many bugs, re-added newer features and
created OpenSSH.
-Markus Friedl contributed the support for SSH
-protocol versions 1.5 and 2.0.
-Niels Provos and Markus Friedl contributed support
-for privilege separation.
+.An Markus Friedl
+contributed the support for SSH protocol versions 1.5 and 2.0.
+.An Niels Provos
+and
+.An Markus Friedl
+contributed support for privilege separation.
diff --git a/sshd_config.android b/sshd_config.android
index 3f3aa427..211ac528 100644
--- a/sshd_config.android
+++ b/sshd_config.android
@@ -1,120 +1,5 @@
-# $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $
-
-# This is the sshd server system-wide configuration file. See
-# sshd_config(5) for more information.
-
-# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
-
-# The strategy used for options in the default sshd_config shipped with
-# OpenSSH is to specify options with their default value where
-# possible, but leave them commented. Uncommented options override the
-# default value.
-
-#Port 22
-#AddressFamily any
-#ListenAddress 0.0.0.0
-#ListenAddress ::
-
-# The default requires explicit activation of protocol 1
Protocol 2
-
-# HostKey for protocol version 1
-#HostKey /etc/ssh/ssh_host_key
-# HostKeys for protocol version 2
HostKey /data/ssh/ssh_host_rsa_key
HostKey /data/ssh/ssh_host_dsa_key
-
-# Lifetime and size of ephemeral version 1 server key
-#KeyRegenerationInterval 1h
-#ServerKeyBits 1024
-
-# Logging
-# obsoletes QuietMode and FascistLogging
-#SyslogFacility AUTH
-#LogLevel INFO
-
-# Authentication:
-
-#LoginGraceTime 2m
-#PermitRootLogin yes
-#StrictModes yes
-#MaxAuthTries 6
-#MaxSessions 10
-
-#RSAAuthentication yes
-#PubkeyAuthentication yes
-
-# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
-# but this is overridden so installations will only check .ssh/authorized_keys
-AuthorizedKeysFile /data/ssh/authorized_keys
-
-# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
-#RhostsRSAAuthentication no
-# similar for protocol version 2
-#HostbasedAuthentication no
-# Change to yes if you don't trust ~/.ssh/known_hosts for
-# RhostsRSAAuthentication and HostbasedAuthentication
-#IgnoreUserKnownHosts no
-# Don't read the user's ~/.rhosts and ~/.shosts files
-#IgnoreRhosts yes
-
-# To disable tunneled clear text passwords, change to no here!
+AuthorizedKeysFile /data/ssh/authorized_keys
PasswordAuthentication no
-#PermitEmptyPasswords no
-
-# Change to no to disable s/key passwords
-#ChallengeResponseAuthentication yes
-
-# Kerberos options
-#KerberosAuthentication no
-#KerberosOrLocalPasswd yes
-#KerberosTicketCleanup yes
-#KerberosGetAFSToken no
-
-# GSSAPI options
-#GSSAPIAuthentication no
-#GSSAPICleanupCredentials yes
-
-# 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
-# PasswordAuthentication. Depending on your PAM configuration,
-# PAM authentication via ChallengeResponseAuthentication 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'.
-#UsePAM no
-
-#AllowAgentForwarding yes
-#AllowTcpForwarding yes
-#GatewayPorts no
-#X11Forwarding no
-#X11DisplayOffset 10
-#X11UseLocalhost yes
-#PrintMotd yes
-#PrintLastLog yes
-#TCPKeepAlive yes
-#UseLogin no
-#UsePrivilegeSeparation yes
-#PermitUserEnvironment no
-#Compression delayed
-#ClientAliveInterval 0
-#ClientAliveCountMax 3
-#UseDNS yes
-#PidFile /var/run/sshd.pid
-#MaxStartups 10
-#PermitTunnel no
-#ChrootDirectory none
-
-# no default banner path
-#Banner none
-
-# override default of no subsystems
-Subsystem sftp /usr/libexec/sftp-server
-
-# Example of overriding settings on a per-user basis
-#Match User anoncvs
-# X11Forwarding no
-# AllowTcpForwarding no
-# ForceCommand cvs server
diff --git a/ssherr.c b/ssherr.c
index 4ca79399..bd954aad 100644
--- a/ssherr.c
+++ b/ssherr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssherr.c,v 1.4 2015/02/16 22:13:32 djm Exp $ */
+/* $OpenBSD: ssherr.c,v 1.10 2020/01/25 23:13:09 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -104,7 +104,7 @@ ssh_err(int n)
case SSH_ERR_NEED_REKEY:
return "rekeying not supported by peer";
case SSH_ERR_PASSPHRASE_TOO_SHORT:
- return "passphrase is too short (minimum four characters)";
+ return "passphrase is too short (minimum five characters)";
case SSH_ERR_FILE_CHANGED:
return "file changed while reading";
case SSH_ERR_KEY_UNKNOWN_CIPHER:
@@ -135,6 +135,16 @@ ssh_err(int n)
return "Connection corrupted";
case SSH_ERR_PROTOCOL_ERROR:
return "Protocol error";
+ case SSH_ERR_KEY_LENGTH:
+ return "Invalid key length";
+ case SSH_ERR_NUMBER_TOO_LARGE:
+ return "number is too large";
+ case SSH_ERR_SIGN_ALG_UNSUPPORTED:
+ return "signature algorithm not supported";
+ case SSH_ERR_FEATURE_UNSUPPORTED:
+ return "requested feature not supported";
+ case SSH_ERR_DEVICE_NOT_FOUND:
+ return "device not found";
default:
return "unknown error";
}
diff --git a/ssherr.h b/ssherr.h
index 6f771b4b..085e7527 100644
--- a/ssherr.h
+++ b/ssherr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssherr.h,v 1.3 2015/01/30 01:13:33 djm Exp $ */
+/* $OpenBSD: ssherr.h,v 1.8 2020/01/25 23:13:09 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -77,6 +77,11 @@
#define SSH_ERR_CONN_TIMEOUT -53
#define SSH_ERR_CONN_CORRUPT -54
#define SSH_ERR_PROTOCOL_ERROR -55
+#define SSH_ERR_KEY_LENGTH -56
+#define SSH_ERR_NUMBER_TOO_LARGE -57
+#define SSH_ERR_SIGN_ALG_UNSUPPORTED -58
+#define SSH_ERR_FEATURE_UNSUPPORTED -59
+#define SSH_ERR_DEVICE_NOT_FOUND -60
/* Translate a numeric error code to a human-readable error string */
const char *ssh_err(int n);
diff --git a/sshkey-xmss.c b/sshkey-xmss.c
new file mode 100644
index 00000000..88e9ddf4
--- /dev/null
+++ b/sshkey-xmss.c
@@ -0,0 +1,1112 @@
+/* $OpenBSD: sshkey-xmss.c,v 1.8 2019/11/13 07:53:10 markus Exp $ */
+/*
+ * Copyright (c) 2017 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+#ifdef WITH_XMSS
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_SYS_FILE_H
+# include <sys/file.h>
+#endif
+
+#include "ssh2.h"
+#include "ssherr.h"
+#include "sshbuf.h"
+#include "cipher.h"
+#include "sshkey.h"
+#include "sshkey-xmss.h"
+#include "atomicio.h"
+
+#include "xmss_fast.h"
+
+/* opaque internal XMSS state */
+#define XMSS_MAGIC "xmss-state-v1"
+#define XMSS_CIPHERNAME "aes256-gcm@openssh.com"
+struct ssh_xmss_state {
+ xmss_params params;
+ u_int32_t n, w, h, k;
+
+ bds_state bds;
+ u_char *stack;
+ u_int32_t stackoffset;
+ u_char *stacklevels;
+ u_char *auth;
+ u_char *keep;
+ u_char *th_nodes;
+ u_char *retain;
+ treehash_inst *treehash;
+
+ u_int32_t idx; /* state read from file */
+ u_int32_t maxidx; /* restricted # of signatures */
+ int have_state; /* .state file exists */
+ int lockfd; /* locked in sshkey_xmss_get_state() */
+ u_char allow_update; /* allow sshkey_xmss_update_state() */
+ char *enc_ciphername;/* encrypt state with cipher */
+ u_char *enc_keyiv; /* encrypt state with key */
+ u_int32_t enc_keyiv_len; /* length of enc_keyiv */
+};
+
+int sshkey_xmss_init_bds_state(struct sshkey *);
+int sshkey_xmss_init_enc_key(struct sshkey *, const char *);
+void sshkey_xmss_free_bds(struct sshkey *);
+int sshkey_xmss_get_state_from_file(struct sshkey *, const char *,
+ int *, sshkey_printfn *);
+int sshkey_xmss_encrypt_state(const struct sshkey *, struct sshbuf *,
+ struct sshbuf **);
+int sshkey_xmss_decrypt_state(const struct sshkey *, struct sshbuf *,
+ struct sshbuf **);
+int sshkey_xmss_serialize_enc_key(const struct sshkey *, struct sshbuf *);
+int sshkey_xmss_deserialize_enc_key(struct sshkey *, struct sshbuf *);
+
+#define PRINT(s...) do { if (pr) pr(s); } while (0)
+
+int
+sshkey_xmss_init(struct sshkey *key, const char *name)
+{
+ struct ssh_xmss_state *state;
+
+ if (key->xmss_state != NULL)
+ return SSH_ERR_INVALID_FORMAT;
+ if (name == NULL)
+ return SSH_ERR_INVALID_FORMAT;
+ state = calloc(sizeof(struct ssh_xmss_state), 1);
+ if (state == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if (strcmp(name, XMSS_SHA2_256_W16_H10_NAME) == 0) {
+ state->n = 32;
+ state->w = 16;
+ state->h = 10;
+ } else if (strcmp(name, XMSS_SHA2_256_W16_H16_NAME) == 0) {
+ state->n = 32;
+ state->w = 16;
+ state->h = 16;
+ } else if (strcmp(name, XMSS_SHA2_256_W16_H20_NAME) == 0) {
+ state->n = 32;
+ state->w = 16;
+ state->h = 20;
+ } else {
+ free(state);
+ return SSH_ERR_KEY_TYPE_UNKNOWN;
+ }
+ if ((key->xmss_name = strdup(name)) == NULL) {
+ free(state);
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ state->k = 2; /* XXX hardcoded */
+ state->lockfd = -1;
+ if (xmss_set_params(&state->params, state->n, state->h, state->w,
+ state->k) != 0) {
+ free(state);
+ return SSH_ERR_INVALID_FORMAT;
+ }
+ key->xmss_state = state;
+ return 0;
+}
+
+void
+sshkey_xmss_free_state(struct sshkey *key)
+{
+ struct ssh_xmss_state *state = key->xmss_state;
+
+ sshkey_xmss_free_bds(key);
+ if (state) {
+ if (state->enc_keyiv) {
+ explicit_bzero(state->enc_keyiv, state->enc_keyiv_len);
+ free(state->enc_keyiv);
+ }
+ free(state->enc_ciphername);
+ free(state);
+ }
+ key->xmss_state = NULL;
+}
+
+#define SSH_XMSS_K2_MAGIC "k=2"
+#define num_stack(x) ((x->h+1)*(x->n))
+#define num_stacklevels(x) (x->h+1)
+#define num_auth(x) ((x->h)*(x->n))
+#define num_keep(x) ((x->h >> 1)*(x->n))
+#define num_th_nodes(x) ((x->h - x->k)*(x->n))
+#define num_retain(x) (((1ULL << x->k) - x->k - 1) * (x->n))
+#define num_treehash(x) ((x->h) - (x->k))
+
+int
+sshkey_xmss_init_bds_state(struct sshkey *key)
+{
+ struct ssh_xmss_state *state = key->xmss_state;
+ u_int32_t i;
+
+ state->stackoffset = 0;
+ if ((state->stack = calloc(num_stack(state), 1)) == NULL ||
+ (state->stacklevels = calloc(num_stacklevels(state), 1))== NULL ||
+ (state->auth = calloc(num_auth(state), 1)) == NULL ||
+ (state->keep = calloc(num_keep(state), 1)) == NULL ||
+ (state->th_nodes = calloc(num_th_nodes(state), 1)) == NULL ||
+ (state->retain = calloc(num_retain(state), 1)) == NULL ||
+ (state->treehash = calloc(num_treehash(state),
+ sizeof(treehash_inst))) == NULL) {
+ sshkey_xmss_free_bds(key);
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ for (i = 0; i < state->h - state->k; i++)
+ state->treehash[i].node = &state->th_nodes[state->n*i];
+ xmss_set_bds_state(&state->bds, state->stack, state->stackoffset,
+ state->stacklevels, state->auth, state->keep, state->treehash,
+ state->retain, 0);
+ return 0;
+}
+
+void
+sshkey_xmss_free_bds(struct sshkey *key)
+{
+ struct ssh_xmss_state *state = key->xmss_state;
+
+ if (state == NULL)
+ return;
+ free(state->stack);
+ free(state->stacklevels);
+ free(state->auth);
+ free(state->keep);
+ free(state->th_nodes);
+ free(state->retain);
+ free(state->treehash);
+ state->stack = NULL;
+ state->stacklevels = NULL;
+ state->auth = NULL;
+ state->keep = NULL;
+ state->th_nodes = NULL;
+ state->retain = NULL;
+ state->treehash = NULL;
+}
+
+void *
+sshkey_xmss_params(const struct sshkey *key)
+{
+ struct ssh_xmss_state *state = key->xmss_state;
+
+ if (state == NULL)
+ return NULL;
+ return &state->params;
+}
+
+void *
+sshkey_xmss_bds_state(const struct sshkey *key)
+{
+ struct ssh_xmss_state *state = key->xmss_state;
+
+ if (state == NULL)
+ return NULL;
+ return &state->bds;
+}
+
+int
+sshkey_xmss_siglen(const struct sshkey *key, size_t *lenp)
+{
+ struct ssh_xmss_state *state = key->xmss_state;
+
+ if (lenp == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (state == NULL)
+ return SSH_ERR_INVALID_FORMAT;
+ *lenp = 4 + state->n +
+ state->params.wots_par.keysize +
+ state->h * state->n;
+ return 0;
+}
+
+size_t
+sshkey_xmss_pklen(const struct sshkey *key)
+{
+ struct ssh_xmss_state *state = key->xmss_state;
+
+ if (state == NULL)
+ return 0;
+ return state->n * 2;
+}
+
+size_t
+sshkey_xmss_sklen(const struct sshkey *key)
+{
+ struct ssh_xmss_state *state = key->xmss_state;
+
+ if (state == NULL)
+ return 0;
+ return state->n * 4 + 4;
+}
+
+int
+sshkey_xmss_init_enc_key(struct sshkey *k, const char *ciphername)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ const struct sshcipher *cipher;
+ size_t keylen = 0, ivlen = 0;
+
+ if (state == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((cipher = cipher_by_name(ciphername)) == NULL)
+ return SSH_ERR_INTERNAL_ERROR;
+ if ((state->enc_ciphername = strdup(ciphername)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ keylen = cipher_keylen(cipher);
+ ivlen = cipher_ivlen(cipher);
+ state->enc_keyiv_len = keylen + ivlen;
+ if ((state->enc_keyiv = calloc(state->enc_keyiv_len, 1)) == NULL) {
+ free(state->enc_ciphername);
+ state->enc_ciphername = NULL;
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ arc4random_buf(state->enc_keyiv, state->enc_keyiv_len);
+ return 0;
+}
+
+int
+sshkey_xmss_serialize_enc_key(const struct sshkey *k, struct sshbuf *b)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ int r;
+
+ if (state == NULL || state->enc_keyiv == NULL ||
+ state->enc_ciphername == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((r = sshbuf_put_cstring(b, state->enc_ciphername)) != 0 ||
+ (r = sshbuf_put_string(b, state->enc_keyiv,
+ state->enc_keyiv_len)) != 0)
+ return r;
+ return 0;
+}
+
+int
+sshkey_xmss_deserialize_enc_key(struct sshkey *k, struct sshbuf *b)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ size_t len;
+ int r;
+
+ if (state == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((r = sshbuf_get_cstring(b, &state->enc_ciphername, NULL)) != 0 ||
+ (r = sshbuf_get_string(b, &state->enc_keyiv, &len)) != 0)
+ return r;
+ state->enc_keyiv_len = len;
+ return 0;
+}
+
+int
+sshkey_xmss_serialize_pk_info(const struct sshkey *k, struct sshbuf *b,
+ enum sshkey_serialize_rep opts)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ u_char have_info = 1;
+ u_int32_t idx;
+ int r;
+
+ if (state == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (opts != SSHKEY_SERIALIZE_INFO)
+ return 0;
+ idx = k->xmss_sk ? PEEK_U32(k->xmss_sk) : state->idx;
+ if ((r = sshbuf_put_u8(b, have_info)) != 0 ||
+ (r = sshbuf_put_u32(b, idx)) != 0 ||
+ (r = sshbuf_put_u32(b, state->maxidx)) != 0)
+ return r;
+ return 0;
+}
+
+int
+sshkey_xmss_deserialize_pk_info(struct sshkey *k, struct sshbuf *b)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ u_char have_info;
+ int r;
+
+ if (state == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ /* optional */
+ if (sshbuf_len(b) == 0)
+ return 0;
+ if ((r = sshbuf_get_u8(b, &have_info)) != 0)
+ return r;
+ if (have_info != 1)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((r = sshbuf_get_u32(b, &state->idx)) != 0 ||
+ (r = sshbuf_get_u32(b, &state->maxidx)) != 0)
+ return r;
+ return 0;
+}
+
+int
+sshkey_xmss_generate_private_key(struct sshkey *k, u_int bits)
+{
+ int r;
+ const char *name;
+
+ if (bits == 10) {
+ name = XMSS_SHA2_256_W16_H10_NAME;
+ } else if (bits == 16) {
+ name = XMSS_SHA2_256_W16_H16_NAME;
+ } else if (bits == 20) {
+ name = XMSS_SHA2_256_W16_H20_NAME;
+ } else {
+ name = XMSS_DEFAULT_NAME;
+ }
+ if ((r = sshkey_xmss_init(k, name)) != 0 ||
+ (r = sshkey_xmss_init_bds_state(k)) != 0 ||
+ (r = sshkey_xmss_init_enc_key(k, XMSS_CIPHERNAME)) != 0)
+ return r;
+ if ((k->xmss_pk = malloc(sshkey_xmss_pklen(k))) == NULL ||
+ (k->xmss_sk = malloc(sshkey_xmss_sklen(k))) == NULL) {
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ xmss_keypair(k->xmss_pk, k->xmss_sk, sshkey_xmss_bds_state(k),
+ sshkey_xmss_params(k));
+ return 0;
+}
+
+int
+sshkey_xmss_get_state_from_file(struct sshkey *k, const char *filename,
+ int *have_file, sshkey_printfn *pr)
+{
+ struct sshbuf *b = NULL, *enc = NULL;
+ int ret = SSH_ERR_SYSTEM_ERROR, r, fd = -1;
+ u_int32_t len;
+ unsigned char buf[4], *data = NULL;
+
+ *have_file = 0;
+ if ((fd = open(filename, O_RDONLY)) >= 0) {
+ *have_file = 1;
+ if (atomicio(read, fd, buf, sizeof(buf)) != sizeof(buf)) {
+ PRINT("%s: corrupt state file: %s", __func__, filename);
+ goto done;
+ }
+ len = PEEK_U32(buf);
+ if ((data = calloc(len, 1)) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto done;
+ }
+ if (atomicio(read, fd, data, len) != len) {
+ PRINT("%s: cannot read blob: %s", __func__, filename);
+ goto done;
+ }
+ if ((enc = sshbuf_from(data, len)) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto done;
+ }
+ sshkey_xmss_free_bds(k);
+ if ((r = sshkey_xmss_decrypt_state(k, enc, &b)) != 0) {
+ ret = r;
+ goto done;
+ }
+ if ((r = sshkey_xmss_deserialize_state(k, b)) != 0) {
+ ret = r;
+ goto done;
+ }
+ ret = 0;
+ }
+done:
+ if (fd != -1)
+ close(fd);
+ free(data);
+ sshbuf_free(enc);
+ sshbuf_free(b);
+ return ret;
+}
+
+int
+sshkey_xmss_get_state(const struct sshkey *k, sshkey_printfn *pr)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ u_int32_t idx = 0;
+ char *filename = NULL;
+ char *statefile = NULL, *ostatefile = NULL, *lockfile = NULL;
+ int lockfd = -1, have_state = 0, have_ostate, tries = 0;
+ int ret = SSH_ERR_INVALID_ARGUMENT, r;
+
+ if (state == NULL)
+ goto done;
+ /*
+ * If maxidx is set, then we are allowed a limited number
+ * of signatures, but don't need to access the disk.
+ * Otherwise we need to deal with the on-disk state.
+ */
+ if (state->maxidx) {
+ /* xmss_sk always contains the current state */
+ idx = PEEK_U32(k->xmss_sk);
+ if (idx < state->maxidx) {
+ state->allow_update = 1;
+ return 0;
+ }
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+ if ((filename = k->xmss_filename) == NULL)
+ goto done;
+ if (asprintf(&lockfile, "%s.lock", filename) == -1 ||
+ asprintf(&statefile, "%s.state", filename) == -1 ||
+ asprintf(&ostatefile, "%s.ostate", filename) == -1) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto done;
+ }
+ if ((lockfd = open(lockfile, O_CREAT|O_RDONLY, 0600)) == -1) {
+ ret = SSH_ERR_SYSTEM_ERROR;
+ PRINT("%s: cannot open/create: %s", __func__, 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);
+ goto done;
+ }
+ if (++tries > 10) {
+ ret = SSH_ERR_SYSTEM_ERROR;
+ PRINT("%s: giving up on: %s", __func__, 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) {
+ if ((r = sshkey_xmss_get_state_from_file((struct sshkey *)k,
+ ostatefile, &have_ostate, pr)) == 0) {
+ state->allow_update = 1;
+ r = sshkey_xmss_forward_state(k, 1);
+ state->idx = PEEK_U32(k->xmss_sk);
+ state->allow_update = 0;
+ }
+ }
+ if (!have_state && !have_ostate) {
+ /* check that bds state is initialized */
+ if (state->bds.auth == NULL)
+ goto done;
+ PRINT("%s: start from scratch idx 0: %u", __func__, state->idx);
+ } else if (r != 0) {
+ ret = r;
+ goto done;
+ }
+ if (state->idx + 1 < state->idx) {
+ PRINT("%s: state wrap: %u", __func__, state->idx);
+ goto done;
+ }
+ state->have_state = have_state;
+ state->lockfd = lockfd;
+ state->allow_update = 1;
+ lockfd = -1;
+ ret = 0;
+done:
+ if (lockfd != -1)
+ close(lockfd);
+ free(lockfile);
+ free(statefile);
+ free(ostatefile);
+ return ret;
+}
+
+int
+sshkey_xmss_forward_state(const struct sshkey *k, u_int32_t reserve)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ u_char *sig = NULL;
+ size_t required_siglen;
+ unsigned long long smlen;
+ u_char data;
+ int ret, r;
+
+ if (state == NULL || !state->allow_update)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (reserve == 0)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (state->idx + reserve <= state->idx)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((r = sshkey_xmss_siglen(k, &required_siglen)) != 0)
+ return r;
+ if ((sig = malloc(required_siglen)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ while (reserve-- > 0) {
+ state->idx = PEEK_U32(k->xmss_sk);
+ smlen = required_siglen;
+ if ((ret = xmss_sign(k->xmss_sk, sshkey_xmss_bds_state(k),
+ sig, &smlen, &data, 0, sshkey_xmss_params(k))) != 0) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ break;
+ }
+ }
+ free(sig);
+ return r;
+}
+
+int
+sshkey_xmss_update_state(const struct sshkey *k, sshkey_printfn *pr)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ struct sshbuf *b = NULL, *enc = NULL;
+ u_int32_t idx = 0;
+ unsigned char buf[4];
+ char *filename = NULL;
+ char *statefile = NULL, *ostatefile = NULL, *nstatefile = NULL;
+ int fd = -1;
+ int ret = SSH_ERR_INVALID_ARGUMENT;
+
+ if (state == NULL || !state->allow_update)
+ return ret;
+ if (state->maxidx) {
+ /* no update since the number of signatures is limited */
+ ret = 0;
+ goto done;
+ }
+ idx = PEEK_U32(k->xmss_sk);
+ if (idx == state->idx) {
+ /* no signature happened, no need to update */
+ ret = 0;
+ goto done;
+ } else if (idx != state->idx + 1) {
+ PRINT("%s: more than one signature happened: idx %u state %u",
+ __func__, idx, state->idx);
+ goto done;
+ }
+ state->idx = idx;
+ if ((filename = k->xmss_filename) == NULL)
+ goto done;
+ if (asprintf(&statefile, "%s.state", filename) == -1 ||
+ asprintf(&ostatefile, "%s.ostate", filename) == -1 ||
+ asprintf(&nstatefile, "%s.nstate", filename) == -1) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto done;
+ }
+ unlink(nstatefile);
+ if ((b = sshbuf_new()) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto done;
+ }
+ if ((ret = sshkey_xmss_serialize_state(k, b)) != 0) {
+ PRINT("%s: SERLIALIZE FAILED: %d", __func__, ret);
+ goto done;
+ }
+ if ((ret = sshkey_xmss_encrypt_state(k, b, &enc)) != 0) {
+ PRINT("%s: ENCRYPT FAILED: %d", __func__, 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);
+ 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);
+ 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);
+ close(fd);
+ goto done;
+ }
+ if (fsync(fd) == -1) {
+ ret = SSH_ERR_SYSTEM_ERROR;
+ PRINT("%s: sync new state file: %s", __func__, nstatefile);
+ close(fd);
+ goto done;
+ }
+ if (close(fd) == -1) {
+ ret = SSH_ERR_SYSTEM_ERROR;
+ PRINT("%s: close new state file: %s", __func__, 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);
+ goto done;
+ }
+ }
+ if (rename(nstatefile, statefile) == -1) {
+ ret = SSH_ERR_SYSTEM_ERROR;
+ PRINT("%s: rename %s to %s", __func__, nstatefile, statefile);
+ goto done;
+ }
+ ret = 0;
+done:
+ if (state->lockfd != -1) {
+ close(state->lockfd);
+ state->lockfd = -1;
+ }
+ if (nstatefile)
+ unlink(nstatefile);
+ free(statefile);
+ free(ostatefile);
+ free(nstatefile);
+ sshbuf_free(b);
+ sshbuf_free(enc);
+ return ret;
+}
+
+int
+sshkey_xmss_serialize_state(const struct sshkey *k, struct sshbuf *b)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ treehash_inst *th;
+ u_int32_t i, node;
+ int r;
+
+ if (state == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (state->stack == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ state->stackoffset = state->bds.stackoffset; /* copy back */
+ if ((r = sshbuf_put_cstring(b, SSH_XMSS_K2_MAGIC)) != 0 ||
+ (r = sshbuf_put_u32(b, state->idx)) != 0 ||
+ (r = sshbuf_put_string(b, state->stack, num_stack(state))) != 0 ||
+ (r = sshbuf_put_u32(b, state->stackoffset)) != 0 ||
+ (r = sshbuf_put_string(b, state->stacklevels, num_stacklevels(state))) != 0 ||
+ (r = sshbuf_put_string(b, state->auth, num_auth(state))) != 0 ||
+ (r = sshbuf_put_string(b, state->keep, num_keep(state))) != 0 ||
+ (r = sshbuf_put_string(b, state->th_nodes, num_th_nodes(state))) != 0 ||
+ (r = sshbuf_put_string(b, state->retain, num_retain(state))) != 0 ||
+ (r = sshbuf_put_u32(b, num_treehash(state))) != 0)
+ return r;
+ for (i = 0; i < num_treehash(state); i++) {
+ th = &state->treehash[i];
+ node = th->node - state->th_nodes;
+ if ((r = sshbuf_put_u32(b, th->h)) != 0 ||
+ (r = sshbuf_put_u32(b, th->next_idx)) != 0 ||
+ (r = sshbuf_put_u32(b, th->stackusage)) != 0 ||
+ (r = sshbuf_put_u8(b, th->completed)) != 0 ||
+ (r = sshbuf_put_u32(b, node)) != 0)
+ return r;
+ }
+ return 0;
+}
+
+int
+sshkey_xmss_serialize_state_opt(const struct sshkey *k, struct sshbuf *b,
+ enum sshkey_serialize_rep opts)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ int r = SSH_ERR_INVALID_ARGUMENT;
+ u_char have_stack, have_filename, have_enc;
+
+ if (state == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((r = sshbuf_put_u8(b, opts)) != 0)
+ return r;
+ switch (opts) {
+ case SSHKEY_SERIALIZE_STATE:
+ r = sshkey_xmss_serialize_state(k, b);
+ break;
+ case SSHKEY_SERIALIZE_FULL:
+ if ((r = sshkey_xmss_serialize_enc_key(k, b)) != 0)
+ return r;
+ r = sshkey_xmss_serialize_state(k, b);
+ break;
+ case SSHKEY_SERIALIZE_SHIELD:
+ /* all of stack/filename/enc are optional */
+ have_stack = state->stack != NULL;
+ if ((r = sshbuf_put_u8(b, have_stack)) != 0)
+ return r;
+ if (have_stack) {
+ state->idx = PEEK_U32(k->xmss_sk); /* update */
+ if ((r = sshkey_xmss_serialize_state(k, b)) != 0)
+ return r;
+ }
+ have_filename = k->xmss_filename != NULL;
+ if ((r = sshbuf_put_u8(b, have_filename)) != 0)
+ return r;
+ if (have_filename &&
+ (r = sshbuf_put_cstring(b, k->xmss_filename)) != 0)
+ return r;
+ have_enc = state->enc_keyiv != NULL;
+ if ((r = sshbuf_put_u8(b, have_enc)) != 0)
+ return r;
+ if (have_enc &&
+ (r = sshkey_xmss_serialize_enc_key(k, b)) != 0)
+ return r;
+ if ((r = sshbuf_put_u32(b, state->maxidx)) != 0 ||
+ (r = sshbuf_put_u8(b, state->allow_update)) != 0)
+ return r;
+ break;
+ case SSHKEY_SERIALIZE_DEFAULT:
+ r = 0;
+ break;
+ default:
+ r = SSH_ERR_INVALID_ARGUMENT;
+ break;
+ }
+ return r;
+}
+
+int
+sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ treehash_inst *th;
+ u_int32_t i, lh, node;
+ size_t ls, lsl, la, lk, ln, lr;
+ char *magic;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if (state == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (k->xmss_sk == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((state->treehash = calloc(num_treehash(state),
+ sizeof(treehash_inst))) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((r = sshbuf_get_cstring(b, &magic, NULL)) != 0 ||
+ (r = sshbuf_get_u32(b, &state->idx)) != 0 ||
+ (r = sshbuf_get_string(b, &state->stack, &ls)) != 0 ||
+ (r = sshbuf_get_u32(b, &state->stackoffset)) != 0 ||
+ (r = sshbuf_get_string(b, &state->stacklevels, &lsl)) != 0 ||
+ (r = sshbuf_get_string(b, &state->auth, &la)) != 0 ||
+ (r = sshbuf_get_string(b, &state->keep, &lk)) != 0 ||
+ (r = sshbuf_get_string(b, &state->th_nodes, &ln)) != 0 ||
+ (r = sshbuf_get_string(b, &state->retain, &lr)) != 0 ||
+ (r = sshbuf_get_u32(b, &lh)) != 0)
+ goto out;
+ if (strcmp(magic, SSH_XMSS_K2_MAGIC) != 0) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ /* XXX check stackoffset */
+ if (ls != num_stack(state) ||
+ lsl != num_stacklevels(state) ||
+ la != num_auth(state) ||
+ lk != num_keep(state) ||
+ ln != num_th_nodes(state) ||
+ lr != num_retain(state) ||
+ lh != num_treehash(state)) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ for (i = 0; i < num_treehash(state); i++) {
+ th = &state->treehash[i];
+ if ((r = sshbuf_get_u32(b, &th->h)) != 0 ||
+ (r = sshbuf_get_u32(b, &th->next_idx)) != 0 ||
+ (r = sshbuf_get_u32(b, &th->stackusage)) != 0 ||
+ (r = sshbuf_get_u8(b, &th->completed)) != 0 ||
+ (r = sshbuf_get_u32(b, &node)) != 0)
+ goto out;
+ if (node < num_th_nodes(state))
+ th->node = &state->th_nodes[node];
+ }
+ POKE_U32(k->xmss_sk, state->idx);
+ xmss_set_bds_state(&state->bds, state->stack, state->stackoffset,
+ state->stacklevels, state->auth, state->keep, state->treehash,
+ state->retain, 0);
+ /* success */
+ r = 0;
+ out:
+ free(magic);
+ return r;
+}
+
+int
+sshkey_xmss_deserialize_state_opt(struct sshkey *k, struct sshbuf *b)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ enum sshkey_serialize_rep opts;
+ u_char have_state, have_stack, have_filename, have_enc;
+ int r;
+
+ if ((r = sshbuf_get_u8(b, &have_state)) != 0)
+ return r;
+
+ opts = have_state;
+ switch (opts) {
+ case SSHKEY_SERIALIZE_DEFAULT:
+ r = 0;
+ break;
+ case SSHKEY_SERIALIZE_SHIELD:
+ if ((r = sshbuf_get_u8(b, &have_stack)) != 0)
+ return r;
+ if (have_stack &&
+ (r = sshkey_xmss_deserialize_state(k, b)) != 0)
+ return r;
+ if ((r = sshbuf_get_u8(b, &have_filename)) != 0)
+ return r;
+ if (have_filename &&
+ (r = sshbuf_get_cstring(b, &k->xmss_filename, NULL)) != 0)
+ return r;
+ if ((r = sshbuf_get_u8(b, &have_enc)) != 0)
+ return r;
+ if (have_enc &&
+ (r = sshkey_xmss_deserialize_enc_key(k, b)) != 0)
+ return r;
+ if ((r = sshbuf_get_u32(b, &state->maxidx)) != 0 ||
+ (r = sshbuf_get_u8(b, &state->allow_update)) != 0)
+ return r;
+ break;
+ case SSHKEY_SERIALIZE_STATE:
+ if ((r = sshkey_xmss_deserialize_state(k, b)) != 0)
+ return r;
+ break;
+ case SSHKEY_SERIALIZE_FULL:
+ if ((r = sshkey_xmss_deserialize_enc_key(k, b)) != 0 ||
+ (r = sshkey_xmss_deserialize_state(k, b)) != 0)
+ return r;
+ break;
+ default:
+ r = SSH_ERR_INVALID_FORMAT;
+ break;
+ }
+ return r;
+}
+
+int
+sshkey_xmss_encrypt_state(const struct sshkey *k, struct sshbuf *b,
+ struct sshbuf **retp)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ struct sshbuf *encrypted = NULL, *encoded = NULL, *padded = NULL;
+ struct sshcipher_ctx *ciphercontext = NULL;
+ const struct sshcipher *cipher;
+ u_char *cp, *key, *iv = NULL;
+ size_t i, keylen, ivlen, blocksize, authlen, encrypted_len, aadlen;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if (retp != NULL)
+ *retp = NULL;
+ if (state == NULL ||
+ state->enc_keyiv == NULL ||
+ state->enc_ciphername == NULL)
+ return SSH_ERR_INTERNAL_ERROR;
+ if ((cipher = cipher_by_name(state->enc_ciphername)) == NULL) {
+ r = SSH_ERR_INTERNAL_ERROR;
+ goto out;
+ }
+ blocksize = cipher_blocksize(cipher);
+ keylen = cipher_keylen(cipher);
+ ivlen = cipher_ivlen(cipher);
+ authlen = cipher_authlen(cipher);
+ if (state->enc_keyiv_len != keylen + ivlen) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ key = state->enc_keyiv;
+ if ((encrypted = sshbuf_new()) == NULL ||
+ (encoded = sshbuf_new()) == NULL ||
+ (padded = sshbuf_new()) == NULL ||
+ (iv = malloc(ivlen)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ /* replace first 4 bytes of IV with index to ensure uniqueness */
+ memcpy(iv, key + keylen, ivlen);
+ POKE_U32(iv, state->idx);
+
+ if ((r = sshbuf_put(encoded, XMSS_MAGIC, sizeof(XMSS_MAGIC))) != 0 ||
+ (r = sshbuf_put_u32(encoded, state->idx)) != 0)
+ goto out;
+
+ /* padded state will be encrypted */
+ if ((r = sshbuf_putb(padded, b)) != 0)
+ goto out;
+ i = 0;
+ while (sshbuf_len(padded) % blocksize) {
+ if ((r = sshbuf_put_u8(padded, ++i & 0xff)) != 0)
+ goto out;
+ }
+ encrypted_len = sshbuf_len(padded);
+
+ /* header including the length of state is used as AAD */
+ if ((r = sshbuf_put_u32(encoded, encrypted_len)) != 0)
+ goto out;
+ aadlen = sshbuf_len(encoded);
+
+ /* concat header and state */
+ if ((r = sshbuf_putb(encoded, padded)) != 0)
+ goto out;
+
+ /* reserve space for encryption of encoded data plus auth tag */
+ /* encrypt at offset addlen */
+ if ((r = sshbuf_reserve(encrypted,
+ encrypted_len + aadlen + authlen, &cp)) != 0 ||
+ (r = cipher_init(&ciphercontext, cipher, key, keylen,
+ iv, ivlen, 1)) != 0 ||
+ (r = cipher_crypt(ciphercontext, 0, cp, sshbuf_ptr(encoded),
+ encrypted_len, aadlen, authlen)) != 0)
+ goto out;
+
+ /* success */
+ r = 0;
+ out:
+ if (retp != NULL) {
+ *retp = encrypted;
+ encrypted = NULL;
+ }
+ sshbuf_free(padded);
+ sshbuf_free(encoded);
+ sshbuf_free(encrypted);
+ cipher_free(ciphercontext);
+ free(iv);
+ return r;
+}
+
+int
+sshkey_xmss_decrypt_state(const struct sshkey *k, struct sshbuf *encoded,
+ struct sshbuf **retp)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ struct sshbuf *copy = NULL, *decrypted = NULL;
+ struct sshcipher_ctx *ciphercontext = NULL;
+ const struct sshcipher *cipher = NULL;
+ u_char *key, *iv = NULL, *dp;
+ size_t keylen, ivlen, authlen, aadlen;
+ u_int blocksize, encrypted_len, index;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if (retp != NULL)
+ *retp = NULL;
+ if (state == NULL ||
+ state->enc_keyiv == NULL ||
+ state->enc_ciphername == NULL)
+ return SSH_ERR_INTERNAL_ERROR;
+ if ((cipher = cipher_by_name(state->enc_ciphername)) == NULL) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ blocksize = cipher_blocksize(cipher);
+ keylen = cipher_keylen(cipher);
+ ivlen = cipher_ivlen(cipher);
+ authlen = cipher_authlen(cipher);
+ if (state->enc_keyiv_len != keylen + ivlen) {
+ r = SSH_ERR_INTERNAL_ERROR;
+ goto out;
+ }
+ key = state->enc_keyiv;
+
+ if ((copy = sshbuf_fromb(encoded)) == NULL ||
+ (decrypted = sshbuf_new()) == NULL ||
+ (iv = malloc(ivlen)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ /* check magic */
+ if (sshbuf_len(encoded) < sizeof(XMSS_MAGIC) ||
+ memcmp(sshbuf_ptr(encoded), XMSS_MAGIC, sizeof(XMSS_MAGIC))) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ /* parse public portion */
+ if ((r = sshbuf_consume(encoded, sizeof(XMSS_MAGIC))) != 0 ||
+ (r = sshbuf_get_u32(encoded, &index)) != 0 ||
+ (r = sshbuf_get_u32(encoded, &encrypted_len)) != 0)
+ goto out;
+
+ /* check size of encrypted key blob */
+ if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ /* check that an appropriate amount of auth data is present */
+ if (sshbuf_len(encoded) < authlen ||
+ sshbuf_len(encoded) - authlen < encrypted_len) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+
+ aadlen = sshbuf_len(copy) - sshbuf_len(encoded);
+
+ /* replace first 4 bytes of IV with index to ensure uniqueness */
+ memcpy(iv, key + keylen, ivlen);
+ POKE_U32(iv, index);
+
+ /* decrypt private state of key */
+ if ((r = sshbuf_reserve(decrypted, aadlen + encrypted_len, &dp)) != 0 ||
+ (r = cipher_init(&ciphercontext, cipher, key, keylen,
+ iv, ivlen, 0)) != 0 ||
+ (r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(copy),
+ encrypted_len, aadlen, authlen)) != 0)
+ goto out;
+
+ /* there should be no trailing data */
+ if ((r = sshbuf_consume(encoded, encrypted_len + authlen)) != 0)
+ goto out;
+ if (sshbuf_len(encoded) != 0) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+
+ /* remove AAD */
+ if ((r = sshbuf_consume(decrypted, aadlen)) != 0)
+ goto out;
+ /* XXX encrypted includes unchecked padding */
+
+ /* success */
+ r = 0;
+ if (retp != NULL) {
+ *retp = decrypted;
+ decrypted = NULL;
+ }
+ out:
+ cipher_free(ciphercontext);
+ sshbuf_free(copy);
+ sshbuf_free(decrypted);
+ free(iv);
+ return r;
+}
+
+u_int32_t
+sshkey_xmss_signatures_left(const struct sshkey *k)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+ u_int32_t idx;
+
+ if (sshkey_type_plain(k->type) == KEY_XMSS && state &&
+ state->maxidx) {
+ idx = k->xmss_sk ? PEEK_U32(k->xmss_sk) : state->idx;
+ if (idx < state->maxidx)
+ return state->maxidx - idx;
+ }
+ return 0;
+}
+
+int
+sshkey_xmss_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
+{
+ struct ssh_xmss_state *state = k->xmss_state;
+
+ if (sshkey_type_plain(k->type) != KEY_XMSS)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (maxsign == 0)
+ return 0;
+ if (state->idx + maxsign < state->idx)
+ return SSH_ERR_INVALID_ARGUMENT;
+ state->maxidx = state->idx + maxsign;
+ return 0;
+}
+#endif /* WITH_XMSS */
diff --git a/sshkey-xmss.h b/sshkey-xmss.h
new file mode 100644
index 00000000..b9f8ead1
--- /dev/null
+++ b/sshkey-xmss.h
@@ -0,0 +1,56 @@
+/* $OpenBSD: sshkey-xmss.h,v 1.1 2018/02/23 15:58:38 markus Exp $ */
+/*
+ * Copyright (c) 2017 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef SSHKEY_XMSS_H
+#define SSHKEY_XMSS_H
+
+#define XMSS_SHA2_256_W16_H10_NAME "XMSS_SHA2-256_W16_H10"
+#define XMSS_SHA2_256_W16_H16_NAME "XMSS_SHA2-256_W16_H16"
+#define XMSS_SHA2_256_W16_H20_NAME "XMSS_SHA2-256_W16_H20"
+#define XMSS_DEFAULT_NAME XMSS_SHA2_256_W16_H10_NAME
+
+size_t sshkey_xmss_pklen(const struct sshkey *);
+size_t sshkey_xmss_sklen(const struct sshkey *);
+int sshkey_xmss_init(struct sshkey *, const char *);
+void sshkey_xmss_free_state(struct sshkey *);
+int sshkey_xmss_generate_private_key(struct sshkey *, 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);
+int sshkey_xmss_serialize_pk_info(const struct sshkey *, struct sshbuf *,
+ enum sshkey_serialize_rep);
+int sshkey_xmss_deserialize_state(struct sshkey *, struct sshbuf *);
+int sshkey_xmss_deserialize_state_opt(struct sshkey *, struct sshbuf *);
+int sshkey_xmss_deserialize_pk_info(struct sshkey *, struct sshbuf *);
+
+int sshkey_xmss_siglen(const struct sshkey *, size_t *);
+void *sshkey_xmss_params(const struct sshkey *);
+void *sshkey_xmss_bds_state(const struct sshkey *);
+int sshkey_xmss_get_state(const struct sshkey *, sshkey_printfn *);
+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 *);
+u_int32_t sshkey_xmss_signatures_left(const struct sshkey *);
+
+#endif /* SSHKEY_XMSS_H */
diff --git a/sshkey.c b/sshkey.c
index 47687903..e7b464dc 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.15 2015/03/06 01:40:56 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.108 2020/04/11 10:16:11 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -27,7 +27,6 @@
#include "includes.h"
-#include <sys/param.h> /* MIN MAX */
#include <sys/types.h>
#include <netinet/in.h>
@@ -44,6 +43,7 @@
#include <stdio.h>
#include <string.h>
#include <resolv.h>
+#include <time.h>
#ifdef HAVE_UTIL_H
#include <util.h>
#endif /* HAVE_UTIL_H */
@@ -52,12 +52,19 @@
#include "ssherr.h"
#include "misc.h"
#include "sshbuf.h"
-#include "rsa.h"
#include "cipher.h"
#include "digest.h"
#define SSHKEY_INTERNAL
#include "sshkey.h"
#include "match.h"
+#include "ssh-sk.h"
+
+#ifdef WITH_XMSS
+#include "sshkey-xmss.h"
+#include "xmss_fast.h"
+#endif
+
+#include "openbsd-compat/openssl-compat.h"
/* openssh private key file format */
#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
@@ -67,12 +74,22 @@
#define KDFNAME "bcrypt"
#define AUTH_MAGIC "openssh-key-v1"
#define SALT_LEN 16
-#define DEFAULT_CIPHERNAME "aes256-cbc"
+#define DEFAULT_CIPHERNAME "aes256-ctr"
#define DEFAULT_ROUNDS 16
/* Version identification string for SSH v1 identity files. */
#define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
+/*
+ * Constants relating to "shielding" support; protection of keys expected
+ * to remain in memory for long durations
+ */
+#define SSHKEY_SHIELD_PREKEY_LEN (16 * 1024)
+#define SSHKEY_SHIELD_CIPHER "aes256-ctr" /* XXX want AES-EME* */
+#define SSHKEY_SHIELD_PREKEY_HASH SSH_DIGEST_SHA512
+
+int sshkey_private_serialize_opt(struct sshkey *key,
+ struct sshbuf *buf, enum sshkey_serialize_rep);
static int sshkey_from_blob_internal(struct sshbuf *buf,
struct sshkey **keyp, int allow_cert);
@@ -80,43 +97,64 @@ static int sshkey_from_blob_internal(struct sshbuf *buf,
struct keytype {
const char *name;
const char *shortname;
+ const char *sigalg;
int type;
int nid;
int cert;
+ int sigonly;
};
static const struct keytype keytypes[] = {
- { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 },
- { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
- KEY_ED25519_CERT, 0, 1 },
+ { "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 },
+ { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL,
+ KEY_ED25519_CERT, 0, 1, 0 },
+ { "sk-ssh-ed25519@openssh.com", "ED25519-SK", NULL,
+ KEY_ED25519_SK, 0, 0, 0 },
+ { "sk-ssh-ed25519-cert-v01@openssh.com", "ED25519-SK-CERT", NULL,
+ KEY_ED25519_SK_CERT, 0, 1, 0 },
+#ifdef WITH_XMSS
+ { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 },
+ { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL,
+ KEY_XMSS_CERT, 0, 1, 0 },
+#endif /* WITH_XMSS */
#ifdef WITH_OPENSSL
- { NULL, "RSA1", KEY_RSA1, 0, 0 },
- { "ssh-rsa", "RSA", KEY_RSA, 0, 0 },
- { "ssh-dss", "DSA", KEY_DSA, 0, 0 },
+ { "ssh-rsa", "RSA", NULL, KEY_RSA, 0, 0, 0 },
+ { "rsa-sha2-256", "RSA", NULL, KEY_RSA, 0, 0, 1 },
+ { "rsa-sha2-512", "RSA", NULL, KEY_RSA, 0, 0, 1 },
+ { "ssh-dss", "DSA", NULL, KEY_DSA, 0, 0, 0 },
# ifdef OPENSSL_HAS_ECC
- { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 },
- { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 },
+ { "ecdsa-sha2-nistp256", "ECDSA", NULL,
+ KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
+ { "ecdsa-sha2-nistp384", "ECDSA", NULL,
+ KEY_ECDSA, NID_secp384r1, 0, 0 },
# ifdef OPENSSL_HAS_NISTP521
- { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 },
+ { "ecdsa-sha2-nistp521", "ECDSA", NULL,
+ KEY_ECDSA, NID_secp521r1, 0, 0 },
# endif /* OPENSSL_HAS_NISTP521 */
+ { "sk-ecdsa-sha2-nistp256@openssh.com", "ECDSA-SK", NULL,
+ KEY_ECDSA_SK, NID_X9_62_prime256v1, 0, 0 },
# endif /* OPENSSL_HAS_ECC */
- { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 },
- { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 },
+ { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
+ KEY_RSA_CERT, 0, 1, 0 },
+ { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
+ "rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
+ { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
+ "rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
+ { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
+ KEY_DSA_CERT, 0, 1, 0 },
# ifdef OPENSSL_HAS_ECC
- { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",
- KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 },
- { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
- KEY_ECDSA_CERT, NID_secp384r1, 1 },
+ { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", NULL,
+ KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
+ { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", NULL,
+ KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
# ifdef OPENSSL_HAS_NISTP521
- { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
- KEY_ECDSA_CERT, NID_secp521r1, 1 },
+ { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL,
+ KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
# endif /* OPENSSL_HAS_NISTP521 */
+ { "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-SK-CERT", NULL,
+ KEY_ECDSA_SK_CERT, NID_X9_62_prime256v1, 1, 0 },
# endif /* OPENSSL_HAS_ECC */
- { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00",
- KEY_RSA_CERT_V00, 0, 1 },
- { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00",
- KEY_DSA_CERT_V00, 0, 1 },
#endif /* WITH_OPENSSL */
- { NULL, NULL, -1, -1, 0 }
+ { NULL, NULL, NULL, -1, -1, 0, 0 }
};
const char *
@@ -182,13 +220,26 @@ sshkey_type_from_name(const char *name)
return KEY_UNSPEC;
}
+static int
+key_type_is_ecdsa_variant(int type)
+{
+ switch (type) {
+ case KEY_ECDSA:
+ case KEY_ECDSA_CERT:
+ case KEY_ECDSA_SK:
+ case KEY_ECDSA_SK_CERT:
+ return 1;
+ }
+ return 0;
+}
+
int
sshkey_ecdsa_nid_from_name(const char *name)
{
const struct keytype *kt;
for (kt = keytypes; kt->type != -1; kt++) {
- if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
+ if (!key_type_is_ecdsa_variant(kt->type))
continue;
if (kt->name != NULL && strcmp(name, kt->name) == 0)
return kt->nid;
@@ -197,7 +248,7 @@ sshkey_ecdsa_nid_from_name(const char *name)
}
char *
-key_alg_list(int certs_only, int plain_only)
+sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep)
{
char *tmp, *ret = NULL;
size_t nlen, rlen = 0;
@@ -206,10 +257,12 @@ key_alg_list(int certs_only, int plain_only)
for (kt = keytypes; kt->type != -1; kt++) {
if (kt->name == NULL)
continue;
+ if (!include_sigonly && kt->sigonly)
+ continue;
if ((certs_only && !kt->cert) || (plain_only && kt->cert))
continue;
if (ret != NULL)
- ret[rlen++] = '\n';
+ ret[rlen++] = sep;
nlen = strlen(kt->name);
if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
free(ret);
@@ -236,10 +289,6 @@ sshkey_names_valid2(const char *names, int allow_wildcard)
for ((p = strsep(&cp, ",")); p && *p != '\0';
(p = strsep(&cp, ","))) {
type = sshkey_type_from_name(p);
- if (type == KEY_RSA1) {
- free(s);
- return 0;
- }
if (type == KEY_UNSPEC) {
if (allow_wildcard) {
/*
@@ -248,10 +297,8 @@ sshkey_names_valid2(const char *names, int allow_wildcard)
* the component is accepted.
*/
for (kt = keytypes; kt->type != -1; kt++) {
- if (kt->type == KEY_RSA1)
- continue;
if (match_pattern_list(kt->name,
- p, strlen(p), 0) != 0)
+ p, 0) != 0)
break;
}
if (kt->type != -1)
@@ -268,40 +315,41 @@ sshkey_names_valid2(const char *names, int allow_wildcard)
u_int
sshkey_size(const struct sshkey *k)
{
+#ifdef WITH_OPENSSL
+ const BIGNUM *rsa_n, *dsa_p;
+#endif /* WITH_OPENSSL */
+
switch (k->type) {
#ifdef WITH_OPENSSL
- case KEY_RSA1:
case KEY_RSA:
- case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
- return BN_num_bits(k->rsa->n);
+ if (k->rsa == NULL)
+ return 0;
+ RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
+ return BN_num_bits(rsa_n);
case KEY_DSA:
- case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
- return BN_num_bits(k->dsa->p);
+ if (k->dsa == NULL)
+ return 0;
+ DSA_get0_pqg(k->dsa, &dsa_p, NULL, NULL);
+ return BN_num_bits(dsa_p);
case KEY_ECDSA:
case KEY_ECDSA_CERT:
+ case KEY_ECDSA_SK:
+ case KEY_ECDSA_SK_CERT:
return sshkey_curve_nid_to_bits(k->ecdsa_nid);
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
+ case KEY_ED25519_SK:
+ case KEY_ED25519_SK_CERT:
+ case KEY_XMSS:
+ case KEY_XMSS_CERT:
return 256; /* XXX */
}
return 0;
}
-int
-sshkey_cert_is_legacy(const struct sshkey *k)
-{
- switch (k->type) {
- case KEY_DSA_CERT_V00:
- case KEY_RSA_CERT_V00:
- return 1;
- default:
- return 0;
- }
-}
-
static int
sshkey_type_is_valid_ca(int type)
{
@@ -309,7 +357,10 @@ sshkey_type_is_valid_ca(int type)
case KEY_RSA:
case KEY_DSA:
case KEY_ECDSA:
+ case KEY_ECDSA_SK:
case KEY_ED25519:
+ case KEY_ED25519_SK:
+ case KEY_XMSS:
return 1;
default:
return 0;
@@ -324,21 +375,39 @@ sshkey_is_cert(const struct sshkey *k)
return sshkey_type_is_cert(k->type);
}
+int
+sshkey_is_sk(const struct sshkey *k)
+{
+ if (k == NULL)
+ return 0;
+ switch (sshkey_type_plain(k->type)) {
+ case KEY_ECDSA_SK:
+ case KEY_ED25519_SK:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
/* Return the cert-less equivalent to a certified key type */
int
sshkey_type_plain(int type)
{
switch (type) {
- case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
return KEY_RSA;
- case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
return KEY_DSA;
case KEY_ECDSA_CERT:
return KEY_ECDSA;
+ case KEY_ECDSA_SK_CERT:
+ return KEY_ECDSA_SK;
case KEY_ED25519_CERT:
return KEY_ED25519;
+ case KEY_ED25519_SK_CERT:
+ return KEY_ED25519_SK;
+ case KEY_XMSS_CERT:
+ return KEY_XMSS;
default:
return type;
}
@@ -437,22 +506,16 @@ cert_free(struct sshkey_cert *cert)
if (cert == NULL)
return;
- if (cert->certblob != NULL)
- sshbuf_free(cert->certblob);
- if (cert->critical != NULL)
- sshbuf_free(cert->critical);
- if (cert->extensions != NULL)
- sshbuf_free(cert->extensions);
- if (cert->key_id != NULL)
- free(cert->key_id);
+ sshbuf_free(cert->certblob);
+ sshbuf_free(cert->critical);
+ sshbuf_free(cert->extensions);
+ free(cert->key_id);
for (i = 0; i < cert->nprincipals; i++)
free(cert->principals[i]);
- if (cert->principals != NULL)
- free(cert->principals);
- if (cert->signature_key != NULL)
- sshkey_free(cert->signature_key);
- explicit_bzero(cert, sizeof(*cert));
- free(cert);
+ free(cert->principals);
+ sshkey_free(cert->signature_key);
+ free(cert->signature_type);
+ freezero(cert, sizeof(*cert));
}
static struct sshkey_cert *
@@ -471,6 +534,7 @@ cert_new(void)
cert->key_id = NULL;
cert->principals = NULL;
cert->signature_key = NULL;
+ cert->signature_type = NULL;
return cert;
}
@@ -493,32 +557,21 @@ sshkey_new(int type)
k->cert = NULL;
k->ed25519_sk = NULL;
k->ed25519_pk = NULL;
+ k->xmss_sk = NULL;
+ k->xmss_pk = NULL;
switch (k->type) {
#ifdef WITH_OPENSSL
- case KEY_RSA1:
case KEY_RSA:
- case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
- if ((rsa = RSA_new()) == NULL ||
- (rsa->n = BN_new()) == NULL ||
- (rsa->e = BN_new()) == NULL) {
- if (rsa != NULL)
- RSA_free(rsa);
+ if ((rsa = RSA_new()) == NULL) {
free(k);
return NULL;
}
k->rsa = rsa;
break;
case KEY_DSA:
- case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
- if ((dsa = DSA_new()) == NULL ||
- (dsa->p = BN_new()) == NULL ||
- (dsa->q = BN_new()) == NULL ||
- (dsa->g = BN_new()) == NULL ||
- (dsa->pub_key = BN_new()) == NULL) {
- if (dsa != NULL)
- DSA_free(dsa);
+ if ((dsa = DSA_new()) == NULL) {
free(k);
return NULL;
}
@@ -526,11 +579,17 @@ sshkey_new(int type)
break;
case KEY_ECDSA:
case KEY_ECDSA_CERT:
+ case KEY_ECDSA_SK:
+ case KEY_ECDSA_SK_CERT:
/* Cannot do anything until we know the group */
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
+ case KEY_ED25519_SK:
+ case KEY_ED25519_SK_CERT:
+ case KEY_XMSS:
+ case KEY_XMSS_CERT:
/* no need to prealloc */
break;
case KEY_UNSPEC:
@@ -538,7 +597,6 @@ sshkey_new(int type)
default:
free(k);
return NULL;
- break;
}
if (sshkey_is_cert(k)) {
@@ -551,62 +609,6 @@ sshkey_new(int type)
return k;
}
-int
-sshkey_add_private(struct sshkey *k)
-{
- switch (k->type) {
-#ifdef WITH_OPENSSL
- case KEY_RSA1:
- case KEY_RSA:
- case KEY_RSA_CERT_V00:
- case KEY_RSA_CERT:
-#define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL)
- if (bn_maybe_alloc_failed(k->rsa->d) ||
- bn_maybe_alloc_failed(k->rsa->iqmp) ||
- bn_maybe_alloc_failed(k->rsa->q) ||
- bn_maybe_alloc_failed(k->rsa->p) ||
- bn_maybe_alloc_failed(k->rsa->dmq1) ||
- bn_maybe_alloc_failed(k->rsa->dmp1))
- return SSH_ERR_ALLOC_FAIL;
- break;
- case KEY_DSA:
- case KEY_DSA_CERT_V00:
- case KEY_DSA_CERT:
- if (bn_maybe_alloc_failed(k->dsa->priv_key))
- return SSH_ERR_ALLOC_FAIL;
- break;
-#undef bn_maybe_alloc_failed
- case KEY_ECDSA:
- case KEY_ECDSA_CERT:
- /* Cannot do anything until we know the group */
- break;
-#endif /* WITH_OPENSSL */
- case KEY_ED25519:
- case KEY_ED25519_CERT:
- /* no need to prealloc */
- break;
- case KEY_UNSPEC:
- break;
- default:
- return SSH_ERR_INVALID_ARGUMENT;
- }
- return 0;
-}
-
-struct sshkey *
-sshkey_new_private(int type)
-{
- struct sshkey *k = sshkey_new(type);
-
- if (k == NULL)
- return NULL;
- if (sshkey_add_private(k) != 0) {
- sshkey_free(k);
- return NULL;
- }
- return k;
-}
-
void
sshkey_free(struct sshkey *k)
{
@@ -614,43 +616,57 @@ sshkey_free(struct sshkey *k)
return;
switch (k->type) {
#ifdef WITH_OPENSSL
- case KEY_RSA1:
case KEY_RSA:
- case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
- if (k->rsa != NULL)
- RSA_free(k->rsa);
+ RSA_free(k->rsa);
k->rsa = NULL;
break;
case KEY_DSA:
- case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
- if (k->dsa != NULL)
- DSA_free(k->dsa);
+ DSA_free(k->dsa);
k->dsa = NULL;
break;
# ifdef OPENSSL_HAS_ECC
+ case KEY_ECDSA_SK:
+ case KEY_ECDSA_SK_CERT:
+ free(k->sk_application);
+ sshbuf_free(k->sk_key_handle);
+ sshbuf_free(k->sk_reserved);
+ /* FALLTHROUGH */
case KEY_ECDSA:
case KEY_ECDSA_CERT:
- if (k->ecdsa != NULL)
- EC_KEY_free(k->ecdsa);
+ EC_KEY_free(k->ecdsa);
k->ecdsa = NULL;
break;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
+ case KEY_ED25519_SK:
+ case KEY_ED25519_SK_CERT:
+ free(k->sk_application);
+ sshbuf_free(k->sk_key_handle);
+ sshbuf_free(k->sk_reserved);
+ /* FALLTHROUGH */
case KEY_ED25519:
case KEY_ED25519_CERT:
- if (k->ed25519_pk) {
- explicit_bzero(k->ed25519_pk, ED25519_PK_SZ);
- free(k->ed25519_pk);
- k->ed25519_pk = NULL;
- }
- if (k->ed25519_sk) {
- explicit_bzero(k->ed25519_sk, ED25519_SK_SZ);
- free(k->ed25519_sk);
- k->ed25519_sk = NULL;
- }
+ freezero(k->ed25519_pk, ED25519_PK_SZ);
+ k->ed25519_pk = NULL;
+ freezero(k->ed25519_sk, ED25519_SK_SZ);
+ k->ed25519_sk = NULL;
break;
+#ifdef WITH_XMSS
+ case KEY_XMSS:
+ case KEY_XMSS_CERT:
+ freezero(k->xmss_pk, sshkey_xmss_pklen(k));
+ k->xmss_pk = NULL;
+ freezero(k->xmss_sk, sshkey_xmss_sklen(k));
+ k->xmss_sk = NULL;
+ sshkey_xmss_free_state(k);
+ free(k->xmss_name);
+ k->xmss_name = NULL;
+ free(k->xmss_filename);
+ k->xmss_filename = NULL;
+ break;
+#endif /* WITH_XMSS */
case KEY_UNSPEC:
break;
default:
@@ -658,8 +674,9 @@ sshkey_free(struct sshkey *k)
}
if (sshkey_is_cert(k))
cert_free(k->cert);
- explicit_bzero(k, sizeof(*k));
- free(k);
+ freezero(k->shielded_private, k->shielded_len);
+ freezero(k->shield_prekey, k->shield_prekey_len);
+ freezero(k, sizeof(*k));
}
static int
@@ -684,9 +701,12 @@ cert_compare(struct sshkey_cert *a, struct sshkey_cert *b)
int
sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
{
-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
- BN_CTX *bnctx;
-#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
+#if defined(WITH_OPENSSL)
+ const BIGNUM *rsa_e_a, *rsa_n_a;
+ const BIGNUM *rsa_e_b, *rsa_n_b;
+ const BIGNUM *dsa_p_a, *dsa_q_a, *dsa_g_a, *dsa_pub_key_a;
+ const BIGNUM *dsa_p_b, *dsa_q_b, *dsa_g_b, *dsa_pub_key_b;
+#endif /* WITH_OPENSSL */
if (a == NULL || b == NULL ||
sshkey_type_plain(a->type) != sshkey_type_plain(b->type))
@@ -694,46 +714,67 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
switch (a->type) {
#ifdef WITH_OPENSSL
- case KEY_RSA1:
- case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
case KEY_RSA:
- return a->rsa != NULL && b->rsa != NULL &&
- BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
- BN_cmp(a->rsa->n, b->rsa->n) == 0;
- case KEY_DSA_CERT_V00:
+ if (a->rsa == NULL || b->rsa == NULL)
+ return 0;
+ RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL);
+ RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL);
+ return BN_cmp(rsa_e_a, rsa_e_b) == 0 &&
+ BN_cmp(rsa_n_a, rsa_n_b) == 0;
case KEY_DSA_CERT:
case KEY_DSA:
- return a->dsa != NULL && b->dsa != NULL &&
- BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
- BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
- BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
- BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
+ if (a->dsa == NULL || b->dsa == NULL)
+ return 0;
+ DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a);
+ DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b);
+ DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL);
+ DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL);
+ return BN_cmp(dsa_p_a, dsa_p_b) == 0 &&
+ BN_cmp(dsa_q_a, dsa_q_b) == 0 &&
+ BN_cmp(dsa_g_a, dsa_g_b) == 0 &&
+ BN_cmp(dsa_pub_key_a, dsa_pub_key_b) == 0;
# ifdef OPENSSL_HAS_ECC
+ case KEY_ECDSA_SK:
+ case KEY_ECDSA_SK_CERT:
+ if (a->sk_application == NULL || b->sk_application == NULL)
+ return 0;
+ if (strcmp(a->sk_application, b->sk_application) != 0)
+ return 0;
+ /* FALLTHROUGH */
case KEY_ECDSA_CERT:
case KEY_ECDSA:
if (a->ecdsa == NULL || b->ecdsa == NULL ||
EC_KEY_get0_public_key(a->ecdsa) == NULL ||
EC_KEY_get0_public_key(b->ecdsa) == NULL)
return 0;
- if ((bnctx = BN_CTX_new()) == NULL)
- return 0;
if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
- EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
+ EC_KEY_get0_group(b->ecdsa), NULL) != 0 ||
EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
EC_KEY_get0_public_key(a->ecdsa),
- EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
- BN_CTX_free(bnctx);
+ EC_KEY_get0_public_key(b->ecdsa), NULL) != 0)
return 0;
- }
- BN_CTX_free(bnctx);
return 1;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
+ case KEY_ED25519_SK:
+ case KEY_ED25519_SK_CERT:
+ if (a->sk_application == NULL || b->sk_application == NULL)
+ return 0;
+ if (strcmp(a->sk_application, b->sk_application) != 0)
+ return 0;
+ /* FALLTHROUGH */
case KEY_ED25519:
case KEY_ED25519_CERT:
return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
+#ifdef WITH_XMSS
+ case KEY_XMSS:
+ case KEY_XMSS_CERT:
+ return a->xmss_pk != NULL && b->xmss_pk != NULL &&
+ sshkey_xmss_pklen(a) == sshkey_xmss_pklen(b) &&
+ memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) == 0;
+#endif /* WITH_XMSS */
default:
return 0;
}
@@ -753,26 +794,39 @@ sshkey_equal(const struct sshkey *a, const struct sshkey *b)
}
static int
-to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)
+to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
+ enum sshkey_serialize_rep opts)
{
int type, ret = SSH_ERR_INTERNAL_ERROR;
const char *typename;
+#ifdef WITH_OPENSSL
+ const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
+#endif /* WITH_OPENSSL */
if (key == NULL)
return SSH_ERR_INVALID_ARGUMENT;
+ if (sshkey_is_cert(key)) {
+ if (key->cert == NULL)
+ return SSH_ERR_EXPECTED_CERT;
+ if (sshbuf_len(key->cert->certblob) == 0)
+ return SSH_ERR_KEY_LACKS_CERTBLOB;
+ }
type = force_plain ? sshkey_type_plain(key->type) : key->type;
typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
switch (type) {
#ifdef WITH_OPENSSL
- case KEY_DSA_CERT_V00:
- case KEY_RSA_CERT_V00:
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
+ case KEY_ECDSA_SK_CERT:
case KEY_RSA_CERT:
#endif /* WITH_OPENSSL */
case KEY_ED25519_CERT:
+ case KEY_ED25519_SK_CERT:
+#ifdef WITH_XMSS
+ case KEY_XMSS_CERT:
+#endif /* WITH_XMSS */
/* Use the existing blob */
/* XXX modified flag? */
if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
@@ -782,15 +836,18 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)
case KEY_DSA:
if (key->dsa == NULL)
return SSH_ERR_INVALID_ARGUMENT;
+ DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
+ DSA_get0_key(key->dsa, &dsa_pub_key, NULL);
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
- (ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 ||
- (ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
- (ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 ||
- (ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0)
+ (ret = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
+ (ret = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
+ (ret = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
+ (ret = sshbuf_put_bignum2(b, dsa_pub_key)) != 0)
return ret;
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
+ case KEY_ECDSA_SK:
if (key->ecdsa == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
@@ -798,25 +855,50 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)
sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
(ret = sshbuf_put_eckey(b, key->ecdsa)) != 0)
return ret;
+ if (type == KEY_ECDSA_SK) {
+ if ((ret = sshbuf_put_cstring(b,
+ key->sk_application)) != 0)
+ return ret;
+ }
break;
# endif
case KEY_RSA:
if (key->rsa == NULL)
return SSH_ERR_INVALID_ARGUMENT;
+ RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL);
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
- (ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 ||
- (ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0)
+ (ret = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
+ (ret = sshbuf_put_bignum2(b, rsa_n)) != 0)
return ret;
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
+ case KEY_ED25519_SK:
if (key->ed25519_pk == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
(ret = sshbuf_put_string(b,
key->ed25519_pk, ED25519_PK_SZ)) != 0)
return ret;
+ if (type == KEY_ED25519_SK) {
+ if ((ret = sshbuf_put_cstring(b,
+ key->sk_application)) != 0)
+ return ret;
+ }
+ break;
+#ifdef WITH_XMSS
+ case KEY_XMSS:
+ if (key->xmss_name == NULL || key->xmss_pk == NULL ||
+ sshkey_xmss_pklen(key) == 0)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
+ (ret = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
+ (ret = sshbuf_put_string(b,
+ key->xmss_pk, sshkey_xmss_pklen(key))) != 0 ||
+ (ret = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
+ return ret;
break;
+#endif /* WITH_XMSS */
default:
return SSH_ERR_KEY_TYPE_UNKNOWN;
}
@@ -826,18 +908,19 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)
int
sshkey_putb(const struct sshkey *key, struct sshbuf *b)
{
- return to_blob_buf(key, b, 0);
+ return to_blob_buf(key, b, 0, SSHKEY_SERIALIZE_DEFAULT);
}
int
-sshkey_puts(const struct sshkey *key, struct sshbuf *b)
+sshkey_puts_opts(const struct sshkey *key, struct sshbuf *b,
+ enum sshkey_serialize_rep opts)
{
struct sshbuf *tmp;
int r;
if ((tmp = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- r = to_blob_buf(key, tmp, 0);
+ r = to_blob_buf(key, tmp, 0, opts);
if (r == 0)
r = sshbuf_put_stringb(b, tmp);
sshbuf_free(tmp);
@@ -845,13 +928,20 @@ sshkey_puts(const struct sshkey *key, struct sshbuf *b)
}
int
+sshkey_puts(const struct sshkey *key, struct sshbuf *b)
+{
+ return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT);
+}
+
+int
sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b)
{
- return to_blob_buf(key, b, 1);
+ return to_blob_buf(key, b, 1, SSHKEY_SERIALIZE_DEFAULT);
}
static int
-to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain)
+to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain,
+ enum sshkey_serialize_rep opts)
{
int ret = SSH_ERR_INTERNAL_ERROR;
size_t len;
@@ -863,7 +953,7 @@ to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain)
*blobp = NULL;
if ((b = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if ((ret = to_blob_buf(key, b, force_plain)) != 0)
+ if ((ret = to_blob_buf(key, b, force_plain, opts)) != 0)
goto out;
len = sshbuf_len(b);
if (lenp != NULL)
@@ -884,13 +974,13 @@ to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain)
int
sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
{
- return to_blob(key, blobp, lenp, 0);
+ return to_blob(key, blobp, lenp, 0, SSHKEY_SERIALIZE_DEFAULT);
}
int
sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
{
- return to_blob(key, blobp, lenp, 1);
+ return to_blob(key, blobp, lenp, 1, SSHKEY_SERIALIZE_DEFAULT);
}
int
@@ -909,22 +999,8 @@ sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
-
- if (k->type == KEY_RSA1) {
-#ifdef WITH_OPENSSL
- int nlen = BN_num_bytes(k->rsa->n);
- int elen = BN_num_bytes(k->rsa->e);
-
- blob_len = nlen + elen;
- if (nlen >= INT_MAX - elen ||
- (blob = malloc(blob_len)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- BN_bn2bin(k->rsa->n, blob);
- BN_bn2bin(k->rsa->e, blob + nlen);
-#endif /* WITH_OPENSSL */
- } else if ((r = to_blob(k, &blob, &blob_len, 1)) != 0)
+ if ((r = to_blob(k, &blob, &blob_len, 1, SSHKEY_SERIALIZE_DEFAULT))
+ != 0)
goto out;
if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
@@ -943,10 +1019,8 @@ sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
r = 0;
out:
free(ret);
- if (blob != NULL) {
- explicit_bzero(blob, blob_len);
- free(blob);
- }
+ if (blob != NULL)
+ freezero(blob, blob_len);
return r;
}
@@ -956,7 +1030,6 @@ fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
char *ret;
size_t plen = strlen(alg) + 1;
size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1;
- int r;
if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL)
return NULL;
@@ -964,10 +1037,8 @@ fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
strlcat(ret, ":", rlen);
if (dgst_raw_len == 0)
return ret;
- if ((r = b64_ntop(dgst_raw, dgst_raw_len,
- ret + plen, rlen - plen)) == -1) {
- explicit_bzero(ret, rlen);
- free(ret);
+ if (b64_ntop(dgst_raw, dgst_raw_len, ret + plen, rlen - plen) == -1) {
+ freezero(ret, rlen);
return NULL;
}
/* Trim padding characters from end */
@@ -1109,10 +1180,10 @@ fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
y += (input & 0x2) ? 1 : -1;
/* assure we are still in bounds */
- x = MAX(x, 0);
- y = MAX(y, 0);
- x = MIN(x, FLDSIZE_X - 1);
- y = MIN(y, FLDSIZE_Y - 1);
+ x = MAXIMUM(x, 0);
+ y = MAXIMUM(y, 0);
+ x = MINIMUM(x, FLDSIZE_X - 1);
+ y = MINIMUM(y, FLDSIZE_Y - 1);
/* augment the field */
if (field[x][y] < len - 2)
@@ -1153,7 +1224,7 @@ fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
for (y = 0; y < FLDSIZE_Y; y++) {
*p++ = '|';
for (x = 0; x < FLDSIZE_X; x++)
- *p++ = augmentation_string[MIN(field[x][y], len)];
+ *p++ = augmentation_string[MINIMUM(field[x][y], len)];
*p++ = '|';
*p++ = '\n';
}
@@ -1207,300 +1278,286 @@ sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
dgst_raw, dgst_raw_len, k);
break;
default:
- explicit_bzero(dgst_raw, dgst_raw_len);
- free(dgst_raw);
+ freezero(dgst_raw, dgst_raw_len);
return NULL;
}
- explicit_bzero(dgst_raw, dgst_raw_len);
- free(dgst_raw);
+ freezero(dgst_raw, dgst_raw_len);
return retval;
}
-#ifdef WITH_SSH1
-/*
- * Reads a multiple-precision integer in decimal from the buffer, and advances
- * the pointer. The integer must already be initialized. This function is
- * permitted to modify the buffer. This leaves *cpp to point just beyond the
- * last processed character.
- */
static int
-read_decimal_bignum(char **cpp, BIGNUM *v)
+peek_type_nid(const char *s, size_t l, int *nid)
{
- char *cp;
- size_t e;
- int skip = 1; /* skip white space */
+ const struct keytype *kt;
- cp = *cpp;
- while (*cp == ' ' || *cp == '\t')
- cp++;
- e = strspn(cp, "0123456789");
- if (e == 0)
- return SSH_ERR_INVALID_FORMAT;
- if (e > SSHBUF_MAX_BIGNUM * 3)
- return SSH_ERR_BIGNUM_TOO_LARGE;
- if (cp[e] == '\0')
- skip = 0;
- else if (index(" \t\r\n", cp[e]) == NULL)
- return SSH_ERR_INVALID_FORMAT;
- cp[e] = '\0';
- if (BN_dec2bn(&v, cp) <= 0)
- return SSH_ERR_INVALID_FORMAT;
- *cpp = cp + e + skip;
- return 0;
+ for (kt = keytypes; kt->type != -1; kt++) {
+ if (kt->name == NULL || strlen(kt->name) != l)
+ continue;
+ if (memcmp(s, kt->name, l) == 0) {
+ *nid = -1;
+ if (key_type_is_ecdsa_variant(kt->type))
+ *nid = kt->nid;
+ return kt->type;
+ }
+ }
+ return KEY_UNSPEC;
}
-#endif /* WITH_SSH1 */
-/* returns 0 ok, and < 0 error */
+/* XXX this can now be made const char * */
int
sshkey_read(struct sshkey *ret, char **cpp)
{
struct sshkey *k;
- int retval = SSH_ERR_INVALID_FORMAT;
- char *cp, *space;
+ char *cp, *blobcopy;
+ size_t space;
int r, type, curve_nid = -1;
struct sshbuf *blob;
-#ifdef WITH_SSH1
- char *ep;
- u_long bits;
-#endif /* WITH_SSH1 */
- cp = *cpp;
+ if (ret == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
switch (ret->type) {
- case KEY_RSA1:
-#ifdef WITH_SSH1
- /* Get number of bits. */
- bits = strtoul(cp, &ep, 10);
- if (*cp == '\0' || index(" \t\r\n", *ep) == NULL ||
- bits == 0 || bits > SSHBUF_MAX_BIGNUM * 8)
- return SSH_ERR_INVALID_FORMAT; /* Bad bit count... */
- /* Get public exponent, public modulus. */
- if ((r = read_decimal_bignum(&ep, ret->rsa->e)) < 0)
- return r;
- if ((r = read_decimal_bignum(&ep, ret->rsa->n)) < 0)
- return r;
- *cpp = ep;
- /* validate the claimed number of bits */
- if (BN_num_bits(ret->rsa->n) != (int)bits)
- return SSH_ERR_KEY_BITS_MISMATCH;
- retval = 0;
-#endif /* WITH_SSH1 */
- break;
case KEY_UNSPEC:
case KEY_RSA:
case KEY_DSA:
case KEY_ECDSA:
+ case KEY_ECDSA_SK:
case KEY_ED25519:
- case KEY_DSA_CERT_V00:
- case KEY_RSA_CERT_V00:
+ case KEY_ED25519_SK:
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
+ case KEY_ECDSA_SK_CERT:
case KEY_RSA_CERT:
case KEY_ED25519_CERT:
- space = strchr(cp, ' ');
- if (space == NULL)
- return SSH_ERR_INVALID_FORMAT;
- *space = '\0';
- type = sshkey_type_from_name(cp);
- if (sshkey_type_plain(type) == KEY_ECDSA &&
- (curve_nid = sshkey_ecdsa_nid_from_name(cp)) == -1)
- return SSH_ERR_EC_CURVE_INVALID;
- *space = ' ';
- if (type == KEY_UNSPEC)
- return SSH_ERR_INVALID_FORMAT;
- cp = space+1;
- if (*cp == '\0')
- return SSH_ERR_INVALID_FORMAT;
- if (ret->type != KEY_UNSPEC && ret->type != type)
- return SSH_ERR_KEY_TYPE_MISMATCH;
- if ((blob = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- /* trim comment */
- space = strchr(cp, ' ');
- if (space) {
- /* advance 'space': skip whitespace */
- *space++ = '\0';
- while (*space == ' ' || *space == '\t')
- space++;
- *cpp = space;
- } else
- *cpp = cp + strlen(cp);
- if ((r = sshbuf_b64tod(blob, cp)) != 0) {
- sshbuf_free(blob);
- return r;
- }
- if ((r = sshkey_from_blob(sshbuf_ptr(blob),
- sshbuf_len(blob), &k)) != 0) {
- sshbuf_free(blob);
- return r;
- }
+ case KEY_ED25519_SK_CERT:
+#ifdef WITH_XMSS
+ case KEY_XMSS:
+ case KEY_XMSS_CERT:
+#endif /* WITH_XMSS */
+ break; /* ok */
+ default:
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+
+ /* Decode type */
+ cp = *cpp;
+ space = strcspn(cp, " \t");
+ if (space == strlen(cp))
+ return SSH_ERR_INVALID_FORMAT;
+ if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC)
+ return SSH_ERR_INVALID_FORMAT;
+
+ /* skip whitespace */
+ for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+ if (*cp == '\0')
+ return SSH_ERR_INVALID_FORMAT;
+ if (ret->type != KEY_UNSPEC && ret->type != type)
+ return SSH_ERR_KEY_TYPE_MISMATCH;
+ if ((blob = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+
+ /* find end of keyblob and decode */
+ space = strcspn(cp, " \t");
+ if ((blobcopy = strndup(cp, space)) == NULL) {
sshbuf_free(blob);
- if (k->type != type) {
- sshkey_free(k);
- return SSH_ERR_KEY_TYPE_MISMATCH;
- }
- if (sshkey_type_plain(type) == KEY_ECDSA &&
- curve_nid != k->ecdsa_nid) {
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ if ((r = sshbuf_b64tod(blob, blobcopy)) != 0) {
+ free(blobcopy);
+ sshbuf_free(blob);
+ return r;
+ }
+ free(blobcopy);
+ if ((r = sshkey_fromb(blob, &k)) != 0) {
+ sshbuf_free(blob);
+ return r;
+ }
+ sshbuf_free(blob);
+
+ /* skip whitespace and leave cp at start of comment */
+ for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+
+ /* ensure type of blob matches type at start of line */
+ if (k->type != type) {
+ sshkey_free(k);
+ return SSH_ERR_KEY_TYPE_MISMATCH;
+ }
+ if (key_type_is_ecdsa_variant(type) && curve_nid != k->ecdsa_nid) {
+ sshkey_free(k);
+ return SSH_ERR_EC_CURVE_MISMATCH;
+ }
+
+ /* Fill in ret from parsed key */
+ ret->type = type;
+ if (sshkey_is_cert(ret)) {
+ if (!sshkey_is_cert(k)) {
sshkey_free(k);
- return SSH_ERR_EC_CURVE_MISMATCH;
- }
- ret->type = type;
- if (sshkey_is_cert(ret)) {
- if (!sshkey_is_cert(k)) {
- sshkey_free(k);
- return SSH_ERR_EXPECTED_CERT;
- }
- if (ret->cert != NULL)
- cert_free(ret->cert);
- ret->cert = k->cert;
- k->cert = NULL;
+ return SSH_ERR_EXPECTED_CERT;
}
+ if (ret->cert != NULL)
+ cert_free(ret->cert);
+ ret->cert = k->cert;
+ k->cert = NULL;
+ }
+ switch (sshkey_type_plain(ret->type)) {
#ifdef WITH_OPENSSL
- if (sshkey_type_plain(ret->type) == KEY_RSA) {
- if (ret->rsa != NULL)
- RSA_free(ret->rsa);
- ret->rsa = k->rsa;
- k->rsa = NULL;
+ case KEY_RSA:
+ RSA_free(ret->rsa);
+ ret->rsa = k->rsa;
+ k->rsa = NULL;
#ifdef DEBUG_PK
- RSA_print_fp(stderr, ret->rsa, 8);
+ RSA_print_fp(stderr, ret->rsa, 8);
#endif
- }
- if (sshkey_type_plain(ret->type) == KEY_DSA) {
- if (ret->dsa != NULL)
- DSA_free(ret->dsa);
- ret->dsa = k->dsa;
- k->dsa = NULL;
+ break;
+ case KEY_DSA:
+ DSA_free(ret->dsa);
+ ret->dsa = k->dsa;
+ k->dsa = NULL;
#ifdef DEBUG_PK
- DSA_print_fp(stderr, ret->dsa, 8);
+ DSA_print_fp(stderr, ret->dsa, 8);
#endif
- }
+ break;
# ifdef OPENSSL_HAS_ECC
- if (sshkey_type_plain(ret->type) == KEY_ECDSA) {
- if (ret->ecdsa != NULL)
- EC_KEY_free(ret->ecdsa);
- ret->ecdsa = k->ecdsa;
- ret->ecdsa_nid = k->ecdsa_nid;
- k->ecdsa = NULL;
- k->ecdsa_nid = -1;
+ case KEY_ECDSA:
+ EC_KEY_free(ret->ecdsa);
+ ret->ecdsa = k->ecdsa;
+ ret->ecdsa_nid = k->ecdsa_nid;
+ k->ecdsa = NULL;
+ k->ecdsa_nid = -1;
#ifdef DEBUG_PK
- sshkey_dump_ec_key(ret->ecdsa);
+ sshkey_dump_ec_key(ret->ecdsa);
#endif
- }
+ break;
+ case KEY_ECDSA_SK:
+ EC_KEY_free(ret->ecdsa);
+ ret->ecdsa = k->ecdsa;
+ ret->ecdsa_nid = k->ecdsa_nid;
+ ret->sk_application = k->sk_application;
+ k->ecdsa = NULL;
+ k->ecdsa_nid = -1;
+ k->sk_application = NULL;
+#ifdef DEBUG_PK
+ sshkey_dump_ec_key(ret->ecdsa);
+ fprintf(stderr, "App: %s\n", ret->sk_application);
+#endif
+ break;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
- if (sshkey_type_plain(ret->type) == KEY_ED25519) {
- free(ret->ed25519_pk);
- ret->ed25519_pk = k->ed25519_pk;
- k->ed25519_pk = NULL;
+ case KEY_ED25519:
+ freezero(ret->ed25519_pk, ED25519_PK_SZ);
+ ret->ed25519_pk = k->ed25519_pk;
+ k->ed25519_pk = NULL;
#ifdef DEBUG_PK
- /* XXX */
+ /* XXX */
+#endif
+ break;
+ case KEY_ED25519_SK:
+ freezero(ret->ed25519_pk, ED25519_PK_SZ);
+ ret->ed25519_pk = k->ed25519_pk;
+ ret->sk_application = k->sk_application;
+ k->ed25519_pk = NULL;
+ k->sk_application = NULL;
+ break;
+#ifdef WITH_XMSS
+ case KEY_XMSS:
+ free(ret->xmss_pk);
+ ret->xmss_pk = k->xmss_pk;
+ k->xmss_pk = NULL;
+ free(ret->xmss_state);
+ ret->xmss_state = k->xmss_state;
+ k->xmss_state = NULL;
+ free(ret->xmss_name);
+ ret->xmss_name = k->xmss_name;
+ k->xmss_name = NULL;
+ free(ret->xmss_filename);
+ ret->xmss_filename = k->xmss_filename;
+ k->xmss_filename = NULL;
+#ifdef DEBUG_PK
+ /* XXX */
#endif
- }
- retval = 0;
-/*XXXX*/
- sshkey_free(k);
- if (retval != 0)
- break;
break;
+#endif /* WITH_XMSS */
default:
- return SSH_ERR_INVALID_ARGUMENT;
+ sshkey_free(k);
+ return SSH_ERR_INTERNAL_ERROR;
}
- return retval;
+ sshkey_free(k);
+
+ /* success */
+ *cpp = cp;
+ return 0;
}
+
int
-sshkey_write(const struct sshkey *key, FILE *f)
+sshkey_to_base64(const struct sshkey *key, char **b64p)
{
- int ret = SSH_ERR_INTERNAL_ERROR;
- struct sshbuf *b = NULL, *bb = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ struct sshbuf *b = NULL;
char *uu = NULL;
-#ifdef WITH_SSH1
- u_int bits = 0;
- char *dec_e = NULL, *dec_n = NULL;
-#endif /* WITH_SSH1 */
- if (sshkey_is_cert(key)) {
- if (key->cert == NULL)
- return SSH_ERR_EXPECTED_CERT;
- if (sshbuf_len(key->cert->certblob) == 0)
- return SSH_ERR_KEY_LACKS_CERTBLOB;
- }
+ if (b64p != NULL)
+ *b64p = NULL;
if ((b = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- switch (key->type) {
-#ifdef WITH_SSH1
- case KEY_RSA1:
- if (key->rsa == NULL || key->rsa->e == NULL ||
- key->rsa->n == NULL) {
- ret = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL ||
- (dec_n = BN_bn2dec(key->rsa->n)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- /* size of modulus 'n' */
- if ((bits = BN_num_bits(key->rsa->n)) <= 0) {
- ret = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- if ((ret = sshbuf_putf(b, "%u %s %s", bits, dec_e, dec_n)) != 0)
- goto out;
-#endif /* WITH_SSH1 */
- break;
-#ifdef WITH_OPENSSL
- case KEY_DSA:
- case KEY_DSA_CERT_V00:
- case KEY_DSA_CERT:
- case KEY_ECDSA:
- case KEY_ECDSA_CERT:
- case KEY_RSA:
- case KEY_RSA_CERT_V00:
- case KEY_RSA_CERT:
-#endif /* WITH_OPENSSL */
- case KEY_ED25519:
- case KEY_ED25519_CERT:
- if ((bb = sshbuf_new()) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((ret = sshkey_putb(key, bb)) != 0)
- goto out;
- if ((uu = sshbuf_dtob64(bb)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((ret = sshbuf_putf(b, "%s ", sshkey_ssh_name(key))) != 0)
- goto out;
- if ((ret = sshbuf_put(b, uu, strlen(uu))) != 0)
- goto out;
- break;
- default:
- ret = SSH_ERR_KEY_TYPE_UNKNOWN;
+ if ((r = sshkey_putb(key, b)) != 0)
+ goto out;
+ if ((uu = sshbuf_dtob64_string(b, 0)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
goto out;
}
+ /* Success */
+ if (b64p != NULL) {
+ *b64p = uu;
+ uu = NULL;
+ }
+ r = 0;
+ out:
+ sshbuf_free(b);
+ free(uu);
+ return r;
+}
+
+int
+sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
+{
+ int r = SSH_ERR_INTERNAL_ERROR;
+ char *uu = NULL;
+
+ if ((r = sshkey_to_base64(key, &uu)) != 0)
+ goto out;
+ if ((r = sshbuf_putf(b, "%s %s",
+ sshkey_ssh_name(key), uu)) != 0)
+ goto out;
+ r = 0;
+ out:
+ free(uu);
+ return r;
+}
+
+int
+sshkey_write(const struct sshkey *key, FILE *f)
+{
+ struct sshbuf *b = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if ((b = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((r = sshkey_format_text(key, b)) != 0)
+ goto out;
if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) {
if (feof(f))
errno = EPIPE;
- ret = SSH_ERR_SYSTEM_ERROR;
+ r = SSH_ERR_SYSTEM_ERROR;
goto out;
}
- ret = 0;
+ /* Success */
+ r = 0;
out:
- if (b != NULL)
- sshbuf_free(b);
- if (bb != NULL)
- sshbuf_free(bb);
- if (uu != NULL)
- free(uu);
-#ifdef WITH_SSH1
- if (dec_e != NULL)
- OPENSSL_free(dec_e);
- if (dec_n != NULL)
- OPENSSL_free(dec_n);
-#endif /* WITH_SSH1 */
- return ret;
+ sshbuf_free(b);
+ return r;
}
const char *
@@ -1524,10 +1581,11 @@ rsa_generate_private_key(u_int bits, RSA **rsap)
BIGNUM *f4 = NULL;
int ret = SSH_ERR_INTERNAL_ERROR;
- if (rsap == NULL ||
- bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
- bits > SSHBUF_MAX_BIGNUM * 8)
+ if (rsap == NULL)
return SSH_ERR_INVALID_ARGUMENT;
+ if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
+ bits > SSHBUF_MAX_BIGNUM * 8)
+ return SSH_ERR_KEY_LENGTH;
*rsap = NULL;
if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
@@ -1542,10 +1600,8 @@ rsa_generate_private_key(u_int bits, RSA **rsap)
private = NULL;
ret = 0;
out:
- if (private != NULL)
- RSA_free(private);
- if (f4 != NULL)
- BN_free(f4);
+ RSA_free(private);
+ BN_free(f4);
return ret;
}
@@ -1555,8 +1611,10 @@ dsa_generate_private_key(u_int bits, DSA **dsap)
DSA *private;
int ret = SSH_ERR_INTERNAL_ERROR;
- if (dsap == NULL || bits != 1024)
+ if (dsap == NULL)
return SSH_ERR_INVALID_ARGUMENT;
+ if (bits != 1024)
+ return SSH_ERR_KEY_LENGTH;
if ((private = DSA_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
@@ -1564,7 +1622,6 @@ dsa_generate_private_key(u_int bits, DSA **dsap)
*dsap = NULL;
if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
NULL, NULL) || !DSA_generate_key(private)) {
- DSA_free(private);
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
@@ -1572,8 +1629,7 @@ dsa_generate_private_key(u_int bits, DSA **dsap)
private = NULL;
ret = 0;
out:
- if (private != NULL)
- DSA_free(private);
+ DSA_free(private);
return ret;
}
@@ -1592,7 +1648,6 @@ sshkey_ecdsa_key_to_nid(EC_KEY *k)
};
int nid;
u_int i;
- BN_CTX *bnctx;
const EC_GROUP *g = EC_KEY_get0_group(k);
/*
@@ -1605,18 +1660,13 @@ sshkey_ecdsa_key_to_nid(EC_KEY *k)
*/
if ((nid = EC_GROUP_get_curve_name(g)) > 0)
return nid;
- if ((bnctx = BN_CTX_new()) == NULL)
- return -1;
for (i = 0; nids[i] != -1; i++) {
- if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) {
- BN_CTX_free(bnctx);
+ if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
return -1;
- }
- if (EC_GROUP_cmp(g, eg, bnctx) == 0)
+ if (EC_GROUP_cmp(g, eg, NULL) == 0)
break;
EC_GROUP_free(eg);
}
- BN_CTX_free(bnctx);
if (nids[i] != -1) {
/* Use the group with the NID attached */
EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
@@ -1634,9 +1684,10 @@ ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap)
EC_KEY *private;
int ret = SSH_ERR_INTERNAL_ERROR;
- if (nid == NULL || ecdsap == NULL ||
- (*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
+ if (nid == NULL || ecdsap == NULL)
return SSH_ERR_INVALID_ARGUMENT;
+ if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
+ return SSH_ERR_KEY_LENGTH;
*ecdsap = NULL;
if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
@@ -1651,8 +1702,7 @@ ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap)
private = NULL;
ret = 0;
out:
- if (private != NULL)
- EC_KEY_free(private);
+ EC_KEY_free(private);
return ret;
}
# endif /* OPENSSL_HAS_ECC */
@@ -1679,6 +1729,11 @@ sshkey_generate(int type, u_int bits, struct sshkey **keyp)
crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
ret = 0;
break;
+#ifdef WITH_XMSS
+ case KEY_XMSS:
+ ret = sshkey_xmss_generate_private_key(k, bits);
+ break;
+#endif /* WITH_XMSS */
#ifdef WITH_OPENSSL
case KEY_DSA:
ret = dsa_generate_private_key(bits, &k->dsa);
@@ -1690,7 +1745,6 @@ sshkey_generate(int type, u_int bits, struct sshkey **keyp)
break;
# endif /* OPENSSL_HAS_ECC */
case KEY_RSA:
- case KEY_RSA1:
ret = rsa_generate_private_key(bits, &k->rsa);
break;
#endif /* WITH_OPENSSL */
@@ -1711,134 +1765,430 @@ sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key)
u_int i;
const struct sshkey_cert *from;
struct sshkey_cert *to;
- int ret = SSH_ERR_INTERNAL_ERROR;
-
- if (to_key->cert != NULL) {
- cert_free(to_key->cert);
- to_key->cert = NULL;
- }
+ int r = SSH_ERR_INTERNAL_ERROR;
- if ((from = from_key->cert) == NULL)
+ if (to_key == NULL || (from = from_key->cert) == NULL)
return SSH_ERR_INVALID_ARGUMENT;
- if ((to = to_key->cert = cert_new()) == NULL)
+ if ((to = cert_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if ((ret = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
- (ret = sshbuf_putb(to->critical, from->critical)) != 0 ||
- (ret = sshbuf_putb(to->extensions, from->extensions) != 0))
- return ret;
+ if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
+ (r = sshbuf_putb(to->critical, from->critical)) != 0 ||
+ (r = sshbuf_putb(to->extensions, from->extensions)) != 0)
+ goto out;
to->serial = from->serial;
to->type = from->type;
if (from->key_id == NULL)
to->key_id = NULL;
- else if ((to->key_id = strdup(from->key_id)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
+ else if ((to->key_id = strdup(from->key_id)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
to->valid_after = from->valid_after;
to->valid_before = from->valid_before;
if (from->signature_key == NULL)
to->signature_key = NULL;
- else if ((ret = sshkey_from_private(from->signature_key,
+ else if ((r = sshkey_from_private(from->signature_key,
&to->signature_key)) != 0)
- return ret;
-
- if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS)
- return SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ if (from->signature_type != NULL &&
+ (to->signature_type = strdup(from->signature_type)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
if (from->nprincipals > 0) {
if ((to->principals = calloc(from->nprincipals,
- sizeof(*to->principals))) == NULL)
- return SSH_ERR_ALLOC_FAIL;
+ sizeof(*to->principals))) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
for (i = 0; i < from->nprincipals; i++) {
to->principals[i] = strdup(from->principals[i]);
if (to->principals[i] == NULL) {
to->nprincipals = i;
- return SSH_ERR_ALLOC_FAIL;
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
}
}
}
to->nprincipals = from->nprincipals;
- return 0;
+
+ /* success */
+ cert_free(to_key->cert);
+ to_key->cert = to;
+ to = NULL;
+ r = 0;
+ out:
+ cert_free(to);
+ return r;
}
int
sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
{
struct sshkey *n = NULL;
- int ret = SSH_ERR_INTERNAL_ERROR;
-
- if (pkp != NULL)
- *pkp = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+#ifdef WITH_OPENSSL
+ const BIGNUM *rsa_n, *rsa_e;
+ BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL;
+ const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
+ BIGNUM *dsa_p_dup = NULL, *dsa_q_dup = NULL, *dsa_g_dup = NULL;
+ BIGNUM *dsa_pub_key_dup = NULL;
+#endif /* WITH_OPENSSL */
+ *pkp = NULL;
+ if ((n = sshkey_new(k->type)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
switch (k->type) {
#ifdef WITH_OPENSSL
case KEY_DSA:
- case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
- if ((n = sshkey_new(k->type)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
- (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
- (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
- (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) {
- sshkey_free(n);
- return SSH_ERR_ALLOC_FAIL;
+ DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g);
+ DSA_get0_key(k->dsa, &dsa_pub_key, NULL);
+ if ((dsa_p_dup = BN_dup(dsa_p)) == NULL ||
+ (dsa_q_dup = BN_dup(dsa_q)) == NULL ||
+ (dsa_g_dup = BN_dup(dsa_g)) == NULL ||
+ (dsa_pub_key_dup = BN_dup(dsa_pub_key)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (!DSA_set0_pqg(n->dsa, dsa_p_dup, dsa_q_dup, dsa_g_dup)) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ dsa_p_dup = dsa_q_dup = dsa_g_dup = NULL; /* transferred */
+ if (!DSA_set0_key(n->dsa, dsa_pub_key_dup, NULL)) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
}
+ dsa_pub_key_dup = NULL; /* transferred */
+
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
case KEY_ECDSA_CERT:
- if ((n = sshkey_new(k->type)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
+ case KEY_ECDSA_SK:
+ case KEY_ECDSA_SK_CERT:
n->ecdsa_nid = k->ecdsa_nid;
n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
if (n->ecdsa == NULL) {
- sshkey_free(n);
- return SSH_ERR_ALLOC_FAIL;
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
}
if (EC_KEY_set_public_key(n->ecdsa,
EC_KEY_get0_public_key(k->ecdsa)) != 1) {
- sshkey_free(n);
- return SSH_ERR_LIBCRYPTO_ERROR;
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
}
+ if (k->type != KEY_ECDSA_SK && k->type != KEY_ECDSA_SK_CERT)
+ break;
+ /* Append security-key application string */
+ if ((n->sk_application = strdup(k->sk_application)) == NULL)
+ goto out;
break;
# endif /* OPENSSL_HAS_ECC */
case KEY_RSA:
- case KEY_RSA1:
- case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
- if ((n = sshkey_new(k->type)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
- (BN_copy(n->rsa->e, k->rsa->e) == NULL)) {
- sshkey_free(n);
- return SSH_ERR_ALLOC_FAIL;
+ RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL);
+ if ((rsa_n_dup = BN_dup(rsa_n)) == NULL ||
+ (rsa_e_dup = BN_dup(rsa_e)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (!RSA_set0_key(n->rsa, rsa_n_dup, rsa_e_dup, NULL)) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
}
+ rsa_n_dup = rsa_e_dup = NULL; /* transferred */
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
- if ((n = sshkey_new(k->type)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
+ case KEY_ED25519_SK:
+ case KEY_ED25519_SK_CERT:
if (k->ed25519_pk != NULL) {
if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
- sshkey_free(n);
- return SSH_ERR_ALLOC_FAIL;
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
}
memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
}
+ if (k->type != KEY_ED25519_SK &&
+ k->type != KEY_ED25519_SK_CERT)
+ break;
+ /* Append security-key application string */
+ if ((n->sk_application = strdup(k->sk_application)) == NULL)
+ goto out;
+ break;
+#ifdef WITH_XMSS
+ case KEY_XMSS:
+ case KEY_XMSS_CERT:
+ if ((r = sshkey_xmss_init(n, k->xmss_name)) != 0)
+ goto out;
+ if (k->xmss_pk != NULL) {
+ u_int32_t left;
+ size_t pklen = sshkey_xmss_pklen(k);
+ if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) {
+ r = SSH_ERR_INTERNAL_ERROR;
+ goto out;
+ }
+ if ((n->xmss_pk = malloc(pklen)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ memcpy(n->xmss_pk, k->xmss_pk, pklen);
+ /* simulate number of signatures left on pubkey */
+ left = sshkey_xmss_signatures_left(k);
+ if (left)
+ sshkey_xmss_enable_maxsign(n, left);
+ }
break;
+#endif /* WITH_XMSS */
default:
- return SSH_ERR_KEY_TYPE_UNKNOWN;
+ r = SSH_ERR_KEY_TYPE_UNKNOWN;
+ goto out;
}
- if (sshkey_is_cert(k)) {
- if ((ret = sshkey_cert_copy(k, n)) != 0) {
- sshkey_free(n);
- return ret;
+ if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0)
+ goto out;
+ /* success */
+ *pkp = n;
+ n = NULL;
+ r = 0;
+ out:
+ sshkey_free(n);
+#ifdef WITH_OPENSSL
+ BN_clear_free(rsa_n_dup);
+ BN_clear_free(rsa_e_dup);
+ BN_clear_free(dsa_p_dup);
+ BN_clear_free(dsa_q_dup);
+ BN_clear_free(dsa_g_dup);
+ BN_clear_free(dsa_pub_key_dup);
+#endif
+
+ return r;
+}
+
+int
+sshkey_is_shielded(struct sshkey *k)
+{
+ return k != NULL && k->shielded_private != NULL;
+}
+
+int
+sshkey_shield_private(struct sshkey *k)
+{
+ struct sshbuf *prvbuf = NULL;
+ u_char *prekey = NULL, *enc = NULL, keyiv[SSH_DIGEST_MAX_LENGTH];
+ struct sshcipher_ctx *cctx = NULL;
+ const struct sshcipher *cipher;
+ size_t i, enclen = 0;
+ struct sshkey *kswap = NULL, tmp;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+#ifdef DEBUG_PK
+ fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
+#endif
+ if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
+ ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
+ r = SSH_ERR_INTERNAL_ERROR;
+ goto out;
+ }
+
+ /* Prepare a random pre-key, and from it an ephemeral key */
+ if ((prekey = malloc(SSHKEY_SHIELD_PREKEY_LEN)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ arc4random_buf(prekey, SSHKEY_SHIELD_PREKEY_LEN);
+ if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
+ prekey, SSHKEY_SHIELD_PREKEY_LEN,
+ keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
+ goto out;
+#ifdef DEBUG_PK
+ fprintf(stderr, "%s: key+iv\n", __func__);
+ sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
+ stderr);
+#endif
+ if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
+ keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 1)) != 0)
+ goto out;
+
+ /* Serialise and encrypt the private key using the ephemeral key */
+ if ((prvbuf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (sshkey_is_shielded(k) && (r = sshkey_unshield_private(k)) != 0)
+ goto out;
+ if ((r = sshkey_private_serialize_opt(k, prvbuf,
+ SSHKEY_SERIALIZE_SHIELD)) != 0)
+ goto out;
+ /* pad to cipher blocksize */
+ i = 0;
+ while (sshbuf_len(prvbuf) % cipher_blocksize(cipher)) {
+ if ((r = sshbuf_put_u8(prvbuf, ++i & 0xff)) != 0)
+ goto out;
+ }
+#ifdef DEBUG_PK
+ fprintf(stderr, "%s: serialised\n", __func__);
+ sshbuf_dump(prvbuf, stderr);
+#endif
+ /* encrypt */
+ enclen = sshbuf_len(prvbuf);
+ if ((enc = malloc(enclen)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = cipher_crypt(cctx, 0, enc,
+ sshbuf_ptr(prvbuf), sshbuf_len(prvbuf), 0, 0)) != 0)
+ goto out;
+#ifdef DEBUG_PK
+ fprintf(stderr, "%s: encrypted\n", __func__);
+ sshbuf_dump_data(enc, enclen, stderr);
+#endif
+
+ /* Make a scrubbed, public-only copy of our private key argument */
+ if ((r = sshkey_from_private(k, &kswap)) != 0)
+ goto out;
+
+ /* Swap the private key out (it will be destroyed below) */
+ tmp = *kswap;
+ *kswap = *k;
+ *k = tmp;
+
+ /* Insert the shielded key into our argument */
+ k->shielded_private = enc;
+ k->shielded_len = enclen;
+ k->shield_prekey = prekey;
+ k->shield_prekey_len = SSHKEY_SHIELD_PREKEY_LEN;
+ enc = prekey = NULL; /* transferred */
+ enclen = 0;
+
+ /* preserve key fields that are required for correct operation */
+ k->sk_flags = kswap->sk_flags;
+
+ /* success */
+ r = 0;
+
+ out:
+ /* XXX behaviour on error - invalidate original private key? */
+ cipher_free(cctx);
+ explicit_bzero(keyiv, sizeof(keyiv));
+ explicit_bzero(&tmp, sizeof(tmp));
+ freezero(enc, enclen);
+ freezero(prekey, SSHKEY_SHIELD_PREKEY_LEN);
+ sshkey_free(kswap);
+ sshbuf_free(prvbuf);
+ return r;
+}
+
+int
+sshkey_unshield_private(struct sshkey *k)
+{
+ struct sshbuf *prvbuf = NULL;
+ u_char pad, *cp, keyiv[SSH_DIGEST_MAX_LENGTH];
+ struct sshcipher_ctx *cctx = NULL;
+ const struct sshcipher *cipher;
+ size_t i;
+ struct sshkey *kswap = NULL, tmp;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+#ifdef DEBUG_PK
+ fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
+#endif
+ if (!sshkey_is_shielded(k))
+ return 0; /* nothing to do */
+
+ if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
+ ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
+ r = SSH_ERR_INTERNAL_ERROR;
+ goto out;
+ }
+ /* check size of shielded key blob */
+ if (k->shielded_len < cipher_blocksize(cipher) ||
+ (k->shielded_len % cipher_blocksize(cipher)) != 0) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+
+ /* Calculate the ephemeral key from the prekey */
+ if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
+ k->shield_prekey, k->shield_prekey_len,
+ keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
+ goto out;
+ if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
+ keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 0)) != 0)
+ goto out;
+#ifdef DEBUG_PK
+ fprintf(stderr, "%s: key+iv\n", __func__);
+ sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
+ stderr);
+#endif
+
+ /* Decrypt and parse the shielded private key using the ephemeral key */
+ if ((prvbuf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_reserve(prvbuf, k->shielded_len, &cp)) != 0)
+ goto out;
+ /* decrypt */
+#ifdef DEBUG_PK
+ fprintf(stderr, "%s: encrypted\n", __func__);
+ sshbuf_dump_data(k->shielded_private, k->shielded_len, stderr);
+#endif
+ if ((r = cipher_crypt(cctx, 0, cp,
+ k->shielded_private, k->shielded_len, 0, 0)) != 0)
+ goto out;
+#ifdef DEBUG_PK
+ fprintf(stderr, "%s: serialised\n", __func__);
+ sshbuf_dump(prvbuf, stderr);
+#endif
+ /* Parse private key */
+ if ((r = sshkey_private_deserialize(prvbuf, &kswap)) != 0)
+ goto out;
+ /* Check deterministic padding */
+ i = 0;
+ while (sshbuf_len(prvbuf)) {
+ if ((r = sshbuf_get_u8(prvbuf, &pad)) != 0)
+ goto out;
+ if (pad != (++i & 0xff)) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
}
}
- *pkp = n;
- return 0;
+
+ /* Swap the parsed key back into place */
+ tmp = *kswap;
+ *kswap = *k;
+ *k = tmp;
+
+ /* success */
+ r = 0;
+
+ out:
+ cipher_free(cctx);
+ explicit_bzero(keyiv, sizeof(keyiv));
+ explicit_bzero(&tmp, sizeof(tmp));
+ sshkey_free(kswap);
+ sshbuf_free(prvbuf);
+ return r;
}
static int
@@ -1849,21 +2199,20 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
u_char *sig = NULL;
size_t signed_len = 0, slen = 0, kidlen = 0;
int ret = SSH_ERR_INTERNAL_ERROR;
- int v00 = sshkey_cert_is_legacy(key);
/* Copy the entire key blob for verification and later serialisation */
if ((ret = sshbuf_putb(key->cert->certblob, certbuf)) != 0)
return ret;
- if ((!v00 && (ret = sshbuf_get_u64(b, &key->cert->serial)) != 0) ||
+ /* Parse body of certificate up to signature */
+ if ((ret = sshbuf_get_u64(b, &key->cert->serial)) != 0 ||
(ret = sshbuf_get_u32(b, &key->cert->type)) != 0 ||
(ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 ||
(ret = sshbuf_froms(b, &principals)) != 0 ||
(ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 ||
(ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 ||
(ret = sshbuf_froms(b, &crit)) != 0 ||
- (!v00 && (ret = sshbuf_froms(b, &exts)) != 0) ||
- (v00 && (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0) ||
+ (ret = sshbuf_froms(b, &exts)) != 0 ||
(ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 ||
(ret = sshbuf_froms(b, &ca)) != 0) {
/* XXX debug print error for ret */
@@ -1900,8 +2249,8 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
goto out;
}
oprincipals = key->cert->principals;
- key->cert->principals = realloc(key->cert->principals,
- (key->cert->nprincipals + 1) *
+ key->cert->principals = recallocarray(key->cert->principals,
+ key->cert->nprincipals, key->cert->nprincipals + 1,
sizeof(*key->cert->principals));
if (key->cert->principals == NULL) {
free(principal);
@@ -1923,7 +2272,6 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
/*
* Validate critical options and extensions sections format.
- * NB. extensions are not present in v00 certs.
*/
while (sshbuf_len(crit) != 0) {
if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 ||
@@ -1952,7 +2300,10 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
goto out;
}
if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
- sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0)
+ sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0, NULL)) != 0)
+ goto out;
+ if ((ret = sshkey_get_sigtype(sig, slen,
+ &key->cert->signature_type)) != 0)
goto out;
/* Success */
@@ -1966,24 +2317,42 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
return ret;
}
+#ifdef WITH_OPENSSL
+static int
+check_rsa_length(const RSA *rsa)
+{
+ const BIGNUM *rsa_n;
+
+ RSA_get0_key(rsa, &rsa_n, NULL, NULL);
+ if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
+ return SSH_ERR_KEY_LENGTH;
+ return 0;
+}
+#endif
+
static int
sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
int allow_cert)
{
int type, ret = SSH_ERR_INTERNAL_ERROR;
- char *ktype = NULL, *curve = NULL;
+ char *ktype = NULL, *curve = NULL, *xmss_name = NULL;
struct sshkey *key = NULL;
size_t len;
u_char *pk = NULL;
struct sshbuf *copy;
-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
+#if defined(WITH_OPENSSL)
+ BIGNUM *rsa_n = NULL, *rsa_e = NULL;
+ BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL;
+# if defined(OPENSSL_HAS_ECC)
EC_POINT *q = NULL;
-#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
+# endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
#ifdef DEBUG_PK /* XXX */
sshbuf_dump(b, stderr);
#endif
- *keyp = NULL;
+ if (keyp != NULL)
+ *keyp = NULL;
if ((copy = sshbuf_fromb(b)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
@@ -2008,16 +2377,22 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
}
/* FALLTHROUGH */
case KEY_RSA:
- case KEY_RSA_CERT_V00:
if ((key = sshkey_new(type)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if (sshbuf_get_bignum2(b, key->rsa->e) == -1 ||
- sshbuf_get_bignum2(b, key->rsa->n) == -1) {
+ if (sshbuf_get_bignum2(b, &rsa_e) != 0 ||
+ sshbuf_get_bignum2(b, &rsa_n) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
+ if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ rsa_n = rsa_e = NULL; /* transferred */
+ if ((ret = check_rsa_length(key->rsa)) != 0)
+ goto out;
#ifdef DEBUG_PK
RSA_print_fp(stderr, key->rsa, 8);
#endif
@@ -2030,31 +2405,42 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
}
/* FALLTHROUGH */
case KEY_DSA:
- case KEY_DSA_CERT_V00:
if ((key = sshkey_new(type)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if (sshbuf_get_bignum2(b, key->dsa->p) == -1 ||
- sshbuf_get_bignum2(b, key->dsa->q) == -1 ||
- sshbuf_get_bignum2(b, key->dsa->g) == -1 ||
- sshbuf_get_bignum2(b, key->dsa->pub_key) == -1) {
+ if (sshbuf_get_bignum2(b, &dsa_p) != 0 ||
+ sshbuf_get_bignum2(b, &dsa_q) != 0 ||
+ sshbuf_get_bignum2(b, &dsa_g) != 0 ||
+ sshbuf_get_bignum2(b, &dsa_pub_key) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
+ if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ dsa_p = dsa_q = dsa_g = NULL; /* transferred */
+ if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ dsa_pub_key = NULL; /* transferred */
#ifdef DEBUG_PK
DSA_print_fp(stderr, key->dsa, 8);
#endif
break;
+# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA_CERT:
+ case KEY_ECDSA_SK_CERT:
/* Skip nonce */
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* FALLTHROUGH */
-# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
+ case KEY_ECDSA_SK:
if ((key = sshkey_new(type)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
@@ -2068,8 +2454,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
ret = SSH_ERR_EC_CURVE_MISMATCH;
goto out;
}
- if (key->ecdsa != NULL)
- EC_KEY_free(key->ecdsa);
+ EC_KEY_free(key->ecdsa);
if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
== NULL) {
ret = SSH_ERR_EC_CURVE_INVALID;
@@ -2096,10 +2481,22 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
#ifdef DEBUG_PK
sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
#endif
+ if (type == KEY_ECDSA_SK || type == KEY_ECDSA_SK_CERT) {
+ /* Parse additional security-key application string */
+ if (sshbuf_get_cstring(b, &key->sk_application,
+ NULL) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+#ifdef DEBUG_PK
+ fprintf(stderr, "App: %s\n", key->sk_application);
+#endif
+ }
break;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
case KEY_ED25519_CERT:
+ case KEY_ED25519_SK_CERT:
/* Skip nonce */
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
@@ -2107,6 +2504,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
}
/* FALLTHROUGH */
case KEY_ED25519:
+ case KEY_ED25519_SK:
if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
goto out;
if (len != ED25519_PK_SZ) {
@@ -2117,15 +2515,51 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
+ if (type == KEY_ED25519_SK || type == KEY_ED25519_SK_CERT) {
+ /* Parse additional security-key application string */
+ if (sshbuf_get_cstring(b, &key->sk_application,
+ NULL) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+#ifdef DEBUG_PK
+ fprintf(stderr, "App: %s\n", key->sk_application);
+#endif
+ }
key->ed25519_pk = pk;
pk = NULL;
break;
- case KEY_UNSPEC:
+#ifdef WITH_XMSS
+ case KEY_XMSS_CERT:
+ /* Skip nonce */
+ if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ /* FALLTHROUGH */
+ case KEY_XMSS:
+ if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
+ goto out;
if ((key = sshkey_new(type)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
+ if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
+ goto out;
+ if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
+ goto out;
+ if (len == 0 || len != sshkey_xmss_pklen(key)) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ key->xmss_pk = pk;
+ pk = NULL;
+ if (type != KEY_XMSS_CERT &&
+ (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
+ goto out;
break;
+#endif /* WITH_XMSS */
+ case KEY_UNSPEC:
default:
ret = SSH_ERR_KEY_TYPE_UNKNOWN;
goto out;
@@ -2140,18 +2574,28 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
goto out;
}
ret = 0;
- *keyp = key;
- key = NULL;
+ if (keyp != NULL) {
+ *keyp = key;
+ key = NULL;
+ }
out:
sshbuf_free(copy);
sshkey_free(key);
+ free(xmss_name);
free(ktype);
free(curve);
free(pk);
-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
- if (q != NULL)
- EC_POINT_free(q);
-#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
+#if defined(WITH_OPENSSL)
+ BN_clear_free(rsa_n);
+ BN_clear_free(rsa_e);
+ BN_clear_free(dsa_p);
+ BN_clear_free(dsa_q);
+ BN_clear_free(dsa_g);
+ BN_clear_free(dsa_pub_key);
+# if defined(OPENSSL_HAS_ECC)
+ EC_POINT_free(q);
+# endif /* OPENSSL_HAS_ECC */
+#endif /* WITH_OPENSSL */
return ret;
}
@@ -2188,53 +2632,171 @@ sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
}
int
-sshkey_sign(const struct sshkey *key,
+sshkey_get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
+{
+ int r;
+ struct sshbuf *b = NULL;
+ char *sigtype = NULL;
+
+ if (sigtypep != NULL)
+ *sigtypep = NULL;
+ if ((b = sshbuf_from(sig, siglen)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((r = sshbuf_get_cstring(b, &sigtype, NULL)) != 0)
+ goto out;
+ /* success */
+ if (sigtypep != NULL) {
+ *sigtypep = sigtype;
+ sigtype = NULL;
+ }
+ r = 0;
+ out:
+ free(sigtype);
+ sshbuf_free(b);
+ return r;
+}
+
+/*
+ *
+ * Checks whether a certificate's signature type is allowed.
+ * Returns 0 (success) if the certificate signature type appears in the
+ * "allowed" pattern-list, or the key is not a certificate to begin with.
+ * Otherwise returns a ssherr.h code.
+ */
+int
+sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed)
+{
+ if (key == NULL || allowed == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (!sshkey_type_is_cert(key->type))
+ return 0;
+ if (key->cert == NULL || key->cert->signature_type == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1)
+ return SSH_ERR_SIGN_ALG_UNSUPPORTED;
+ return 0;
+}
+
+/*
+ * Returns the expected signature algorithm for a given public key algorithm.
+ */
+const char *
+sshkey_sigalg_by_name(const char *name)
+{
+ const struct keytype *kt;
+
+ for (kt = keytypes; kt->type != -1; kt++) {
+ if (strcmp(kt->name, name) != 0)
+ continue;
+ if (kt->sigalg != NULL)
+ return kt->sigalg;
+ if (!kt->cert)
+ return kt->name;
+ return sshkey_ssh_name_from_type_nid(
+ sshkey_type_plain(kt->type), kt->nid);
+ }
+ return NULL;
+}
+
+/*
+ * Verifies that the signature algorithm appearing inside the signature blob
+ * matches that which was requested.
+ */
+int
+sshkey_check_sigtype(const u_char *sig, size_t siglen,
+ const char *requested_alg)
+{
+ const char *expected_alg;
+ char *sigtype = NULL;
+ int r;
+
+ if (requested_alg == NULL)
+ return 0;
+ if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0)
+ return r;
+ r = strcmp(expected_alg, sigtype) == 0;
+ free(sigtype);
+ return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED;
+}
+
+int
+sshkey_sign(struct sshkey *key,
u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, u_int compat)
+ const u_char *data, size_t datalen,
+ const char *alg, const char *sk_provider, u_int compat)
{
+ int was_shielded = sshkey_is_shielded(key);
+ int r2, r = SSH_ERR_INTERNAL_ERROR;
+
if (sigp != NULL)
*sigp = NULL;
if (lenp != NULL)
*lenp = 0;
if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
return SSH_ERR_INVALID_ARGUMENT;
+ if ((r = sshkey_unshield_private(key)) != 0)
+ return r;
switch (key->type) {
#ifdef WITH_OPENSSL
- case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
case KEY_DSA:
- return ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
+ r = ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
+ break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA_CERT:
case KEY_ECDSA:
- return ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
+ r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
+ break;
# endif /* OPENSSL_HAS_ECC */
- case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
case KEY_RSA:
- return ssh_rsa_sign(key, sigp, lenp, data, datalen, compat);
+ r = ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
+ break;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
- return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
+ r = ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
+ break;
+ case KEY_ED25519_SK:
+ case KEY_ED25519_SK_CERT:
+ case KEY_ECDSA_SK_CERT:
+ case KEY_ECDSA_SK:
+ r = sshsk_sign(sk_provider, key, sigp, lenp, data,
+ datalen, compat, /* XXX PIN */ NULL);
+ break;
+#ifdef WITH_XMSS
+ case KEY_XMSS:
+ case KEY_XMSS_CERT:
+ r = ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
+ break;
+#endif /* WITH_XMSS */
default:
- return SSH_ERR_KEY_TYPE_UNKNOWN;
+ r = SSH_ERR_KEY_TYPE_UNKNOWN;
+ break;
}
+ if (was_shielded && (r2 = sshkey_shield_private(key)) != 0)
+ return r2;
+ return r;
}
/*
* ssh_key_verify returns 0 for a correct signature and < 0 on error.
+ * If "alg" specified, then the signature must use that algorithm.
*/
int
sshkey_verify(const struct sshkey *key,
const u_char *sig, size_t siglen,
- const u_char *data, size_t dlen, u_int compat)
+ const u_char *data, size_t dlen, const char *alg, u_int compat,
+ struct sshkey_sig_details **detailsp)
{
+ if (detailsp != NULL)
+ *detailsp = NULL;
if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
return SSH_ERR_INVALID_ARGUMENT;
switch (key->type) {
#ifdef WITH_OPENSSL
- case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
case KEY_DSA:
return ssh_dss_verify(key, sig, siglen, data, dlen, compat);
@@ -2242,139 +2804,64 @@ sshkey_verify(const struct sshkey *key,
case KEY_ECDSA_CERT:
case KEY_ECDSA:
return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat);
+ case KEY_ECDSA_SK_CERT:
+ case KEY_ECDSA_SK:
+ return ssh_ecdsa_sk_verify(key, sig, siglen, data, dlen,
+ compat, detailsp);
# endif /* OPENSSL_HAS_ECC */
- case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
case KEY_RSA:
- return ssh_rsa_verify(key, sig, siglen, data, dlen, compat);
+ return ssh_rsa_verify(key, sig, siglen, data, dlen, alg);
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
+ case KEY_ED25519_SK:
+ case KEY_ED25519_SK_CERT:
+ return ssh_ed25519_sk_verify(key, sig, siglen, data, dlen,
+ compat, detailsp);
+#ifdef WITH_XMSS
+ case KEY_XMSS:
+ case KEY_XMSS_CERT:
+ return ssh_xmss_verify(key, sig, siglen, data, dlen, compat);
+#endif /* WITH_XMSS */
default:
return SSH_ERR_KEY_TYPE_UNKNOWN;
}
}
-/* Converts a private to a public key */
-int
-sshkey_demote(const struct sshkey *k, struct sshkey **dkp)
-{
- struct sshkey *pk;
- int ret = SSH_ERR_INTERNAL_ERROR;
-
- if (dkp != NULL)
- *dkp = NULL;
-
- if ((pk = calloc(1, sizeof(*pk))) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- pk->type = k->type;
- pk->flags = k->flags;
- pk->ecdsa_nid = k->ecdsa_nid;
- pk->dsa = NULL;
- pk->ecdsa = NULL;
- pk->rsa = NULL;
- pk->ed25519_pk = NULL;
- pk->ed25519_sk = NULL;
-
- switch (k->type) {
-#ifdef WITH_OPENSSL
- case KEY_RSA_CERT_V00:
- case KEY_RSA_CERT:
- if ((ret = sshkey_cert_copy(k, pk)) != 0)
- goto fail;
- /* FALLTHROUGH */
- case KEY_RSA1:
- case KEY_RSA:
- if ((pk->rsa = RSA_new()) == NULL ||
- (pk->rsa->e = BN_dup(k->rsa->e)) == NULL ||
- (pk->rsa->n = BN_dup(k->rsa->n)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto fail;
- }
- break;
- case KEY_DSA_CERT_V00:
- case KEY_DSA_CERT:
- if ((ret = sshkey_cert_copy(k, pk)) != 0)
- goto fail;
- /* FALLTHROUGH */
- case KEY_DSA:
- if ((pk->dsa = DSA_new()) == NULL ||
- (pk->dsa->p = BN_dup(k->dsa->p)) == NULL ||
- (pk->dsa->q = BN_dup(k->dsa->q)) == NULL ||
- (pk->dsa->g = BN_dup(k->dsa->g)) == NULL ||
- (pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto fail;
- }
- break;
- case KEY_ECDSA_CERT:
- if ((ret = sshkey_cert_copy(k, pk)) != 0)
- goto fail;
- /* FALLTHROUGH */
-# ifdef OPENSSL_HAS_ECC
- case KEY_ECDSA:
- pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid);
- if (pk->ecdsa == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto fail;
- }
- if (EC_KEY_set_public_key(pk->ecdsa,
- EC_KEY_get0_public_key(k->ecdsa)) != 1) {
- ret = SSH_ERR_LIBCRYPTO_ERROR;
- goto fail;
- }
- break;
-# endif /* OPENSSL_HAS_ECC */
-#endif /* WITH_OPENSSL */
- case KEY_ED25519_CERT:
- if ((ret = sshkey_cert_copy(k, pk)) != 0)
- goto fail;
- /* FALLTHROUGH */
- case KEY_ED25519:
- if (k->ed25519_pk != NULL) {
- if ((pk->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto fail;
- }
- memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
- }
- break;
- default:
- ret = SSH_ERR_KEY_TYPE_UNKNOWN;
- fail:
- sshkey_free(pk);
- return ret;
- }
- *dkp = pk;
- return 0;
-}
-
/* Convert a plain key to their _CERT equivalent */
int
-sshkey_to_certified(struct sshkey *k, int legacy)
+sshkey_to_certified(struct sshkey *k)
{
int newtype;
switch (k->type) {
#ifdef WITH_OPENSSL
case KEY_RSA:
- newtype = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT;
+ newtype = KEY_RSA_CERT;
break;
case KEY_DSA:
- newtype = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;
+ newtype = KEY_DSA_CERT;
break;
case KEY_ECDSA:
- if (legacy)
- return SSH_ERR_INVALID_ARGUMENT;
newtype = KEY_ECDSA_CERT;
break;
+ case KEY_ECDSA_SK:
+ newtype = KEY_ECDSA_SK_CERT;
+ break;
#endif /* WITH_OPENSSL */
+ case KEY_ED25519_SK:
+ newtype = KEY_ED25519_SK_CERT;
+ break;
case KEY_ED25519:
- if (legacy)
- return SSH_ERR_INVALID_ARGUMENT;
newtype = KEY_ED25519_CERT;
break;
+#ifdef WITH_XMSS
+ case KEY_XMSS:
+ newtype = KEY_XMSS_CERT;
+ break;
+#endif /* WITH_XMSS */
default:
return SSH_ERR_INVALID_ARGUMENT;
}
@@ -2398,13 +2885,18 @@ sshkey_drop_cert(struct sshkey *k)
/* Sign a certified key, (re-)generating the signed certblob. */
int
-sshkey_certify(struct sshkey *k, struct sshkey *ca)
+sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
+ const char *sk_provider, sshkey_certify_signer *signer, void *signer_ctx)
{
struct sshbuf *principals = NULL;
u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
size_t i, ca_len, sig_len;
int ret = SSH_ERR_INTERNAL_ERROR;
- struct sshbuf *cert;
+ struct sshbuf *cert = NULL;
+ char *sigtype = NULL;
+#ifdef WITH_OPENSSL
+ const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
+#endif /* WITH_OPENSSL */
if (k == NULL || k->cert == NULL ||
k->cert->certblob == NULL || ca == NULL)
@@ -2414,6 +2906,23 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca)
if (!sshkey_type_is_valid_ca(ca->type))
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
+ /*
+ * If no alg specified as argument but a signature_type was set,
+ * then prefer that. If both were specified, then they must match.
+ */
+ if (alg == NULL)
+ alg = k->cert->signature_type;
+ else if (k->cert->signature_type != NULL &&
+ strcmp(alg, k->cert->signature_type) != 0)
+ return SSH_ERR_INVALID_ARGUMENT;
+
+ /*
+ * If no signing algorithm or signature_type was specified and we're
+ * using a RSA key, then default to a good signature algorithm.
+ */
+ if (alg == NULL && ca->type == KEY_RSA)
+ alg = "rsa-sha2-512";
+
if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
@@ -2424,56 +2933,74 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca)
/* -v01 certs put nonce first */
arc4random_buf(&nonce, sizeof(nonce));
- if (!sshkey_cert_is_legacy(k)) {
- if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
- goto out;
- }
+ if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
+ goto out;
/* XXX this substantially duplicates to_blob(); refactor */
switch (k->type) {
#ifdef WITH_OPENSSL
- case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
- if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 ||
- (ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 ||
- (ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 ||
- (ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0)
+ DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g);
+ DSA_get0_key(k->dsa, &dsa_pub_key, NULL);
+ if ((ret = sshbuf_put_bignum2(cert, dsa_p)) != 0 ||
+ (ret = sshbuf_put_bignum2(cert, dsa_q)) != 0 ||
+ (ret = sshbuf_put_bignum2(cert, dsa_g)) != 0 ||
+ (ret = sshbuf_put_bignum2(cert, dsa_pub_key)) != 0)
goto out;
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA_CERT:
+ case KEY_ECDSA_SK_CERT:
if ((ret = sshbuf_put_cstring(cert,
sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 ||
(ret = sshbuf_put_ec(cert,
EC_KEY_get0_public_key(k->ecdsa),
EC_KEY_get0_group(k->ecdsa))) != 0)
goto out;
+ if (k->type == KEY_ECDSA_SK_CERT) {
+ if ((ret = sshbuf_put_cstring(cert,
+ k->sk_application)) != 0)
+ goto out;
+ }
break;
# endif /* OPENSSL_HAS_ECC */
- case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
- if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 ||
- (ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0)
+ RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL);
+ if ((ret = sshbuf_put_bignum2(cert, rsa_e)) != 0 ||
+ (ret = sshbuf_put_bignum2(cert, rsa_n)) != 0)
goto out;
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519_CERT:
+ case KEY_ED25519_SK_CERT:
if ((ret = sshbuf_put_string(cert,
k->ed25519_pk, ED25519_PK_SZ)) != 0)
goto out;
+ if (k->type == KEY_ED25519_SK_CERT) {
+ if ((ret = sshbuf_put_cstring(cert,
+ k->sk_application)) != 0)
+ goto out;
+ }
+ break;
+#ifdef WITH_XMSS
+ case KEY_XMSS_CERT:
+ if (k->xmss_name == NULL) {
+ ret = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if ((ret = sshbuf_put_cstring(cert, k->xmss_name)) ||
+ (ret = sshbuf_put_string(cert,
+ k->xmss_pk, sshkey_xmss_pklen(k))) != 0)
+ goto out;
break;
+#endif /* WITH_XMSS */
default:
ret = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
- /* -v01 certs have a serial number next */
- if (!sshkey_cert_is_legacy(k)) {
- if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0)
- goto out;
- }
-
- if ((ret = sshbuf_put_u32(cert, k->cert->type)) != 0 ||
+ if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 ||
+ (ret = sshbuf_put_u32(cert, k->cert->type)) != 0 ||
(ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0)
goto out;
@@ -2489,30 +3016,27 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca)
if ((ret = sshbuf_put_stringb(cert, principals)) != 0 ||
(ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 ||
(ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 ||
- (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0)
- goto out;
-
- /* -v01 certs have non-critical options here */
- if (!sshkey_cert_is_legacy(k)) {
- if ((ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0)
- goto out;
- }
-
- /* -v00 certs put the nonce at the end */
- if (sshkey_cert_is_legacy(k)) {
- if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
- goto out;
- }
-
- if ((ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */
+ (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0 ||
+ (ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0 ||
+ (ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */
(ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0)
goto out;
/* Sign the whole mess */
- if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
- sshbuf_len(cert), 0)) != 0)
+ if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
+ sshbuf_len(cert), alg, sk_provider, 0, signer_ctx)) != 0)
goto out;
-
+ /* Check and update signature_type against what was actually used */
+ if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
+ goto out;
+ if (alg != NULL && strcmp(alg, sigtype) != 0) {
+ ret = SSH_ERR_SIGN_ALG_UNSUPPORTED;
+ goto out;
+ }
+ if (k->cert->signature_type == NULL) {
+ k->cert->signature_type = sigtype;
+ sigtype = NULL;
+ }
/* Append signature and we are done */
if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
goto out;
@@ -2520,15 +3044,32 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca)
out:
if (ret != 0)
sshbuf_reset(cert);
- if (sig_blob != NULL)
- free(sig_blob);
- if (ca_blob != NULL)
- free(ca_blob);
- if (principals != NULL)
- sshbuf_free(principals);
+ free(sig_blob);
+ free(ca_blob);
+ free(sigtype);
+ sshbuf_free(principals);
return ret;
}
+static int
+default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp,
+ const u_char *data, size_t datalen,
+ const char *alg, const char *sk_provider, 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);
+}
+
+int
+sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg,
+ const char *sk_provider)
+{
+ return sshkey_certify_custom(k, ca, alg, sk_provider,
+ default_key_sign, NULL);
+}
+
int
sshkey_cert_check_authority(const struct sshkey *k,
int want_host, int require_principal,
@@ -2537,8 +3078,8 @@ sshkey_cert_check_authority(const struct sshkey *k,
u_int i, principal_matches;
time_t now = time(NULL);
- if (reason != NULL)
- *reason = NULL;
+ if (reason == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
if (want_host) {
if (k->cert->type != SSH2_CERT_TYPE_HOST) {
@@ -2586,53 +3127,108 @@ sshkey_cert_check_authority(const struct sshkey *k,
return 0;
}
+size_t
+sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
+{
+ char from[32], to[32], ret[64];
+ time_t tt;
+ struct tm *tm;
+
+ *from = *to = '\0';
+ if (cert->valid_after == 0 &&
+ cert->valid_before == 0xffffffffffffffffULL)
+ return strlcpy(s, "forever", l);
+
+ if (cert->valid_after != 0) {
+ /* XXX revisit INT_MAX in 2038 :) */
+ tt = cert->valid_after > INT_MAX ?
+ INT_MAX : cert->valid_after;
+ tm = localtime(&tt);
+ strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
+ }
+ if (cert->valid_before != 0xffffffffffffffffULL) {
+ /* XXX revisit INT_MAX in 2038 :) */
+ tt = cert->valid_before > INT_MAX ?
+ INT_MAX : cert->valid_before;
+ tm = localtime(&tt);
+ strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
+ }
+
+ if (cert->valid_after == 0)
+ snprintf(ret, sizeof(ret), "before %s", to);
+ else if (cert->valid_before == 0xffffffffffffffffULL)
+ snprintf(ret, sizeof(ret), "after %s", from);
+ else
+ snprintf(ret, sizeof(ret), "from %s to %s", from, to);
+
+ return strlcpy(s, ret, l);
+}
+
int
-sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
+sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
+ enum sshkey_serialize_rep opts)
{
int r = SSH_ERR_INTERNAL_ERROR;
+ int was_shielded = sshkey_is_shielded(key);
+ struct sshbuf *b = NULL;
+#ifdef WITH_OPENSSL
+ const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
+ const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dsa_priv_key;
+#endif /* WITH_OPENSSL */
+ if ((r = sshkey_unshield_private(key)) != 0)
+ return r;
+ if ((b = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
goto out;
switch (key->type) {
#ifdef WITH_OPENSSL
case KEY_RSA:
- if ((r = sshbuf_put_bignum2(b, key->rsa->n)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->rsa->e)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0)
+ RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d);
+ RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
+ RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
+ if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 ||
+ (r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
+ (r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
+ (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
+ (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
+ (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
goto out;
break;
- case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
+ RSA_get0_key(key->rsa, NULL, NULL, &rsa_d);
+ RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
+ RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0)
+ (r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
+ (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
+ (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
+ (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
goto out;
break;
case KEY_DSA:
- if ((r = sshbuf_put_bignum2(b, key->dsa->p)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->dsa->g)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0)
+ DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
+ DSA_get0_key(key->dsa, &dsa_pub_key, &dsa_priv_key);
+ if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
+ (r = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
+ (r = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
+ (r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0 ||
+ (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
goto out;
break;
- case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
+ DSA_get0_key(key->dsa, NULL, &dsa_priv_key);
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
- (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0)
+ (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
goto out;
break;
# ifdef OPENSSL_HAS_ECC
@@ -2654,6 +3250,28 @@ sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
EC_KEY_get0_private_key(key->ecdsa))) != 0)
goto out;
break;
+ case KEY_ECDSA_SK:
+ if ((r = sshbuf_put_cstring(b,
+ sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
+ (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
+ (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
+ (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
+ (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
+ (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
+ goto out;
+ break;
+ case KEY_ECDSA_SK_CERT:
+ if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
+ (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
+ (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
+ (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
+ (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
+ goto out;
+ break;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
case KEY_ED25519:
@@ -2675,26 +3293,100 @@ sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
ED25519_SK_SZ)) != 0)
goto out;
break;
+ case KEY_ED25519_SK:
+ if ((r = sshbuf_put_string(b, key->ed25519_pk,
+ ED25519_PK_SZ)) != 0 ||
+ (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
+ (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
+ (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
+ (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
+ goto out;
+ break;
+ case KEY_ED25519_SK_CERT:
+ if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
+ (r = sshbuf_put_string(b, key->ed25519_pk,
+ ED25519_PK_SZ)) != 0 ||
+ (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
+ (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
+ (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
+ (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
+ goto out;
+ break;
+#ifdef WITH_XMSS
+ case KEY_XMSS:
+ if (key->xmss_name == NULL) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
+ (r = sshbuf_put_string(b, key->xmss_pk,
+ sshkey_xmss_pklen(key))) != 0 ||
+ (r = sshbuf_put_string(b, key->xmss_sk,
+ sshkey_xmss_sklen(key))) != 0 ||
+ (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
+ goto out;
+ break;
+ case KEY_XMSS_CERT:
+ if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0 ||
+ key->xmss_name == NULL) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
+ (r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
+ (r = sshbuf_put_string(b, key->xmss_pk,
+ sshkey_xmss_pklen(key))) != 0 ||
+ (r = sshbuf_put_string(b, key->xmss_sk,
+ sshkey_xmss_sklen(key))) != 0 ||
+ (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
+ goto out;
+ break;
+#endif /* WITH_XMSS */
default:
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
- /* success */
+ /*
+ * success (but we still need to append the output to buf after
+ * possibly re-shielding the private key)
+ */
r = 0;
out:
+ if (was_shielded)
+ r = sshkey_shield_private(key);
+ if (r == 0)
+ r = sshbuf_putb(buf, b);
+ sshbuf_free(b);
+
return r;
}
int
+sshkey_private_serialize(struct sshkey *key, struct sshbuf *b)
+{
+ return sshkey_private_serialize_opt(key, b,
+ SSHKEY_SERIALIZE_DEFAULT);
+}
+
+int
sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
{
- char *tname = NULL, *curve = NULL;
+ char *tname = NULL, *curve = NULL, *xmss_name = NULL;
struct sshkey *k = NULL;
size_t pklen = 0, sklen = 0;
int type, r = SSH_ERR_INTERNAL_ERROR;
u_char *ed25519_pk = NULL, *ed25519_sk = NULL;
+ u_char *xmss_pk = NULL, *xmss_sk = NULL;
#ifdef WITH_OPENSSL
BIGNUM *exponent = NULL;
+ BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
+ BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL;
+ BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
+ BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL;
#endif /* WITH_OPENSSL */
if (kp != NULL)
@@ -2702,33 +3394,60 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0)
goto out;
type = sshkey_type_from_name(tname);
+ if (sshkey_type_is_cert(type)) {
+ /*
+ * Certificate key private keys begin with the certificate
+ * itself. Make sure this matches the type of the enclosing
+ * private key.
+ */
+ if ((r = sshkey_froms(buf, &k)) != 0)
+ goto out;
+ if (k->type != type) {
+ r = SSH_ERR_KEY_CERT_MISMATCH;
+ goto out;
+ }
+ /* For ECDSA keys, the group must match too */
+ if (k->type == KEY_ECDSA &&
+ k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) {
+ r = SSH_ERR_KEY_CERT_MISMATCH;
+ goto out;
+ }
+ } else {
+ if ((k = sshkey_new(type)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ }
switch (type) {
#ifdef WITH_OPENSSL
case KEY_DSA:
- if ((k = sshkey_new_private(type)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
+ if ((r = sshbuf_get_bignum2(buf, &dsa_p)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &dsa_q)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &dsa_g)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &dsa_pub_key)) != 0)
+ goto out;
+ if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
- if ((r = sshbuf_get_bignum2(buf, k->dsa->p)) != 0 ||
- (r = sshbuf_get_bignum2(buf, k->dsa->q)) != 0 ||
- (r = sshbuf_get_bignum2(buf, k->dsa->g)) != 0 ||
- (r = sshbuf_get_bignum2(buf, k->dsa->pub_key)) != 0 ||
- (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0)
+ dsa_p = dsa_q = dsa_g = NULL; /* transferred */
+ if (!DSA_set0_key(k->dsa, dsa_pub_key, NULL)) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
- break;
- case KEY_DSA_CERT_V00:
+ }
+ dsa_pub_key = NULL; /* transferred */
+ /* FALLTHROUGH */
case KEY_DSA_CERT:
- if ((r = sshkey_froms(buf, &k)) != 0 ||
- (r = sshkey_add_private(k)) != 0 ||
- (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0)
+ if ((r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
+ goto out;
+ if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
+ }
+ dsa_priv_key = NULL; /* transferred */
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
- if ((k = sshkey_new_private(type)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
@@ -2740,72 +3459,108 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
goto out;
}
k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
- if (k->ecdsa == NULL || (exponent = BN_new()) == NULL) {
+ if (k->ecdsa == NULL) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
- if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 ||
- (r = sshbuf_get_bignum2(buf, exponent)))
+ if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0)
+ goto out;
+ /* FALLTHROUGH */
+ case KEY_ECDSA_CERT:
+ if ((r = sshbuf_get_bignum2(buf, &exponent)) != 0)
goto out;
if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
- EC_KEY_get0_public_key(k->ecdsa)) != 0) ||
+ EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
(r = sshkey_ec_validate_private(k->ecdsa)) != 0)
goto out;
break;
- case KEY_ECDSA_CERT:
- if ((exponent = BN_new()) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
+ case KEY_ECDSA_SK:
+ if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
+ r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
- if ((r = sshkey_froms(buf, &k)) != 0 ||
- (r = sshkey_add_private(k)) != 0 ||
- (r = sshbuf_get_bignum2(buf, exponent)) != 0)
+ if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0)
goto out;
- if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
+ if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
+ r = SSH_ERR_EC_CURVE_MISMATCH;
+ goto out;
+ }
+ if ((k->sk_key_handle = sshbuf_new()) == NULL ||
+ (k->sk_reserved = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
+ if (k->ecdsa == NULL) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
+ if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 ||
+ (r = sshbuf_get_cstring(buf, &k->sk_application,
+ NULL)) != 0 ||
+ (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
+ (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
+ (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
+ goto out;
if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
- EC_KEY_get0_public_key(k->ecdsa)) != 0) ||
- (r = sshkey_ec_validate_private(k->ecdsa)) != 0)
+ EC_KEY_get0_public_key(k->ecdsa))) != 0)
goto out;
break;
-# endif /* OPENSSL_HAS_ECC */
- case KEY_RSA:
- if ((k = sshkey_new_private(type)) == NULL) {
+ case KEY_ECDSA_SK_CERT:
+ if ((k->sk_key_handle = sshbuf_new()) == NULL ||
+ (k->sk_reserved = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((r = sshbuf_get_bignum2(buf, k->rsa->n)) != 0 ||
- (r = sshbuf_get_bignum2(buf, k->rsa->e)) != 0 ||
- (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 ||
- (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
- (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
- (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
- (r = rsa_generate_additional_parameters(k->rsa)) != 0)
+ if ((r = sshbuf_get_cstring(buf, &k->sk_application,
+ NULL)) != 0 ||
+ (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
+ (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
+ (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
+ goto out;
+ if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
+ EC_KEY_get0_public_key(k->ecdsa))) != 0)
goto out;
break;
- case KEY_RSA_CERT_V00:
+# endif /* OPENSSL_HAS_ECC */
+ case KEY_RSA:
+ if ((r = sshbuf_get_bignum2(buf, &rsa_n)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &rsa_e)) != 0)
+ goto out;
+ if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, NULL)) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ rsa_n = rsa_e = NULL; /* transferred */
+ /* FALLTHROUGH */
case KEY_RSA_CERT:
- if ((r = sshkey_froms(buf, &k)) != 0 ||
- (r = sshkey_add_private(k)) != 0 ||
- (r = sshbuf_get_bignum2(buf, k->rsa->d) != 0) ||
- (r = sshbuf_get_bignum2(buf, k->rsa->iqmp) != 0) ||
- (r = sshbuf_get_bignum2(buf, k->rsa->p) != 0) ||
- (r = sshbuf_get_bignum2(buf, k->rsa->q) != 0) ||
- (r = rsa_generate_additional_parameters(k->rsa)) != 0)
+ if ((r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0)
+ goto out;
+ if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ rsa_d = NULL; /* transferred */
+ if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ rsa_p = rsa_q = NULL; /* transferred */
+ if ((r = check_rsa_length(k->rsa)) != 0)
+ goto out;
+ if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
goto out;
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
- if ((k = sshkey_new_private(type)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
+ case KEY_ED25519_CERT:
if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
(r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
goto out;
@@ -2815,22 +3570,51 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
}
k->ed25519_pk = ed25519_pk;
k->ed25519_sk = ed25519_sk;
- ed25519_pk = ed25519_sk = NULL;
+ ed25519_pk = ed25519_sk = NULL; /* transferred */
break;
- case KEY_ED25519_CERT:
- if ((r = sshkey_froms(buf, &k)) != 0 ||
- (r = sshkey_add_private(k)) != 0 ||
- (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
- (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
+ case KEY_ED25519_SK:
+ case KEY_ED25519_SK_CERT:
+ if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0)
goto out;
- if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
+ if (pklen != ED25519_PK_SZ) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
+ if ((k->sk_key_handle = sshbuf_new()) == NULL ||
+ (k->sk_reserved = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_get_cstring(buf, &k->sk_application,
+ NULL)) != 0 ||
+ (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
+ (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
+ (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
+ goto out;
k->ed25519_pk = ed25519_pk;
- k->ed25519_sk = ed25519_sk;
- ed25519_pk = ed25519_sk = NULL;
+ ed25519_pk = NULL; /* transferred */
+ break;
+#ifdef WITH_XMSS
+ 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 (pklen != sshkey_xmss_pklen(k) ||
+ sklen != sshkey_xmss_sklen(k)) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ k->xmss_pk = xmss_pk;
+ k->xmss_sk = xmss_sk;
+ xmss_pk = xmss_sk = NULL;
+ /* optional internal state */
+ if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
+ goto out;
break;
+#endif /* WITH_XMSS */
default:
r = SSH_ERR_KEY_TYPE_UNKNOWN;
goto out;
@@ -2839,9 +3623,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
/* enable blinding */
switch (k->type) {
case KEY_RSA:
- case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
- case KEY_RSA1:
if (RSA_blinding_on(k->rsa, NULL) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
@@ -2859,18 +3641,25 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
free(tname);
free(curve);
#ifdef WITH_OPENSSL
- if (exponent != NULL)
- BN_clear_free(exponent);
+ BN_clear_free(exponent);
+ BN_clear_free(dsa_p);
+ BN_clear_free(dsa_q);
+ BN_clear_free(dsa_g);
+ BN_clear_free(dsa_pub_key);
+ BN_clear_free(dsa_priv_key);
+ BN_clear_free(rsa_n);
+ BN_clear_free(rsa_e);
+ BN_clear_free(rsa_d);
+ BN_clear_free(rsa_p);
+ BN_clear_free(rsa_q);
+ BN_clear_free(rsa_iqmp);
#endif /* WITH_OPENSSL */
sshkey_free(k);
- if (ed25519_pk != NULL) {
- explicit_bzero(ed25519_pk, pklen);
- free(ed25519_pk);
- }
- if (ed25519_sk != NULL) {
- explicit_bzero(ed25519_sk, sklen);
- free(ed25519_sk);
- }
+ freezero(ed25519_pk, pklen);
+ freezero(ed25519_sk, sklen);
+ free(xmss_name);
+ freezero(xmss_pk, pklen);
+ freezero(xmss_sk, sklen);
return r;
}
@@ -2878,14 +3667,17 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
int
sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
{
- BN_CTX *bnctx;
EC_POINT *nq = NULL;
- BIGNUM *order, *x, *y, *tmp;
+ BIGNUM *order = NULL, *x = NULL, *y = NULL, *tmp = NULL;
int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
- if ((bnctx = BN_CTX_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- BN_CTX_start(bnctx);
+ /*
+ * NB. This assumes OpenSSL has already verified that the public
+ * point lies on the curve. This is done by EC_POINT_oct2point()
+ * implicitly calling EC_POINT_is_on_curve(). If this code is ever
+ * reachable with public points not unmarshalled using
+ * EC_POINT_oct2point then the caller will need to explicitly check.
+ */
/*
* We shouldn't ever hit this case because bignum_get_ecpoint()
@@ -2899,18 +3691,18 @@ sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
if (EC_POINT_is_at_infinity(group, public))
goto out;
- if ((x = BN_CTX_get(bnctx)) == NULL ||
- (y = BN_CTX_get(bnctx)) == NULL ||
- (order = BN_CTX_get(bnctx)) == NULL ||
- (tmp = BN_CTX_get(bnctx)) == NULL) {
+ if ((x = BN_new()) == NULL ||
+ (y = BN_new()) == NULL ||
+ (order = BN_new()) == NULL ||
+ (tmp = BN_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
/* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
- if (EC_GROUP_get_order(group, order, bnctx) != 1 ||
+ if (EC_GROUP_get_order(group, order, NULL) != 1 ||
EC_POINT_get_affine_coordinates_GFp(group, public,
- x, y, bnctx) != 1) {
+ x, y, NULL) != 1) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
@@ -2923,7 +3715,7 @@ sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) {
+ if (EC_POINT_mul(group, nq, NULL, public, order, NULL) != 1) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
@@ -2939,31 +3731,27 @@ sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
goto out;
ret = 0;
out:
- BN_CTX_free(bnctx);
- if (nq != NULL)
- EC_POINT_free(nq);
+ BN_clear_free(x);
+ BN_clear_free(y);
+ BN_clear_free(order);
+ BN_clear_free(tmp);
+ EC_POINT_free(nq);
return ret;
}
int
sshkey_ec_validate_private(const EC_KEY *key)
{
- BN_CTX *bnctx;
- BIGNUM *order, *tmp;
+ BIGNUM *order = NULL, *tmp = NULL;
int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
- if ((bnctx = BN_CTX_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- BN_CTX_start(bnctx);
-
- if ((order = BN_CTX_get(bnctx)) == NULL ||
- (tmp = BN_CTX_get(bnctx)) == NULL) {
+ if ((order = BN_new()) == NULL || (tmp = BN_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
/* log2(private) > log2(order)/2 */
- if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1) {
+ if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, NULL) != 1) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
@@ -2980,47 +3768,43 @@ sshkey_ec_validate_private(const EC_KEY *key)
goto out;
ret = 0;
out:
- BN_CTX_free(bnctx);
+ BN_clear_free(order);
+ BN_clear_free(tmp);
return ret;
}
void
sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
{
- BIGNUM *x, *y;
- BN_CTX *bnctx;
+ BIGNUM *x = NULL, *y = NULL;
if (point == NULL) {
fputs("point=(NULL)\n", stderr);
return;
}
- if ((bnctx = BN_CTX_new()) == NULL) {
- fprintf(stderr, "%s: BN_CTX_new failed\n", __func__);
- return;
- }
- BN_CTX_start(bnctx);
- if ((x = BN_CTX_get(bnctx)) == NULL ||
- (y = BN_CTX_get(bnctx)) == NULL) {
- fprintf(stderr, "%s: BN_CTX_get failed\n", __func__);
- return;
+ if ((x = BN_new()) == NULL || (y = BN_new()) == NULL) {
+ fprintf(stderr, "%s: BN_new failed\n", __func__);
+ goto out;
}
if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
NID_X9_62_prime_field) {
fprintf(stderr, "%s: group is not a prime field\n", __func__);
- return;
+ goto out;
}
- if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y,
- bnctx) != 1) {
+ if (EC_POINT_get_affine_coordinates_GFp(group, point,
+ x, y, NULL) != 1) {
fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n",
__func__);
- return;
+ goto out;
}
fputs("x=", stderr);
BN_print_fp(stderr, x);
fputs("\ny=", stderr);
BN_print_fp(stderr, y);
fputs("\n", stderr);
- BN_CTX_free(bnctx);
+ out:
+ BN_clear_free(x);
+ BN_clear_free(y);
}
void
@@ -3040,7 +3824,7 @@ sshkey_dump_ec_key(const EC_KEY *key)
#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
static int
-sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
+sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob,
const char *passphrase, const char *comment, const char *ciphername,
int rounds)
{
@@ -3050,13 +3834,11 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
u_int check;
int r = SSH_ERR_INTERNAL_ERROR;
- struct sshcipher_ctx ciphercontext;
+ struct sshcipher_ctx *ciphercontext = NULL;
const struct sshcipher *cipher;
const char *kdfname = KDFNAME;
struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL;
- memset(&ciphercontext, 0, sizeof(ciphercontext));
-
if (rounds <= 0)
rounds = DEFAULT_ROUNDS;
if (passphrase == NULL || !strlen(passphrase)) {
@@ -3064,12 +3846,8 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
kdfname = "none";
} else if (ciphername == NULL)
ciphername = DEFAULT_CIPHERNAME;
- else if (cipher_number(ciphername) != SSH_CIPHER_SSH2) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
if ((cipher = cipher_by_name(ciphername)) == NULL) {
- r = SSH_ERR_INTERNAL_ERROR;
+ r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
@@ -3124,7 +3902,8 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
goto out;
/* append private key and comment*/
- if ((r = sshkey_private_serialize(prv, encrypted)) != 0 ||
+ if ((r = sshkey_private_serialize_opt(prv, encrypted,
+ SSHKEY_SERIALIZE_FULL)) != 0 ||
(r = sshbuf_put_cstring(encrypted, comment)) != 0)
goto out;
@@ -3143,29 +3922,16 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
if ((r = sshbuf_reserve(encoded,
sshbuf_len(encrypted) + authlen, &cp)) != 0)
goto out;
- if ((r = cipher_crypt(&ciphercontext, 0, cp,
+ if ((r = cipher_crypt(ciphercontext, 0, cp,
sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0)
goto out;
- /* uuencode */
- if ((b64 = sshbuf_dtob64(encoded)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
-
sshbuf_reset(blob);
- if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0)
- goto out;
- for (i = 0; i < strlen(b64); i++) {
- if ((r = sshbuf_put_u8(blob, b64[i])) != 0)
- goto out;
- /* insert line breaks */
- if (i % 70 == 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
- goto out;
- }
- if (i % 70 != 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
- goto out;
- if ((r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
+
+ /* assemble uuencoded key */
+ if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0 ||
+ (r = sshbuf_dtob64(encoded, blob, 1)) != 0 ||
+ (r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
goto out;
/* success */
@@ -3175,49 +3941,33 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
sshbuf_free(kdf);
sshbuf_free(encoded);
sshbuf_free(encrypted);
- cipher_cleanup(&ciphercontext);
+ cipher_free(ciphercontext);
explicit_bzero(salt, sizeof(salt));
- if (key != NULL) {
- explicit_bzero(key, keylen + ivlen);
- free(key);
- }
- if (pubkeyblob != NULL) {
- explicit_bzero(pubkeyblob, pubkeylen);
- free(pubkeyblob);
- }
- if (b64 != NULL) {
- explicit_bzero(b64, strlen(b64));
- free(b64);
- }
+ if (key != NULL)
+ freezero(key, keylen + ivlen);
+ if (pubkeyblob != NULL)
+ freezero(pubkeyblob, pubkeylen);
+ if (b64 != NULL)
+ freezero(b64, strlen(b64));
return r;
}
static int
-sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
- struct sshkey **keyp, char **commentp)
+private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp)
{
- char *comment = NULL, *ciphername = NULL, *kdfname = NULL;
- const struct sshcipher *cipher = NULL;
const u_char *cp;
- int r = SSH_ERR_INTERNAL_ERROR;
size_t encoded_len;
- size_t i, keylen = 0, ivlen = 0, slen = 0;
+ int r;
+ u_char last;
struct sshbuf *encoded = NULL, *decoded = NULL;
- struct sshbuf *kdf = NULL, *decrypted = NULL;
- struct sshcipher_ctx ciphercontext;
- struct sshkey *k = NULL;
- u_char *key = NULL, *salt = NULL, *dp, pad, last;
- u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
- memset(&ciphercontext, 0, sizeof(ciphercontext));
- if (keyp != NULL)
- *keyp = NULL;
- if (commentp != NULL)
- *commentp = NULL;
+ if (blob == NULL || decodedp == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+
+ *decodedp = NULL;
if ((encoded = sshbuf_new()) == NULL ||
- (decoded = sshbuf_new()) == NULL ||
- (decrypted = sshbuf_new()) == NULL) {
+ (decoded = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
@@ -3267,13 +4017,56 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
+ /* success */
+ *decodedp = decoded;
+ decoded = NULL;
+ r = 0;
+ out:
+ sshbuf_free(encoded);
+ sshbuf_free(decoded);
+ return r;
+}
+
+static int
+private2_decrypt(struct sshbuf *decoded, const char *passphrase,
+ struct sshbuf **decryptedp, struct sshkey **pubkeyp)
+{
+ char *ciphername = NULL, *kdfname = NULL;
+ const struct sshcipher *cipher = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0;
+ struct sshbuf *kdf = NULL, *decrypted = NULL;
+ struct sshcipher_ctx *ciphercontext = NULL;
+ struct sshkey *pubkey = NULL;
+ u_char *key = NULL, *salt = NULL, *dp;
+ u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
+
+ if (decoded == NULL || decryptedp == NULL || pubkeyp == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+
+ *decryptedp = NULL;
+ *pubkeyp = NULL;
+
+ if ((decrypted = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
/* parse public portion of key */
if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
(r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||
(r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||
(r = sshbuf_froms(decoded, &kdf)) != 0 ||
- (r = sshbuf_get_u32(decoded, &nkeys)) != 0 ||
- (r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */
+ (r = sshbuf_get_u32(decoded, &nkeys)) != 0)
+ goto out;
+
+ if (nkeys != 1) {
+ /* XXX only one key supported at present */
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+
+ if ((r = sshkey_froms(decoded, &pubkey)) != 0 ||
(r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
goto out;
@@ -3281,23 +4074,18 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
r = SSH_ERR_KEY_UNKNOWN_CIPHER;
goto out;
}
- if ((passphrase == NULL || strlen(passphrase) == 0) &&
- strcmp(ciphername, "none") != 0) {
- /* passphrase required */
- r = SSH_ERR_KEY_WRONG_PASSPHRASE;
- goto out;
- }
if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) {
r = SSH_ERR_KEY_UNKNOWN_CIPHER;
goto out;
}
- if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) {
+ if (strcmp(kdfname, "none") == 0 && strcmp(ciphername, "none") != 0) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
- if (nkeys != 1) {
- /* XXX only one key supported */
- r = SSH_ERR_INVALID_FORMAT;
+ if ((passphrase == NULL || strlen(passphrase) == 0) &&
+ strcmp(kdfname, "none") != 0) {
+ /* passphrase required */
+ r = SSH_ERR_KEY_WRONG_PASSPHRASE;
goto out;
}
@@ -3311,6 +4099,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
/* setup key */
keylen = cipher_keylen(cipher);
ivlen = cipher_ivlen(cipher);
+ authlen = cipher_authlen(cipher);
if ((key = calloc(1, keylen + ivlen)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
@@ -3326,19 +4115,26 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
}
}
+ /* check that an appropriate amount of auth data is present */
+ if (sshbuf_len(decoded) < authlen ||
+ sshbuf_len(decoded) - authlen < encrypted_len) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+
/* decrypt private portion of key */
if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 ||
(r = cipher_init(&ciphercontext, cipher, key, keylen,
key + keylen, ivlen, 0)) != 0)
goto out;
- if ((r = cipher_crypt(&ciphercontext, 0, dp, sshbuf_ptr(decoded),
- sshbuf_len(decoded), 0, cipher_authlen(cipher))) != 0) {
+ if ((r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(decoded),
+ encrypted_len, 0, authlen)) != 0) {
/* an integrity error here indicates an incorrect passphrase */
if (r == SSH_ERR_MAC_INVALID)
r = SSH_ERR_KEY_WRONG_PASSPHRASE;
goto out;
}
- if ((r = sshbuf_consume(decoded, encrypted_len)) != 0)
+ if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0)
goto out;
/* there should be no trailing data */
if (sshbuf_len(decoded) != 0) {
@@ -3354,13 +4150,38 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
r = SSH_ERR_KEY_WRONG_PASSPHRASE;
goto out;
}
+ /* success */
+ *decryptedp = decrypted;
+ decrypted = NULL;
+ *pubkeyp = pubkey;
+ pubkey = NULL;
+ r = 0;
+ out:
+ cipher_free(ciphercontext);
+ free(ciphername);
+ free(kdfname);
+ sshkey_free(pubkey);
+ if (salt != NULL) {
+ explicit_bzero(salt, slen);
+ free(salt);
+ }
+ if (key != NULL) {
+ explicit_bzero(key, keylen + ivlen);
+ free(key);
+ }
+ sshbuf_free(kdf);
+ sshbuf_free(decrypted);
+ return r;
+}
- /* Load the private key and comment */
- if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
- (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
- goto out;
+/* Check deterministic padding after private key */
+static int
+private2_check_padding(struct sshbuf *decrypted)
+{
+ u_char pad;
+ size_t i;
+ int r = SSH_ERR_INTERNAL_ERROR;
- /* Check deterministic padding */
i = 0;
while (sshbuf_len(decrypted)) {
if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)
@@ -3370,8 +4191,54 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
goto out;
}
}
+ /* success */
+ r = 0;
+ out:
+ explicit_bzero(&pad, sizeof(pad));
+ explicit_bzero(&i, sizeof(i));
+ return r;
+}
- /* XXX decode pubkey and check against private */
+static int
+sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
+ struct sshkey **keyp, char **commentp)
+{
+ char *comment = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ struct sshbuf *decoded = NULL, *decrypted = NULL;
+ struct sshkey *k = NULL, *pubkey = NULL;
+
+ if (keyp != NULL)
+ *keyp = NULL;
+ if (commentp != NULL)
+ *commentp = NULL;
+
+ /* Undo base64 encoding and decrypt the private section */
+ if ((r = private2_uudecode(blob, &decoded)) != 0 ||
+ (r = private2_decrypt(decoded, passphrase,
+ &decrypted, &pubkey)) != 0)
+ goto out;
+
+ if (type != KEY_UNSPEC &&
+ sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) {
+ r = SSH_ERR_KEY_TYPE_MISMATCH;
+ goto out;
+ }
+
+ /* Load the private key and comment */
+ if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
+ (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
+ goto out;
+
+ /* Check deterministic padding after private section */
+ if ((r = private2_check_padding(decrypted)) != 0)
+ goto out;
+
+ /* Check that the public key in the envelope matches the private key */
+ if (!sshkey_equal(pubkey, k)) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
/* success */
r = 0;
@@ -3384,167 +4251,121 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
comment = NULL;
}
out:
- pad = 0;
- cipher_cleanup(&ciphercontext);
- free(ciphername);
- free(kdfname);
free(comment);
- if (salt != NULL) {
- explicit_bzero(salt, slen);
- free(salt);
- }
- if (key != NULL) {
- explicit_bzero(key, keylen + ivlen);
- free(key);
- }
- sshbuf_free(encoded);
sshbuf_free(decoded);
- sshbuf_free(kdf);
sshbuf_free(decrypted);
sshkey_free(k);
+ sshkey_free(pubkey);
return r;
}
-#if WITH_SSH1
-/*
- * Serialises the authentication (private) key to a blob, encrypting it with
- * passphrase. The identification of the blob (lowest 64 bits of n) will
- * precede the key to provide identification of the key without needing a
- * passphrase.
- */
static int
-sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
- const char *passphrase, const char *comment)
+sshkey_parse_private2_pubkey(struct sshbuf *blob, int type,
+ struct sshkey **keyp)
{
- struct sshbuf *buffer = NULL, *encrypted = NULL;
- u_char buf[8];
- int r, cipher_num;
- struct sshcipher_ctx ciphercontext;
- const struct sshcipher *cipher;
- u_char *cp;
-
- /*
- * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
- * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
- */
- cipher_num = (strcmp(passphrase, "") == 0) ?
- SSH_CIPHER_NONE : SSH_CIPHER_3DES;
- if ((cipher = cipher_by_number(cipher_num)) == NULL)
- return SSH_ERR_INTERNAL_ERROR;
-
- /* This buffer is used to build the secret part of the private key. */
- if ((buffer = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ struct sshbuf *decoded = NULL;
+ struct sshkey *pubkey = NULL;
+ u_int nkeys = 0;
- /* Put checkbytes for checking passphrase validity. */
- if ((r = sshbuf_reserve(buffer, 4, &cp)) != 0)
- goto out;
- arc4random_buf(cp, 2);
- memcpy(cp + 2, cp, 2);
+ if (keyp != NULL)
+ *keyp = NULL;
- /*
- * Store the private key (n and e will not be stored because they
- * will be stored in plain text, and storing them also in encrypted
- * format would just give known plaintext).
- * Note: q and p are stored in reverse order to SSL.
- */
- if ((r = sshbuf_put_bignum1(buffer, key->rsa->d)) != 0 ||
- (r = sshbuf_put_bignum1(buffer, key->rsa->iqmp)) != 0 ||
- (r = sshbuf_put_bignum1(buffer, key->rsa->q)) != 0 ||
- (r = sshbuf_put_bignum1(buffer, key->rsa->p)) != 0)
+ if ((r = private2_uudecode(blob, &decoded)) != 0)
goto out;
-
- /* Pad the part to be encrypted to a size that is a multiple of 8. */
- explicit_bzero(buf, 8);
- if ((r = sshbuf_put(buffer, buf, 8 - (sshbuf_len(buffer) % 8))) != 0)
+ /* parse public key from unencrypted envelope */
+ if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
+ (r = sshbuf_skip_string(decoded)) != 0 || /* cipher */
+ (r = sshbuf_skip_string(decoded)) != 0 || /* KDF alg */
+ (r = sshbuf_skip_string(decoded)) != 0 || /* KDF hint */
+ (r = sshbuf_get_u32(decoded, &nkeys)) != 0)
goto out;
- /* This buffer will be used to contain the data in the file. */
- if ((encrypted = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
+ if (nkeys != 1) {
+ /* XXX only one key supported at present */
+ r = SSH_ERR_INVALID_FORMAT;
goto out;
}
- /* First store keyfile id string. */
- if ((r = sshbuf_put(encrypted, LEGACY_BEGIN,
- sizeof(LEGACY_BEGIN))) != 0)
- goto out;
-
- /* Store cipher type and "reserved" field. */
- if ((r = sshbuf_put_u8(encrypted, cipher_num)) != 0 ||
- (r = sshbuf_put_u32(encrypted, 0)) != 0)
- goto out;
-
- /* Store public key. This will be in plain text. */
- if ((r = sshbuf_put_u32(encrypted, BN_num_bits(key->rsa->n))) != 0 ||
- (r = sshbuf_put_bignum1(encrypted, key->rsa->n) != 0) ||
- (r = sshbuf_put_bignum1(encrypted, key->rsa->e) != 0) ||
- (r = sshbuf_put_cstring(encrypted, comment) != 0))
+ /* Parse the public key */
+ if ((r = sshkey_froms(decoded, &pubkey)) != 0)
goto out;
- /* Allocate space for the private part of the key in the buffer. */
- if ((r = sshbuf_reserve(encrypted, sshbuf_len(buffer), &cp)) != 0)
+ if (type != KEY_UNSPEC &&
+ sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) {
+ r = SSH_ERR_KEY_TYPE_MISMATCH;
goto out;
+ }
- if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
- CIPHER_ENCRYPT)) != 0)
- goto out;
- if ((r = cipher_crypt(&ciphercontext, 0, cp,
- sshbuf_ptr(buffer), sshbuf_len(buffer), 0, 0)) != 0)
- goto out;
- if ((r = cipher_cleanup(&ciphercontext)) != 0)
- goto out;
-
- r = sshbuf_putb(blob, encrypted);
-
+ /* success */
+ r = 0;
+ if (keyp != NULL) {
+ *keyp = pubkey;
+ pubkey = NULL;
+ }
out:
- explicit_bzero(&ciphercontext, sizeof(ciphercontext));
- explicit_bzero(buf, sizeof(buf));
- if (buffer != NULL)
- sshbuf_free(buffer);
- if (encrypted != NULL)
- sshbuf_free(encrypted);
-
+ sshbuf_free(decoded);
+ sshkey_free(pubkey);
return r;
}
-#endif /* WITH_SSH1 */
#ifdef WITH_OPENSSL
-/* convert SSH v2 key in OpenSSL PEM format */
+/* convert SSH v2 key to PEM or PKCS#8 format */
static int
-sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
- const char *_passphrase, const char *comment)
+sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf,
+ int format, const char *_passphrase, const char *comment)
{
+ int was_shielded = sshkey_is_shielded(key);
int success, r;
int blen, len = strlen(_passphrase);
u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
-#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
- const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
-#else
- const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
-#endif
- const u_char *bptr;
+ const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
+ char *bptr;
BIO *bio = NULL;
+ struct sshbuf *blob;
+ EVP_PKEY *pkey = NULL;
if (len > 0 && len <= 4)
return SSH_ERR_PASSPHRASE_TOO_SHORT;
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
+ if ((blob = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
+ if ((bio = BIO_new(BIO_s_mem())) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshkey_unshield_private(key)) != 0)
+ goto out;
switch (key->type) {
case KEY_DSA:
- success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
- cipher, passphrase, len, NULL, NULL);
+ if (format == SSHKEY_PRIVATE_PEM) {
+ success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
+ cipher, passphrase, len, NULL, NULL);
+ } else {
+ success = EVP_PKEY_set1_DSA(pkey, key->dsa);
+ }
break;
#ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
- success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
- cipher, passphrase, len, NULL, NULL);
+ if (format == SSHKEY_PRIVATE_PEM) {
+ success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
+ cipher, passphrase, len, NULL, NULL);
+ } else {
+ success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
+ }
break;
#endif
case KEY_RSA:
- success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
- cipher, passphrase, len, NULL, NULL);
+ if (format == SSHKEY_PRIVATE_PEM) {
+ success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
+ cipher, passphrase, len, NULL, NULL);
+ } else {
+ success = EVP_PKEY_set1_RSA(pkey, key->rsa);
+ }
break;
default:
success = 0;
@@ -3554,6 +4375,13 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
+ if (format == SSHKEY_PRIVATE_PKCS8) {
+ if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher,
+ passphrase, len, NULL, NULL)) == 0) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ }
if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
r = SSH_ERR_INTERNAL_ERROR;
goto out;
@@ -3562,6 +4390,13 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
goto out;
r = 0;
out:
+ if (was_shielded)
+ r = sshkey_shield_private(key);
+ if (r == 0)
+ r = sshbuf_putb(buf, blob);
+
+ EVP_PKEY_free(pkey);
+ sshbuf_free(blob);
BIO_free(bio);
return r;
}
@@ -3571,220 +4406,123 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
int
sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
const char *passphrase, const char *comment,
- int force_new_format, const char *new_format_cipher, int new_format_rounds)
+ int format, const char *openssh_format_cipher, int openssh_format_rounds)
{
switch (key->type) {
-#ifdef WITH_SSH1
- case KEY_RSA1:
- return sshkey_private_rsa1_to_blob(key, blob,
- passphrase, comment);
-#endif /* WITH_SSH1 */
#ifdef WITH_OPENSSL
case KEY_DSA:
case KEY_ECDSA:
case KEY_RSA:
- if (force_new_format) {
- return sshkey_private_to_blob2(key, blob, passphrase,
- comment, new_format_cipher, new_format_rounds);
- }
- return sshkey_private_pem_to_blob(key, blob,
- passphrase, comment);
+ break; /* see below */
#endif /* WITH_OPENSSL */
case KEY_ED25519:
+ case KEY_ED25519_SK:
+#ifdef WITH_XMSS
+ case KEY_XMSS:
+#endif /* WITH_XMSS */
+#ifdef WITH_OPENSSL
+ case KEY_ECDSA_SK:
+#endif /* WITH_OPENSSL */
return sshkey_private_to_blob2(key, blob, passphrase,
- comment, new_format_cipher, new_format_rounds);
+ comment, openssh_format_cipher, openssh_format_rounds);
default:
return SSH_ERR_KEY_TYPE_UNKNOWN;
}
+
+#ifdef WITH_OPENSSL
+ switch (format) {
+ case SSHKEY_PRIVATE_OPENSSH:
+ return sshkey_private_to_blob2(key, blob, passphrase,
+ comment, openssh_format_cipher, openssh_format_rounds);
+ case SSHKEY_PRIVATE_PEM:
+ case SSHKEY_PRIVATE_PKCS8:
+ return sshkey_private_to_blob_pem_pkcs8(key, blob,
+ format, passphrase, comment);
+ default:
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+#endif /* WITH_OPENSSL */
}
-#ifdef WITH_SSH1
-/*
- * Parse the public, unencrypted portion of a RSA1 key.
- */
-int
-sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob,
- struct sshkey **keyp, char **commentp)
+#ifdef WITH_OPENSSL
+static int
+translate_libcrypto_error(unsigned long pem_err)
{
- int r;
- struct sshkey *pub = NULL;
- struct sshbuf *copy = NULL;
-
- if (keyp != NULL)
- *keyp = NULL;
- if (commentp != NULL)
- *commentp = NULL;
-
- /* Check that it is at least big enough to contain the ID string. */
- if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN))
- return SSH_ERR_INVALID_FORMAT;
-
- /*
- * Make sure it begins with the id string. Consume the id string
- * from the buffer.
- */
- if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0)
+ int pem_reason = ERR_GET_REASON(pem_err);
+
+ switch (ERR_GET_LIB(pem_err)) {
+ case ERR_LIB_PEM:
+ switch (pem_reason) {
+ case PEM_R_BAD_PASSWORD_READ:
+#ifdef PEM_R_PROBLEMS_GETTING_PASSWORD
+ case PEM_R_PROBLEMS_GETTING_PASSWORD:
+#endif
+ case PEM_R_BAD_DECRYPT:
+ return SSH_ERR_KEY_WRONG_PASSPHRASE;
+ default:
+ return SSH_ERR_INVALID_FORMAT;
+ }
+ case ERR_LIB_EVP:
+ switch (pem_reason) {
+#ifdef EVP_R_BAD_DECRYPT
+ case EVP_R_BAD_DECRYPT:
+ return SSH_ERR_KEY_WRONG_PASSPHRASE;
+#endif
+#ifdef EVP_R_BN_DECODE_ERROR
+ case EVP_R_BN_DECODE_ERROR:
+#endif
+ case EVP_R_DECODE_ERROR:
+#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
+ case EVP_R_PRIVATE_KEY_DECODE_ERROR:
+#endif
+ return SSH_ERR_INVALID_FORMAT;
+ default:
+ return SSH_ERR_LIBCRYPTO_ERROR;
+ }
+ case ERR_LIB_ASN1:
return SSH_ERR_INVALID_FORMAT;
- /* Make a working copy of the keyblob and skip past the magic */
- if ((copy = sshbuf_fromb(blob)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0)
- goto out;
-
- /* Skip cipher type, reserved data and key bits. */
- if ((r = sshbuf_get_u8(copy, NULL)) != 0 || /* cipher type */
- (r = sshbuf_get_u32(copy, NULL)) != 0 || /* reserved */
- (r = sshbuf_get_u32(copy, NULL)) != 0) /* key bits */
- goto out;
-
- /* Read the public key from the buffer. */
- if ((pub = sshkey_new(KEY_RSA1)) == NULL ||
- (r = sshbuf_get_bignum1(copy, pub->rsa->n)) != 0 ||
- (r = sshbuf_get_bignum1(copy, pub->rsa->e)) != 0)
- goto out;
-
- /* Finally, the comment */
- if ((r = sshbuf_get_string(copy, (u_char**)commentp, NULL)) != 0)
- goto out;
-
- /* The encrypted private part is not parsed by this function. */
-
- r = 0;
- if (keyp != NULL)
- *keyp = pub;
- else
- sshkey_free(pub);
- pub = NULL;
+ }
+ return SSH_ERR_LIBCRYPTO_ERROR;
+}
- out:
- if (copy != NULL)
- sshbuf_free(copy);
- if (pub != NULL)
- sshkey_free(pub);
- return r;
+static void
+clear_libcrypto_errors(void)
+{
+ while (ERR_get_error() != 0)
+ ;
}
+/*
+ * Translate OpenSSL error codes to determine whether
+ * passphrase is required/incorrect.
+ */
static int
-sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
- struct sshkey **keyp, char **commentp)
+convert_libcrypto_error(void)
{
- int r;
- u_int16_t check1, check2;
- u_int8_t cipher_type;
- struct sshbuf *decrypted = NULL, *copy = NULL;
- u_char *cp;
- char *comment = NULL;
- struct sshcipher_ctx ciphercontext;
- const struct sshcipher *cipher;
- struct sshkey *prv = NULL;
-
- *keyp = NULL;
- if (commentp != NULL)
- *commentp = NULL;
-
- /* Check that it is at least big enough to contain the ID string. */
- if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN))
- return SSH_ERR_INVALID_FORMAT;
-
/*
- * Make sure it begins with the id string. Consume the id string
- * from the buffer.
+ * Some password errors are reported at the beginning
+ * of the error queue.
*/
- if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0)
- return SSH_ERR_INVALID_FORMAT;
-
- if ((prv = sshkey_new_private(KEY_RSA1)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((copy = sshbuf_fromb(blob)) == NULL ||
- (decrypted = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0)
- goto out;
-
- /* Read cipher type. */
- if ((r = sshbuf_get_u8(copy, &cipher_type)) != 0 ||
- (r = sshbuf_get_u32(copy, NULL)) != 0) /* reserved */
- goto out;
-
- /* Read the public key and comment from the buffer. */
- if ((r = sshbuf_get_u32(copy, NULL)) != 0 || /* key bits */
- (r = sshbuf_get_bignum1(copy, prv->rsa->n)) != 0 ||
- (r = sshbuf_get_bignum1(copy, prv->rsa->e)) != 0 ||
- (r = sshbuf_get_cstring(copy, &comment, NULL)) != 0)
- goto out;
-
- /* Check that it is a supported cipher. */
- cipher = cipher_by_number(cipher_type);
- if (cipher == NULL) {
- r = SSH_ERR_KEY_UNKNOWN_CIPHER;
- goto out;
- }
- /* Initialize space for decrypted data. */
- if ((r = sshbuf_reserve(decrypted, sshbuf_len(copy), &cp)) != 0)
- goto out;
-
- /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
- if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
- CIPHER_DECRYPT)) != 0)
- goto out;
- if ((r = cipher_crypt(&ciphercontext, 0, cp,
- sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0) {
- cipher_cleanup(&ciphercontext);
- goto out;
- }
- if ((r = cipher_cleanup(&ciphercontext)) != 0)
- goto out;
-
- if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 ||
- (r = sshbuf_get_u16(decrypted, &check2)) != 0)
- goto out;
- if (check1 != check2) {
- r = SSH_ERR_KEY_WRONG_PASSPHRASE;
- goto out;
- }
-
- /* Read the rest of the private key. */
- if ((r = sshbuf_get_bignum1(decrypted, prv->rsa->d)) != 0 ||
- (r = sshbuf_get_bignum1(decrypted, prv->rsa->iqmp)) != 0 ||
- (r = sshbuf_get_bignum1(decrypted, prv->rsa->q)) != 0 ||
- (r = sshbuf_get_bignum1(decrypted, prv->rsa->p)) != 0)
- goto out;
+ if (translate_libcrypto_error(ERR_peek_error()) ==
+ SSH_ERR_KEY_WRONG_PASSPHRASE)
+ return SSH_ERR_KEY_WRONG_PASSPHRASE;
+ return translate_libcrypto_error(ERR_peek_last_error());
+}
- /* calculate p-1 and q-1 */
- if ((r = rsa_generate_additional_parameters(prv->rsa)) != 0)
- goto out;
+static int
+pem_passphrase_cb(char *buf, int size, int rwflag, void *u)
+{
+ char *p = (char *)u;
+ size_t len;
- /* enable blinding */
- if (RSA_blinding_on(prv->rsa, NULL) != 1) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- r = 0;
- *keyp = prv;
- prv = NULL;
- if (commentp != NULL) {
- *commentp = comment;
- comment = NULL;
- }
- out:
- explicit_bzero(&ciphercontext, sizeof(ciphercontext));
- if (comment != NULL)
- free(comment);
- if (prv != NULL)
- sshkey_free(prv);
- if (copy != NULL)
- sshbuf_free(copy);
- if (decrypted != NULL)
- sshbuf_free(decrypted);
- return r;
+ if (p == NULL || (len = strlen(p)) == 0)
+ return -1;
+ if (size < 0 || len > (size_t)size)
+ return -1;
+ memcpy(buf, p, len);
+ return (int)len;
}
-#endif /* WITH_SSH1 */
-#ifdef WITH_OPENSSL
static int
sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
const char *passphrase, struct sshkey **keyp)
@@ -3794,7 +4532,8 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
BIO *bio = NULL;
int r;
- *keyp = NULL;
+ if (keyp != NULL)
+ *keyp = NULL;
if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX)
return SSH_ERR_ALLOC_FAIL;
@@ -3804,12 +4543,22 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
goto out;
}
- if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
+ clear_libcrypto_errors();
+ if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb,
(char *)passphrase)) == NULL) {
- r = SSH_ERR_KEY_WRONG_PASSPHRASE;
+ /*
+ * libcrypto may return various ASN.1 errors when attempting
+ * to parse a key with an incorrect passphrase.
+ * Treat all format errors as "incorrect passphrase" if a
+ * passphrase was supplied.
+ */
+ if (passphrase != NULL && *passphrase != '\0')
+ r = SSH_ERR_KEY_WRONG_PASSPHRASE;
+ else
+ r = convert_libcrypto_error();
goto out;
}
- if (pk->type == EVP_PKEY_RSA &&
+ if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA &&
(type == KEY_UNSPEC || type == KEY_RSA)) {
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
@@ -3824,7 +4573,9 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
- } else if (pk->type == EVP_PKEY_DSA &&
+ if ((r = check_rsa_length(prv->rsa)) != 0)
+ goto out;
+ } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
(type == KEY_UNSPEC || type == KEY_DSA)) {
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
@@ -3836,7 +4587,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
DSA_print_fp(stderr, prv->dsa, 8);
#endif
#ifdef OPENSSL_HAS_ECC
- } else if (pk->type == EVP_PKEY_EC &&
+ } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC &&
(type == KEY_UNSPEC || type == KEY_ECDSA)) {
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
@@ -3863,14 +4614,14 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
goto out;
}
r = 0;
- *keyp = prv;
- prv = NULL;
+ if (keyp != NULL) {
+ *keyp = prv;
+ prv = NULL;
+ }
out:
BIO_free(bio);
- if (pk != NULL)
- EVP_PKEY_free(pk);
- if (prv != NULL)
- sshkey_free(prv);
+ EVP_PKEY_free(pk);
+ sshkey_free(prv);
return r;
}
#endif /* WITH_OPENSSL */
@@ -3879,63 +4630,150 @@ int
sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
const char *passphrase, struct sshkey **keyp, char **commentp)
{
- int r;
+ int r = SSH_ERR_INTERNAL_ERROR;
- *keyp = NULL;
+ if (keyp != NULL)
+ *keyp = NULL;
if (commentp != NULL)
*commentp = NULL;
switch (type) {
-#ifdef WITH_SSH1
- case KEY_RSA1:
- return sshkey_parse_private_rsa1(blob, passphrase,
- keyp, commentp);
-#endif /* WITH_SSH1 */
-#ifdef WITH_OPENSSL
- case KEY_DSA:
- case KEY_ECDSA:
- case KEY_RSA:
- return sshkey_parse_private_pem_fileblob(blob, type,
- passphrase, keyp);
-#endif /* WITH_OPENSSL */
case KEY_ED25519:
+ case KEY_XMSS:
+ /* No fallback for new-format-only keys */
return sshkey_parse_private2(blob, type, passphrase,
keyp, commentp);
- case KEY_UNSPEC:
- if ((r = sshkey_parse_private2(blob, type, passphrase, keyp,
- commentp)) == 0)
- return 0;
+ default:
+ r = sshkey_parse_private2(blob, type, passphrase, keyp,
+ commentp);
+ /* Only fallback to PEM parser if a format error occurred. */
+ if (r != SSH_ERR_INVALID_FORMAT)
+ return r;
#ifdef WITH_OPENSSL
return sshkey_parse_private_pem_fileblob(blob, type,
passphrase, keyp);
#else
return SSH_ERR_INVALID_FORMAT;
#endif /* WITH_OPENSSL */
- default:
- return SSH_ERR_KEY_TYPE_UNKNOWN;
}
}
int
sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
- const char *filename, struct sshkey **keyp, char **commentp)
+ struct sshkey **keyp, char **commentp)
{
- int r;
-
if (keyp != NULL)
*keyp = NULL;
if (commentp != NULL)
*commentp = NULL;
-#ifdef WITH_SSH1
- /* it's a SSH v1 key if the public key part is readable */
- if ((r = sshkey_parse_public_rsa1_fileblob(buffer, NULL, NULL)) == 0) {
- return sshkey_parse_private_fileblob_type(buffer, KEY_RSA1,
- passphrase, keyp, commentp);
+ return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
+ passphrase, keyp, commentp);
+}
+
+void
+sshkey_sig_details_free(struct sshkey_sig_details *details)
+{
+ freezero(details, sizeof(*details));
+}
+
+int
+sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type,
+ struct sshkey **pubkeyp)
+{
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if (pubkeyp != NULL)
+ *pubkeyp = NULL;
+ /* only new-format private keys bundle a public key inside */
+ if ((r = sshkey_parse_private2_pubkey(blob, type, pubkeyp)) != 0)
+ return r;
+ return 0;
+}
+
+#ifdef WITH_XMSS
+/*
+ * serialize the key with the current state and forward the state
+ * maxsign times.
+ */
+int
+sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
+ u_int32_t maxsign, sshkey_printfn *pr)
+{
+ int r, rupdate;
+
+ if (maxsign == 0 ||
+ sshkey_type_plain(k->type) != KEY_XMSS)
+ return sshkey_private_serialize_opt(k, b,
+ SSHKEY_SERIALIZE_DEFAULT);
+ if ((r = sshkey_xmss_get_state(k, pr)) != 0 ||
+ (r = sshkey_private_serialize_opt(k, b,
+ SSHKEY_SERIALIZE_STATE)) != 0 ||
+ (r = sshkey_xmss_forward_state(k, maxsign)) != 0)
+ goto out;
+ r = 0;
+out:
+ if ((rupdate = sshkey_xmss_update_state(k, pr)) != 0) {
+ if (r == 0)
+ r = rupdate;
}
-#endif /* WITH_SSH1 */
- if ((r = sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
- passphrase, keyp, commentp)) == 0)
- return 0;
return r;
}
+
+u_int32_t
+sshkey_signatures_left(const struct sshkey *k)
+{
+ if (sshkey_type_plain(k->type) == KEY_XMSS)
+ return sshkey_xmss_signatures_left(k);
+ return 0;
+}
+
+int
+sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
+{
+ if (sshkey_type_plain(k->type) != KEY_XMSS)
+ return SSH_ERR_INVALID_ARGUMENT;
+ return sshkey_xmss_enable_maxsign(k, maxsign);
+}
+
+int
+sshkey_set_filename(struct sshkey *k, const char *filename)
+{
+ if (k == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (sshkey_type_plain(k->type) != KEY_XMSS)
+ return 0;
+ if (filename == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((k->xmss_filename = strdup(filename)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ return 0;
+}
+#else
+int
+sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
+ u_int32_t maxsign, sshkey_printfn *pr)
+{
+ return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);
+}
+
+u_int32_t
+sshkey_signatures_left(const struct sshkey *k)
+{
+ return 0;
+}
+
+int
+sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
+{
+ return SSH_ERR_INVALID_ARGUMENT;
+}
+
+int
+sshkey_set_filename(struct sshkey *k, const char *filename)
+{
+ if (k == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ return 0;
+}
+#endif /* WITH_XMSS */
diff --git a/sshkey.h b/sshkey.h
index 62c1c3e2..9c1d4f63 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.5 2015/01/26 02:59:11 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.45 2020/04/08 00:08:46 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -33,12 +33,14 @@
#include <openssl/dsa.h>
# ifdef OPENSSL_HAS_ECC
# include <openssl/ec.h>
+# include <openssl/ecdsa.h>
# else /* OPENSSL_HAS_ECC */
# define EC_KEY void
# define EC_GROUP void
# define EC_POINT void
# endif /* OPENSSL_HAS_ECC */
#else /* WITH_OPENSSL */
+# define BIGNUM void
# define RSA void
# define DSA void
# define EC_KEY void
@@ -46,14 +48,13 @@
# define EC_POINT void
#endif /* WITH_OPENSSL */
-#define SSH_RSA_MINIMUM_MODULUS_SIZE 768
+#define SSH_RSA_MINIMUM_MODULUS_SIZE 1024
#define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20)
struct sshbuf;
/* Key types */
enum sshkey_types {
- KEY_RSA1,
KEY_RSA,
KEY_DSA,
KEY_ECDSA,
@@ -62,8 +63,12 @@ enum sshkey_types {
KEY_DSA_CERT,
KEY_ECDSA_CERT,
KEY_ED25519_CERT,
- KEY_RSA_CERT_V00,
- KEY_DSA_CERT_V00,
+ KEY_XMSS,
+ KEY_XMSS_CERT,
+ KEY_ECDSA_SK,
+ KEY_ECDSA_SK_CERT,
+ KEY_ED25519_SK,
+ KEY_ED25519_SK_CERT,
KEY_UNSPEC
};
@@ -79,6 +84,22 @@ enum sshkey_fp_rep {
SSH_FP_RANDOMART
};
+/* Private key serialisation formats, used on the wire */
+enum sshkey_serialize_rep {
+ SSHKEY_SERIALIZE_DEFAULT = 0,
+ SSHKEY_SERIALIZE_STATE = 1, /* only state is serialized */
+ SSHKEY_SERIALIZE_FULL = 2, /* include keys for saving to disk */
+ SSHKEY_SERIALIZE_SHIELD = 3, /* everything, for encrypting in ram */
+ SSHKEY_SERIALIZE_INFO = 254, /* minimal information */
+};
+
+/* Private key disk formats */
+enum sshkey_private_format {
+ SSHKEY_PRIVATE_OPENSSH = 0,
+ SSHKEY_PRIVATE_PEM = 1,
+ SSHKEY_PRIVATE_PKCS8 = 2,
+};
+
/* key is stored in external hardware */
#define SSHKEY_FLAG_EXT 0x0001
@@ -95,29 +116,54 @@ struct sshkey_cert {
struct sshbuf *critical;
struct sshbuf *extensions;
struct sshkey *signature_key;
+ char *signature_type;
};
/* XXX opaquify? */
struct sshkey {
int type;
int flags;
+ /* KEY_RSA */
RSA *rsa;
+ /* KEY_DSA */
DSA *dsa;
+ /* KEY_ECDSA and KEY_ECDSA_SK */
int ecdsa_nid; /* NID of curve */
EC_KEY *ecdsa;
+ /* KEY_ED25519 and KEY_ED25519_SK */
u_char *ed25519_sk;
u_char *ed25519_pk;
+ /* KEY_XMSS */
+ char *xmss_name;
+ char *xmss_filename; /* for state file updates */
+ void *xmss_state; /* depends on xmss_name, opaque */
+ u_char *xmss_sk;
+ u_char *xmss_pk;
+ /* KEY_ECDSA_SK and KEY_ED25519_SK */
+ char *sk_application;
+ uint8_t sk_flags;
+ struct sshbuf *sk_key_handle;
+ struct sshbuf *sk_reserved;
+ /* Certificates */
struct sshkey_cert *cert;
+ /* Private key shielding */
+ u_char *shielded_private;
+ size_t shielded_len;
+ u_char *shield_prekey;
+ size_t shield_prekey_len;
};
#define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES
#define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES
+/* Additional fields contained in signature */
+struct sshkey_sig_details {
+ uint32_t sk_counter; /* U2F signature counter */
+ uint8_t sk_flags; /* U2F signature flags; see ssh-sk.h */
+};
+
struct sshkey *sshkey_new(int);
-int sshkey_add_private(struct sshkey *);
-struct sshkey *sshkey_new_private(int);
void sshkey_free(struct sshkey *);
-int sshkey_demote(const struct sshkey *, struct sshkey **);
int sshkey_equal_public(const struct sshkey *,
const struct sshkey *);
int sshkey_equal(const struct sshkey *, const struct sshkey *);
@@ -127,23 +173,39 @@ int sshkey_fingerprint_raw(const struct sshkey *k,
int, u_char **retp, size_t *lenp);
const char *sshkey_type(const struct sshkey *);
const char *sshkey_cert_type(const struct sshkey *);
+int sshkey_format_text(const struct sshkey *, struct sshbuf *);
int sshkey_write(const struct sshkey *, FILE *);
int sshkey_read(struct sshkey *, char **);
u_int sshkey_size(const struct sshkey *);
int sshkey_generate(int type, u_int bits, struct sshkey **keyp);
int sshkey_from_private(const struct sshkey *, struct sshkey **);
+
+int sshkey_is_shielded(struct sshkey *);
+int sshkey_shield_private(struct sshkey *);
+int sshkey_unshield_private(struct sshkey *);
+
int sshkey_type_from_name(const char *);
int sshkey_is_cert(const struct sshkey *);
+int sshkey_is_sk(const struct sshkey *);
int sshkey_type_is_cert(int);
int sshkey_type_plain(int);
-int sshkey_to_certified(struct sshkey *, int);
+int sshkey_to_certified(struct sshkey *);
int sshkey_drop_cert(struct sshkey *);
-int sshkey_certify(struct sshkey *, struct sshkey *);
int sshkey_cert_copy(const struct sshkey *, struct sshkey *);
int sshkey_cert_check_authority(const struct sshkey *, int, int,
const char *, const char **);
-int sshkey_cert_is_legacy(const struct sshkey *);
+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 *);
+/* 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 *);
+int sshkey_certify_custom(struct sshkey *, struct sshkey *, const char *,
+ const char *, sshkey_certify_signer *, void *);
int sshkey_ecdsa_nid_from_name(const char *);
int sshkey_curve_name_to_nid(const char *);
@@ -157,48 +219,74 @@ int sshkey_ec_validate_private(const EC_KEY *);
const char *sshkey_ssh_name(const struct sshkey *);
const char *sshkey_ssh_name_plain(const struct sshkey *);
int sshkey_names_valid2(const char *, int);
-char *key_alg_list(int, int);
+char *sshkey_alg_list(int, int, int, char);
int sshkey_from_blob(const u_char *, size_t, struct sshkey **);
int sshkey_fromb(struct sshbuf *, struct sshkey **);
int sshkey_froms(struct sshbuf *, struct sshkey **);
int sshkey_to_blob(const struct sshkey *, u_char **, size_t *);
+int sshkey_to_base64(const struct sshkey *, char **);
int sshkey_putb(const struct sshkey *, struct sshbuf *);
int sshkey_puts(const struct sshkey *, struct sshbuf *);
+int sshkey_puts_opts(const struct sshkey *, struct sshbuf *,
+ enum sshkey_serialize_rep);
int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *);
int sshkey_putb_plain(const struct sshkey *, struct sshbuf *);
-int sshkey_sign(const struct sshkey *, u_char **, size_t *,
- const u_char *, size_t, u_int);
+int sshkey_sign(struct sshkey *, u_char **, size_t *,
+ const u_char *, size_t, const char *, const char *, u_int);
int sshkey_verify(const struct sshkey *, const u_char *, size_t,
- const u_char *, size_t, u_int);
+ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **);
+int sshkey_check_sigtype(const u_char *, size_t, const char *);
+const char *sshkey_sigalg_by_name(const char *);
+int sshkey_get_sigtype(const u_char *, size_t, char **);
/* for debug */
void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *);
void sshkey_dump_ec_key(const EC_KEY *);
/* private key parsing and serialisation */
-int sshkey_private_serialize(const struct sshkey *key, struct sshbuf *buf);
+int sshkey_private_serialize(struct sshkey *key, struct sshbuf *buf);
+int sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
+ enum sshkey_serialize_rep);
int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp);
/* private key file format parsing and serialisation */
int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
const char *passphrase, const char *comment,
- int force_new_format, const char *new_format_cipher, int new_format_rounds);
-int sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob,
- struct sshkey **keyp, char **commentp);
+ int format, const char *openssh_format_cipher, int openssh_format_rounds);
int sshkey_parse_private_fileblob(struct sshbuf *buffer,
- const char *passphrase, const char *filename, struct sshkey **keyp,
- char **commentp);
+ const char *passphrase, struct sshkey **keyp, char **commentp);
int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
const char *passphrase, struct sshkey **keyp, char **commentp);
+int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob,
+ int type, struct sshkey **pubkeyp);
+
+/* XXX should be internal, but used by ssh-keygen */
+int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *);
+
+/* stateful keys (e.g. XMSS) */
+#ifdef NO_ATTRIBUTE_ON_PROTOTYPE_ARGS
+typedef void sshkey_printfn(const char *, ...);
+#else
+typedef void sshkey_printfn(const char *, ...) __attribute__((format(printf, 1, 2)));
+#endif
+int sshkey_set_filename(struct sshkey *, const char *);
+int sshkey_enable_maxsign(struct sshkey *, u_int32_t);
+u_int32_t sshkey_signatures_left(const struct sshkey *);
+int sshkey_forward_state(const struct sshkey *, u_int32_t, sshkey_printfn *);
+int sshkey_private_serialize_maxsign(struct sshkey *key, struct sshbuf *buf,
+ u_int32_t maxsign, sshkey_printfn *pr);
+
+void sshkey_sig_details_free(struct sshkey_sig_details *);
#ifdef SSHKEY_INTERNAL
-int ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, u_int compat);
+int ssh_rsa_sign(const struct sshkey *key,
+ u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
+ const char *ident);
int ssh_rsa_verify(const struct sshkey *key,
- const u_char *signature, size_t signaturelen,
- const u_char *data, size_t datalen, u_int compat);
+ const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
+ const char *alg);
int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat);
int ssh_dss_verify(const struct sshkey *key,
@@ -209,11 +297,24 @@ int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
int ssh_ecdsa_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
const u_char *data, size_t datalen, u_int compat);
+int ssh_ecdsa_sk_verify(const struct sshkey *key,
+ const u_char *signature, size_t signaturelen,
+ const u_char *data, size_t datalen, u_int compat,
+ struct sshkey_sig_details **detailsp);
int ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat);
int ssh_ed25519_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
const u_char *data, size_t datalen, u_int compat);
+int ssh_ed25519_sk_verify(const struct sshkey *key,
+ const u_char *signature, size_t signaturelen,
+ const u_char *data, size_t datalen, u_int compat,
+ struct sshkey_sig_details **detailsp);
+int ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
+ const u_char *data, size_t datalen, u_int compat);
+int ssh_xmss_verify(const struct sshkey *key,
+ const u_char *signature, size_t signaturelen,
+ const u_char *data, size_t datalen, u_int compat);
#endif
#if !defined(WITH_OPENSSL)
diff --git a/sshlogin.c b/sshlogin.c
index 818312ff..08d2600b 100644
--- a/sshlogin.c
+++ b/sshlogin.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshlogin.c,v 1.31 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: sshlogin.c,v 1.34 2019/06/28 13:35:04 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -55,13 +55,15 @@
#include <unistd.h>
#include <limits.h>
+#include "sshlogin.h"
+#include "ssherr.h"
#include "loginrec.h"
#include "log.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "misc.h"
#include "servconf.h"
-extern Buffer loginmsg;
+extern struct sshbuf *loginmsg;
extern ServerOptions options;
/*
@@ -88,8 +90,12 @@ static void
store_lastlog_message(const char *user, uid_t uid)
{
#ifndef NO_SSH_LASTLOG
- char *time_string, hostname[HOST_NAME_MAX+1] = "", buf[512];
+# ifndef CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG
+ char hostname[HOST_NAME_MAX+1] = "";
time_t last_login_time;
+# endif
+ char *time_string;
+ int r;
if (!options.print_lastlog)
return;
@@ -97,7 +103,9 @@ store_lastlog_message(const char *user, uid_t uid)
# ifdef CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG
time_string = sys_auth_get_lastlogin_msg(user, uid);
if (time_string != NULL) {
- buffer_append(&loginmsg, time_string, strlen(time_string));
+ if ((r = sshbuf_put(loginmsg,
+ time_string, strlen(time_string))) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(time_string);
}
# else
@@ -108,12 +116,13 @@ store_lastlog_message(const char *user, uid_t uid)
time_string = ctime(&last_login_time);
time_string[strcspn(time_string, "\n")] = '\0';
if (strcmp(hostname, "") == 0)
- snprintf(buf, sizeof(buf), "Last login: %s\r\n",
+ r = sshbuf_putf(loginmsg, "Last login: %s\r\n",
time_string);
else
- snprintf(buf, sizeof(buf), "Last login: %s from %s\r\n",
+ r = sshbuf_putf(loginmsg, "Last login: %s from %s\r\n",
time_string, hostname);
- buffer_append(&loginmsg, buf, strlen(buf));
+ if (r != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
# endif /* CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG */
#endif /* NO_SSH_LASTLOG */
diff --git a/sshpty.c b/sshpty.c
index 58169226..bce09e25 100644
--- a/sshpty.c
+++ b/sshpty.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshpty.c,v 1.29 2014/09/03 18:55:07 djm Exp $ */
+/* $OpenBSD: sshpty.c,v 1.34 2019/07/04 16:20:10 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -68,26 +68,16 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
int i;
i = openpty(ptyfd, ttyfd, NULL, NULL, NULL);
- if (i < 0) {
+ if (i == -1) {
error("openpty: %.100s", strerror(errno));
return 0;
}
-#ifdef ANDROID
- if (ptsname_r(*ptyfd, namebuf, namebuflen)) {
- fatal("openpty ptsname failed.");
- close(*ptyfd);
- *ptyfd = -1;
- return -1;
- }
- return 1;
-#else
name = ttyname(*ttyfd);
if (!name)
fatal("openpty returns device for which ttyname fails.");
strlcpy(namebuf, name, namebuflen); /* possible truncation */
return 1;
-#endif
}
/* Releases the tty. Its ownership is returned to root, and permissions to 0666. */
@@ -95,12 +85,12 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
void
pty_release(const char *tty)
{
-#ifndef __APPLE_PRIVPTY__
- if (chown(tty, (uid_t) 0, (gid_t) 0) < 0)
+#if !defined(__APPLE_PRIVPTY__) && !defined(HAVE_OPENPTY)
+ if (chown(tty, (uid_t) 0, (gid_t) 0) == -1)
error("chown %.100s 0 0 failed: %.100s", tty, strerror(errno));
- if (chmod(tty, (mode_t) 0666) < 0)
+ if (chmod(tty, (mode_t) 0666) == -1)
error("chmod %.100s 0666 failed: %.100s", tty, strerror(errno));
-#endif /* __APPLE_PRIVPTY__ */
+#endif /* !__APPLE_PRIVPTY__ && !HAVE_OPENPTY */
}
/* Makes the tty the process's controlling tty and sets it to sane modes. */
@@ -110,30 +100,6 @@ pty_make_controlling_tty(int *ttyfd, const char *tty)
{
int fd;
-#ifdef _UNICOS
- if (setsid() < 0)
- error("setsid: %.100s", strerror(errno));
-
- fd = open(tty, O_RDWR|O_NOCTTY);
- if (fd != -1) {
- signal(SIGHUP, SIG_IGN);
- ioctl(fd, TCVHUP, (char *)NULL);
- signal(SIGHUP, SIG_DFL);
- setpgid(0, 0);
- close(fd);
- } else {
- error("Failed to disconnect from controlling tty.");
- }
-
- debug("Setting controlling tty using TCSETCTTY.");
- ioctl(*ttyfd, TCSETCTTY, NULL);
- fd = open("/dev/tty", O_RDWR);
- if (fd < 0)
- error("%.100s: %.100s", tty, strerror(errno));
- close(*ttyfd);
- *ttyfd = fd;
-#else /* _UNICOS */
-
/* First disconnect from the old controlling tty. */
#ifdef TIOCNOTTY
fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
@@ -142,7 +108,7 @@ pty_make_controlling_tty(int *ttyfd, const char *tty)
close(fd);
}
#endif /* TIOCNOTTY */
- if (setsid() < 0)
+ if (setsid() == -1)
error("setsid: %.100s", strerror(errno));
/*
@@ -165,19 +131,18 @@ pty_make_controlling_tty(int *ttyfd, const char *tty)
error("SETPGRP %s",strerror(errno));
#endif /* NEED_SETPGRP */
fd = open(tty, O_RDWR);
- if (fd < 0) {
+ if (fd == -1)
error("%.100s: %.100s", tty, strerror(errno));
- } else {
+ else
close(fd);
- }
+
/* Verify that we now have a controlling tty. */
fd = open(_PATH_TTY, O_WRONLY);
- if (fd < 0)
+ if (fd == -1)
error("open /dev/tty failed - could not set controlling tty: %.100s",
strerror(errno));
else
close(fd);
-#endif /* _UNICOS */
}
/* Changes the window size associated with the pty. */
@@ -206,15 +171,17 @@ pty_setowner(struct passwd *pw, const char *tty)
/* Determine the group to make the owner of the tty. */
grp = getgrnam("tty");
+ if (grp == NULL)
+ debug("%s: no tty group", __func__);
gid = (grp != NULL) ? grp->gr_gid : pw->pw_gid;
- mode = (grp != NULL) ? 0622 : 0600;
+ mode = (grp != NULL) ? 0620 : 0600;
/*
* Change owner and mode of the tty as required.
* Warn but continue if filesystem is read-only and the uids match/
* tty is owned by root.
*/
- if (stat(tty, &st))
+ if (stat(tty, &st) == -1)
fatal("stat(%.100s) failed: %.100s", tty,
strerror(errno));
@@ -223,7 +190,7 @@ pty_setowner(struct passwd *pw, const char *tty)
#endif
if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
- if (chown(tty, pw->pw_uid, gid) < 0) {
+ if (chown(tty, pw->pw_uid, gid) == -1) {
if (errno == EROFS &&
(st.st_uid == pw->pw_uid || st.st_uid == 0))
debug("chown(%.100s, %u, %u) failed: %.100s",
@@ -237,7 +204,7 @@ pty_setowner(struct passwd *pw, const char *tty)
}
if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) {
- if (chmod(tty, mode) < 0) {
+ if (chmod(tty, mode) == -1) {
if (errno == EROFS &&
(st.st_mode & (S_IRGRP | S_IROTH)) == 0)
debug("chmod(%.100s, 0%o) failed: %.100s",
@@ -248,3 +215,17 @@ pty_setowner(struct passwd *pw, const char *tty)
}
}
}
+
+/* Disconnect from the controlling tty. */
+void
+disconnect_controlling_tty(void)
+{
+#ifdef TIOCNOTTY
+ int fd;
+
+ if ((fd = open(_PATH_TTY, O_RDWR | O_NOCTTY)) >= 0) {
+ (void) ioctl(fd, TIOCNOTTY, NULL);
+ close(fd);
+ }
+#endif /* TIOCNOTTY */
+}
diff --git a/sshpty.h b/sshpty.h
index cfa32248..9ec7e9a1 100644
--- a/sshpty.h
+++ b/sshpty.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshpty.h,v 1.12 2010/01/09 05:04:24 djm Exp $ */
+/* $OpenBSD: sshpty.h,v 1.13 2016/11/29 03:54:50 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -25,3 +25,4 @@ void pty_release(const char *);
void pty_make_controlling_tty(int *, const char *);
void pty_change_window_size(int, u_int, u_int, u_int, u_int);
void pty_setowner(struct passwd *, const char *);
+void disconnect_controlling_tty(void);
diff --git a/sshsig.c b/sshsig.c
new file mode 100644
index 00000000..15f9cead
--- /dev/null
+++ b/sshsig.c
@@ -0,0 +1,1041 @@
+/*
+ * Copyright (c) 2019 Google LLC
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "authfd.h"
+#include "authfile.h"
+#include "log.h"
+#include "misc.h"
+#include "sshbuf.h"
+#include "sshsig.h"
+#include "ssherr.h"
+#include "sshkey.h"
+#include "match.h"
+#include "digest.h"
+
+#define SIG_VERSION 0x01
+#define MAGIC_PREAMBLE "SSHSIG"
+#define MAGIC_PREAMBLE_LEN (sizeof(MAGIC_PREAMBLE) - 1)
+#define BEGIN_SIGNATURE "-----BEGIN SSH SIGNATURE-----\n"
+#define END_SIGNATURE "-----END SSH SIGNATURE-----"
+#define RSA_SIGN_ALG "rsa-sha2-512" /* XXX maybe make configurable */
+#define RSA_SIGN_ALLOWED "rsa-sha2-512,rsa-sha2-256"
+#define HASHALG_DEFAULT "sha512" /* XXX maybe make configurable */
+#define HASHALG_ALLOWED "sha256,sha512"
+
+int
+sshsig_armor(const struct sshbuf *blob, struct sshbuf **out)
+{
+ struct sshbuf *buf = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ *out = NULL;
+
+ if ((buf = sshbuf_new()) == NULL) {
+ error("%s: sshbuf_new failed", __func__);
+ 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));
+ goto out;
+ }
+
+ if ((r = sshbuf_dtob64(blob, buf, 1)) != 0) {
+ error("%s: Couldn't base64 encode signature blob: %s",
+ __func__, ssh_err(r));
+ 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));
+ goto out;
+ }
+ /* success */
+ *out = buf;
+ buf = NULL; /* transferred */
+ r = 0;
+ out:
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out)
+{
+ int r;
+ size_t eoffset = 0;
+ struct sshbuf *buf = NULL;
+ struct sshbuf *sbuf = NULL;
+ char *b64 = NULL;
+
+ if ((sbuf = sshbuf_fromb(sig)) == NULL) {
+ error("%s: sshbuf_fromb failed", __func__);
+ return SSH_ERR_ALLOC_FAIL;
+ }
+
+ if ((r = sshbuf_cmp(sbuf, 0,
+ BEGIN_SIGNATURE, sizeof(BEGIN_SIGNATURE)-1)) != 0) {
+ error("Couldn't parse signature: missing header");
+ goto done;
+ }
+
+ if ((r = sshbuf_consume(sbuf, sizeof(BEGIN_SIGNATURE)-1)) != 0) {
+ error("%s: sshbuf_consume failed: %s", __func__, ssh_err(r));
+ goto done;
+ }
+
+ if ((r = sshbuf_find(sbuf, 0, "\n" END_SIGNATURE,
+ sizeof("\n" END_SIGNATURE)-1, &eoffset)) != 0) {
+ error("Couldn't parse signature: missing footer");
+ goto done;
+ }
+
+ if ((r = sshbuf_consume_end(sbuf, sshbuf_len(sbuf)-eoffset)) != 0) {
+ error("%s: sshbuf_consume failed: %s", __func__, ssh_err(r));
+ goto done;
+ }
+
+ if ((b64 = sshbuf_dup_string(sbuf)) == NULL) {
+ error("%s: sshbuf_dup_string failed", __func__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto done;
+ }
+
+ if ((buf = sshbuf_new()) == NULL) {
+ error("%s: sshbuf_new() failed", __func__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto done;
+ }
+
+ if ((r = sshbuf_b64tod(buf, b64)) != 0) {
+ error("Couldn't decode signature: %s", ssh_err(r));
+ goto done;
+ }
+
+ /* success */
+ *out = buf;
+ r = 0;
+ buf = NULL; /* transferred */
+done:
+ sshbuf_free(buf);
+ sshbuf_free(sbuf);
+ free(b64);
+ return r;
+}
+
+static int
+sshsig_wrap_sign(struct sshkey *key, const char *hashalg,
+ const char *sk_provider, const struct sshbuf *h_message,
+ const char *sig_namespace, struct sshbuf **out,
+ sshsig_signer *signer, void *signer_ctx)
+{
+ int r;
+ size_t slen = 0;
+ u_char *sig = NULL;
+ struct sshbuf *blob = NULL;
+ struct sshbuf *tosign = NULL;
+ const char *sign_alg = NULL;
+
+ if ((tosign = sshbuf_new()) == NULL ||
+ (blob = sshbuf_new()) == NULL) {
+ error("%s: sshbuf_new failed", __func__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto done;
+ }
+
+ if ((r = sshbuf_put(tosign, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 ||
+ (r = sshbuf_put_cstring(tosign, sig_namespace)) != 0 ||
+ (r = sshbuf_put_string(tosign, NULL, 0)) != 0 || /* reserved */
+ (r = sshbuf_put_cstring(tosign, hashalg)) != 0 ||
+ (r = sshbuf_put_stringb(tosign, h_message)) != 0) {
+ error("Couldn't construct message to sign: %s", ssh_err(r));
+ goto done;
+ }
+
+ /* If using RSA keys then default to a good signature algorithm */
+ if (sshkey_type_plain(key->type) == KEY_RSA)
+ sign_alg = RSA_SIGN_ALG;
+
+ if (signer != NULL) {
+ if ((r = signer(key, &sig, &slen,
+ sshbuf_ptr(tosign), sshbuf_len(tosign),
+ sign_alg, sk_provider, 0, signer_ctx)) != 0) {
+ error("Couldn't sign message: %s", ssh_err(r));
+ 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));
+ goto done;
+ }
+ }
+
+ if ((r = sshbuf_put(blob, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 ||
+ (r = sshbuf_put_u32(blob, SIG_VERSION)) != 0 ||
+ (r = sshkey_puts(key, blob)) != 0 ||
+ (r = sshbuf_put_cstring(blob, sig_namespace)) != 0 ||
+ (r = sshbuf_put_string(blob, NULL, 0)) != 0 || /* reserved */
+ (r = sshbuf_put_cstring(blob, hashalg)) != 0 ||
+ (r = sshbuf_put_string(blob, sig, slen)) != 0) {
+ error("Couldn't populate blob: %s", ssh_err(r));
+ goto done;
+ }
+
+ if (out != NULL) {
+ *out = blob;
+ blob = NULL;
+ }
+ r = 0;
+done:
+ free(sig);
+ sshbuf_free(blob);
+ sshbuf_free(tosign);
+ return r;
+}
+
+/* Check preamble and version. */
+static int
+sshsig_parse_preamble(struct sshbuf *buf)
+{
+ int r = SSH_ERR_INTERNAL_ERROR;
+ uint32_t sversion;
+
+ if ((r = sshbuf_cmp(buf, 0, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 ||
+ (r = sshbuf_consume(buf, (sizeof(MAGIC_PREAMBLE)-1))) != 0 ||
+ (r = sshbuf_get_u32(buf, &sversion)) != 0) {
+ error("Couldn't verify signature: invalid format");
+ return r;
+ }
+
+ if (sversion > SIG_VERSION) {
+ error("Signature version %lu is larger than supported "
+ "version %u", (unsigned long)sversion, SIG_VERSION);
+ return SSH_ERR_INVALID_FORMAT;
+ }
+ return 0;
+}
+
+static int
+sshsig_check_hashalg(const char *hashalg)
+{
+ if (hashalg == NULL ||
+ match_pattern_list(hashalg, HASHALG_ALLOWED, 0) == 1)
+ return 0;
+ error("%s: unsupported hash algorithm \"%.100s\"", __func__, hashalg);
+ return SSH_ERR_SIGN_ALG_UNSUPPORTED;
+}
+
+static int
+sshsig_peek_hashalg(struct sshbuf *signature, char **hashalgp)
+{
+ struct sshbuf *buf = NULL;
+ char *hashalg = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if (hashalgp != NULL)
+ *hashalgp = NULL;
+ if ((buf = sshbuf_fromb(signature)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((r = sshsig_parse_preamble(buf)) != 0)
+ goto done;
+ if ((r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0 ||
+ (r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0 ||
+ (r = sshbuf_get_string(buf, NULL, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(buf, &hashalg, NULL)) != 0 ||
+ (r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0) {
+ error("Couldn't parse signature blob: %s", ssh_err(r));
+ goto done;
+ }
+
+ /* success */
+ r = 0;
+ *hashalgp = hashalg;
+ hashalg = NULL;
+ done:
+ free(hashalg);
+ sshbuf_free(buf);
+ return r;
+}
+
+static int
+sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
+ const struct sshbuf *h_message, const char *expect_namespace,
+ struct sshkey **sign_keyp, struct sshkey_sig_details **sig_details)
+{
+ int r = SSH_ERR_INTERNAL_ERROR;
+ struct sshbuf *buf = NULL, *toverify = NULL;
+ struct sshkey *key = NULL;
+ const u_char *sig;
+ char *got_namespace = NULL, *sigtype = NULL, *sig_hashalg = NULL;
+ size_t siglen;
+
+ debug("%s: verify message length %zu", __func__, 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__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto done;
+ }
+ if ((r = sshbuf_put(toverify, MAGIC_PREAMBLE,
+ MAGIC_PREAMBLE_LEN)) != 0 ||
+ (r = sshbuf_put_cstring(toverify, expect_namespace)) != 0 ||
+ (r = sshbuf_put_string(toverify, NULL, 0)) != 0 || /* reserved */
+ (r = sshbuf_put_cstring(toverify, hashalg)) != 0 ||
+ (r = sshbuf_put_stringb(toverify, h_message)) != 0) {
+ error("Couldn't construct message to verify: %s", ssh_err(r));
+ goto done;
+ }
+
+ if ((r = sshsig_parse_preamble(signature)) != 0)
+ goto done;
+
+ if ((r = sshkey_froms(signature, &key)) != 0 ||
+ (r = sshbuf_get_cstring(signature, &got_namespace, NULL)) != 0 ||
+ (r = sshbuf_get_string(signature, NULL, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(signature, &sig_hashalg, NULL)) != 0 ||
+ (r = sshbuf_get_string_direct(signature, &sig, &siglen)) != 0) {
+ error("Couldn't parse signature blob: %s", ssh_err(r));
+ goto done;
+ }
+
+ if (sshbuf_len(signature) != 0) {
+ error("Signature contains trailing data");
+ r = SSH_ERR_INVALID_FORMAT;
+ goto done;
+ }
+
+ if (strcmp(expect_namespace, got_namespace) != 0) {
+ error("Couldn't verify signature: namespace does not match");
+ debug("%s: expected namespace \"%s\" received \"%s\"",
+ __func__, 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);
+ 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));
+ goto done;
+ }
+ if (match_pattern_list(sigtype, RSA_SIGN_ALLOWED, 0) != 1) {
+ error("Couldn't verify signature: unsupported RSA "
+ "signature algorithm %s", sigtype);
+ r = SSH_ERR_SIGN_ALG_UNSUPPORTED;
+ goto done;
+ }
+ }
+ if ((r = sshkey_verify(key, sig, siglen, sshbuf_ptr(toverify),
+ sshbuf_len(toverify), NULL, 0, sig_details)) != 0) {
+ error("Signature verification failed: %s", ssh_err(r));
+ goto done;
+ }
+
+ /* success */
+ r = 0;
+ if (sign_keyp != NULL) {
+ *sign_keyp = key;
+ key = NULL; /* transferred */
+ }
+done:
+ free(got_namespace);
+ free(sigtype);
+ free(sig_hashalg);
+ sshbuf_free(buf);
+ sshbuf_free(toverify);
+ sshkey_free(key);
+ return r;
+}
+
+static int
+hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp)
+{
+ char *hex, hash[SSH_DIGEST_MAX_LENGTH];
+ int alg, r = SSH_ERR_INTERNAL_ERROR;
+ struct sshbuf *b = NULL;
+
+ *bp = NULL;
+ memset(hash, 0, sizeof(hash));
+
+ if ((r = sshsig_check_hashalg(hashalg)) != 0)
+ return r;
+ if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
+ error("%s: can't look up hash algorithm %s",
+ __func__, 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));
+ return r;
+ }
+ if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) {
+ debug3("%s: final hash: %s", __func__, hex);
+ freezero(hex, strlen(hex));
+ }
+ if ((b = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) {
+ error("%s: sshbuf_put: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ *bp = b;
+ b = NULL; /* transferred */
+ /* success */
+ r = 0;
+ out:
+ sshbuf_free(b);
+ explicit_bzero(hash, sizeof(hash));
+ return r;
+}
+
+int
+sshsig_signb(struct sshkey *key, const char *hashalg, const char *sk_provider,
+ const struct sshbuf *message, const char *sig_namespace,
+ struct sshbuf **out, sshsig_signer *signer, void *signer_ctx)
+{
+ struct sshbuf *b = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if (hashalg == NULL)
+ hashalg = HASHALG_DEFAULT;
+ if (out != NULL)
+ *out = NULL;
+ if ((r = hash_buffer(message, hashalg, &b)) != 0) {
+ error("%s: hash_buffer failed: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, b,
+ sig_namespace, out, signer, signer_ctx)) != 0)
+ goto out;
+ /* success */
+ r = 0;
+ out:
+ sshbuf_free(b);
+ return r;
+}
+
+int
+sshsig_verifyb(struct sshbuf *signature, const struct sshbuf *message,
+ const char *expect_namespace, struct sshkey **sign_keyp,
+ struct sshkey_sig_details **sig_details)
+{
+ struct sshbuf *b = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ char *hashalg = NULL;
+
+ if (sig_details != NULL)
+ *sig_details = NULL;
+ if (sign_keyp != NULL)
+ *sign_keyp = NULL;
+ if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
+ return r;
+ debug("%s: signature made with hash \"%s\"", __func__, hashalg);
+ if ((r = hash_buffer(message, hashalg, &b)) != 0) {
+ error("%s: hash_buffer failed: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
+ sign_keyp, sig_details)) != 0)
+ goto out;
+ /* success */
+ r = 0;
+ out:
+ sshbuf_free(b);
+ free(hashalg);
+ return r;
+}
+
+static int
+hash_file(int fd, const char *hashalg, struct sshbuf **bp)
+{
+ char *hex, rbuf[8192], hash[SSH_DIGEST_MAX_LENGTH];
+ ssize_t n, total = 0;
+ struct ssh_digest_ctx *ctx;
+ int alg, oerrno, r = SSH_ERR_INTERNAL_ERROR;
+ struct sshbuf *b = NULL;
+
+ *bp = NULL;
+ memset(hash, 0, sizeof(hash));
+
+ if ((r = sshsig_check_hashalg(hashalg)) != 0)
+ return r;
+ if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
+ error("%s: can't look up hash algorithm %s",
+ __func__, hashalg);
+ return SSH_ERR_INTERNAL_ERROR;
+ }
+ if ((ctx = ssh_digest_start(alg)) == NULL) {
+ error("%s: ssh_digest_start failed", __func__);
+ return SSH_ERR_INTERNAL_ERROR;
+ }
+ for (;;) {
+ if ((n = read(fd, rbuf, sizeof(rbuf))) == -1) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ oerrno = errno;
+ error("%s: read: %s", __func__, 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);
+ 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));
+ goto out;
+ }
+ }
+ if ((r = ssh_digest_final(ctx, hash, sizeof(hash))) != 0) {
+ error("%s: ssh_digest_final: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) {
+ debug3("%s: final hash: %s", __func__, hex);
+ freezero(hex, strlen(hex));
+ }
+ if ((b = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) {
+ error("%s: sshbuf_put: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ *bp = b;
+ b = NULL; /* transferred */
+ /* success */
+ r = 0;
+ out:
+ sshbuf_free(b);
+ ssh_digest_free(ctx);
+ explicit_bzero(hash, sizeof(hash));
+ return r;
+}
+
+int
+sshsig_sign_fd(struct sshkey *key, const char *hashalg, const char *sk_provider,
+ int fd, const char *sig_namespace, struct sshbuf **out,
+ sshsig_signer *signer, void *signer_ctx)
+{
+ struct sshbuf *b = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if (hashalg == NULL)
+ hashalg = HASHALG_DEFAULT;
+ if (out != NULL)
+ *out = NULL;
+ if ((r = hash_file(fd, hashalg, &b)) != 0) {
+ error("%s: hash_file failed: %s", __func__, ssh_err(r));
+ return r;
+ }
+ if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, b,
+ sig_namespace, out, signer, signer_ctx)) != 0)
+ goto out;
+ /* success */
+ r = 0;
+ out:
+ sshbuf_free(b);
+ return r;
+}
+
+int
+sshsig_verify_fd(struct sshbuf *signature, int fd,
+ const char *expect_namespace, struct sshkey **sign_keyp,
+ struct sshkey_sig_details **sig_details)
+{
+ struct sshbuf *b = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ char *hashalg = NULL;
+
+ if (sig_details != NULL)
+ *sig_details = NULL;
+ if (sign_keyp != NULL)
+ *sign_keyp = NULL;
+ if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
+ return r;
+ debug("%s: signature made with hash \"%s\"", __func__, hashalg);
+ if ((r = hash_file(fd, hashalg, &b)) != 0) {
+ error("%s: hash_file failed: %s", __func__, ssh_err(r));
+ goto out;
+ }
+ if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
+ sign_keyp, sig_details)) != 0)
+ goto out;
+ /* success */
+ r = 0;
+ out:
+ sshbuf_free(b);
+ free(hashalg);
+ return r;
+}
+
+struct sshsigopt {
+ int ca;
+ char *namespaces;
+};
+
+struct sshsigopt *
+sshsigopt_parse(const char *opts, const char *path, u_long linenum,
+ const char **errstrp)
+{
+ struct sshsigopt *ret;
+ int r;
+ const char *errstr = NULL;
+
+ if ((ret = calloc(1, sizeof(*ret))) == NULL)
+ return NULL;
+ if (opts == NULL || *opts == '\0')
+ return ret; /* Empty options yields empty options :) */
+
+ while (*opts && *opts != ' ' && *opts != '\t') {
+ /* flag options */
+ if ((r = opt_flag("cert-authority", 0, &opts)) != -1) {
+ ret->ca = 1;
+ } else if (opt_match(&opts, "namespaces")) {
+ if (ret->namespaces != NULL) {
+ errstr = "multiple \"namespaces\" clauses";
+ goto fail;
+ }
+ ret->namespaces = opt_dequote(&opts, &errstr);
+ if (ret->namespaces == NULL)
+ goto fail;
+ }
+ /*
+ * Skip the comma, and move to the next option
+ * (or break out if there are no more).
+ */
+ if (*opts == '\0' || *opts == ' ' || *opts == '\t')
+ break; /* End of options. */
+ /* Anything other than a comma is an unknown option */
+ if (*opts != ',') {
+ errstr = "unknown key option";
+ goto fail;
+ }
+ opts++;
+ if (*opts == '\0') {
+ errstr = "unexpected end-of-options";
+ goto fail;
+ }
+ }
+ /* success */
+ return ret;
+ fail:
+ if (errstrp != NULL)
+ *errstrp = errstr;
+ sshsigopt_free(ret);
+ return NULL;
+}
+
+void
+sshsigopt_free(struct sshsigopt *opts)
+{
+ if (opts == NULL)
+ return;
+ free(opts->namespaces);
+ free(opts);
+}
+
+static int
+parse_principals_key_and_options(const char *path, u_long linenum, char *line,
+ const char *required_principal, char **principalsp, struct sshkey **keyp,
+ struct sshsigopt **sigoptsp)
+{
+ char *opts = NULL, *tmp, *cp, *principals = NULL;
+ const char *reason = NULL;
+ struct sshsigopt *sigopts = NULL;
+ struct sshkey *key = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if (principalsp != NULL)
+ *principalsp = NULL;
+ if (sigoptsp != NULL)
+ *sigoptsp = NULL;
+ if (keyp != NULL)
+ *keyp = NULL;
+
+ cp = line;
+ cp = cp + strspn(cp, " \t"); /* skip leading whitespace */
+ if (*cp == '#' || *cp == '\0')
+ return SSH_ERR_KEY_NOT_FOUND; /* blank or all-comment line */
+
+ /* format: identity[,identity...] [option[,option...]] key */
+ if ((tmp = strdelimw(&cp)) == NULL) {
+ error("%s:%lu: invalid line", path, linenum);
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if ((principals = strdup(tmp)) == NULL) {
+ error("%s: strdup failed", __func__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ /*
+ * Bail out early if we're looking for a particular principal and this
+ * line does not list it.
+ */
+ if (required_principal != NULL) {
+ if (match_pattern_list(required_principal,
+ principals, 0) != 1) {
+ /* principal didn't match */
+ r = SSH_ERR_KEY_NOT_FOUND;
+ goto out;
+ }
+ debug("%s: %s:%lu: matched principal \"%s\"",
+ __func__, path, linenum, required_principal);
+ }
+
+ if ((key = sshkey_new(KEY_UNSPEC)) == NULL) {
+ error("%s: sshkey_new failed", __func__);
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (sshkey_read(key, &cp) != 0) {
+ /* no key? Check for options */
+ opts = cp;
+ if (sshkey_advance_past_options(&cp) != 0) {
+ error("%s:%lu: invalid options", path, linenum);
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ *cp++ = '\0';
+ skip_space(&cp);
+ if (sshkey_read(key, &cp) != 0) {
+ error("%s:%lu: invalid key", path, linenum);
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ }
+ debug3("%s:%lu: options %s", path, linenum, opts == NULL ? "" : opts);
+ if ((sigopts = sshsigopt_parse(opts, path, linenum, &reason)) == NULL) {
+ error("%s:%lu: bad options: %s", path, linenum, reason);
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ /* success */
+ if (principalsp != NULL) {
+ *principalsp = principals;
+ principals = NULL; /* transferred */
+ }
+ if (sigoptsp != NULL) {
+ *sigoptsp = sigopts;
+ sigopts = NULL; /* transferred */
+ }
+ if (keyp != NULL) {
+ *keyp = key;
+ key = NULL; /* transferred */
+ }
+ r = 0;
+ out:
+ free(principals);
+ sshsigopt_free(sigopts);
+ sshkey_free(key);
+ return r;
+}
+
+static int
+check_allowed_keys_line(const char *path, u_long linenum, char *line,
+ const struct sshkey *sign_key, const char *principal,
+ const char *sig_namespace)
+{
+ struct sshkey *found_key = NULL;
+ int r, found = 0;
+ const char *reason = NULL;
+ struct sshsigopt *sigopts = NULL;
+
+ /* Parse the line */
+ if ((r = parse_principals_key_and_options(path, linenum, line,
+ principal, NULL, &found_key, &sigopts)) != 0) {
+ /* error already logged */
+ goto done;
+ }
+
+ /* 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;
+ } 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) {
+ 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 */
+ goto done;
+ }
+ done:
+ sshkey_free(found_key);
+ sshsigopt_free(sigopts);
+ return found ? 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)
+{
+ FILE *f = NULL;
+ char *line = NULL;
+ size_t linesize = 0;
+ u_long linenum = 0;
+ int r = SSH_ERR_INTERNAL_ERROR, oerrno;
+
+ /* Check key and principal against file */
+ if ((f = fopen(path, "r")) == NULL) {
+ oerrno = errno;
+ error("Unable to open allowed keys file \"%s\": %s",
+ path, strerror(errno));
+ errno = oerrno;
+ return SSH_ERR_SYSTEM_ERROR;
+ }
+
+ while (getline(&line, &linesize, f) != -1) {
+ linenum++;
+ r = check_allowed_keys_line(path, linenum, line, sign_key,
+ principal, sig_namespace);
+ free(line);
+ line = NULL;
+ if (r == SSH_ERR_KEY_NOT_FOUND)
+ continue;
+ else if (r == 0) {
+ /* success */
+ fclose(f);
+ return 0;
+ } else
+ break;
+ }
+ /* Either we hit an error parsing or we simply didn't find the key */
+ fclose(f);
+ free(line);
+ return r == 0 ? SSH_ERR_KEY_NOT_FOUND : r;
+}
+
+static int
+cert_filter_principals(const char *path, u_long linenum,
+ char **principalsp, const struct sshkey *cert)
+{
+ char *cp, *oprincipals, *principals;
+ const char *reason;
+ struct sshbuf *nprincipals;
+ int r = SSH_ERR_INTERNAL_ERROR, success = 0;
+
+ oprincipals = principals = *principalsp;
+ *principalsp = NULL;
+
+ if ((nprincipals = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ while ((cp = strsep(&principals, ",")) != NULL && *cp != '\0') {
+ if (strcspn(cp, "!?*") != strlen(cp)) {
+ debug("%s:%lu: principal \"%s\" not authorized: "
+ "contains wildcards", path, linenum, cp);
+ continue;
+ }
+ /* Check against principals list in certificate */
+ if ((r = sshkey_cert_check_authority(cert, 0, 1,
+ 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__);
+ goto out;
+ }
+ }
+ if (sshbuf_len(nprincipals) == 0) {
+ error("%s:%lu: no valid principals found", path, linenum);
+ r = SSH_ERR_KEY_CERT_INVALID;
+ goto out;
+ }
+ if ((principals = sshbuf_dup_string(nprincipals)) == NULL) {
+ error("%s: buffer error", __func__);
+ goto out;
+ }
+ /* success */
+ success = 1;
+ *principalsp = principals;
+ out:
+ sshbuf_free(nprincipals);
+ free(oprincipals);
+ return success ? 0 : r;
+}
+
+static int
+get_matching_principals_from_line(const char *path, u_long linenum, char *line,
+ const struct sshkey *sign_key, char **principalsp)
+{
+ struct sshkey *found_key = NULL;
+ char *principals = NULL;
+ int r, found = 0;
+ struct sshsigopt *sigopts = NULL;
+
+ if (principalsp != NULL)
+ *principalsp = NULL;
+
+ /* Parse the line */
+ if ((r = parse_principals_key_and_options(path, linenum, line,
+ NULL, &principals, &found_key, &sigopts)) != 0) {
+ /* error already logged */
+ goto done;
+ }
+
+ if (!sigopts->ca && sshkey_equal(found_key, sign_key)) {
+ /* Exact match of key */
+ debug("%s:%lu: matched key", path, linenum);
+ /* success */
+ found = 1;
+ } else if (sigopts->ca && sshkey_is_cert(sign_key) &&
+ sshkey_equal_public(sign_key->cert->signature_key, found_key)) {
+ /* Remove principals listed in file but not allowed by cert */
+ if ((r = cert_filter_principals(path, linenum,
+ &principals, sign_key)) != 0) {
+ /* error already displayed */
+ debug("%s:%lu: cert_filter_principals: %s",
+ path, linenum, ssh_err(r));
+ goto done;
+ }
+ debug("%s:%lu: matched certificate CA key", path, linenum);
+ /* success */
+ found = 1;
+ } else {
+ /* Key didn't match */
+ goto done;
+ }
+ done:
+ if (found && principalsp != NULL) {
+ *principalsp = principals;
+ principals = NULL; /* transferred */
+ }
+ free(principals);
+ sshkey_free(found_key);
+ sshsigopt_free(sigopts);
+ return found ? 0 : SSH_ERR_KEY_NOT_FOUND;
+}
+
+int
+sshsig_find_principals(const char *path, const struct sshkey *sign_key,
+ char **principals)
+{
+ FILE *f = NULL;
+ char *line = NULL;
+ size_t linesize = 0;
+ u_long linenum = 0;
+ int r = SSH_ERR_INTERNAL_ERROR, oerrno;
+
+ if ((f = fopen(path, "r")) == NULL) {
+ oerrno = errno;
+ error("Unable to open allowed keys file \"%s\": %s",
+ path, strerror(errno));
+ errno = oerrno;
+ return SSH_ERR_SYSTEM_ERROR;
+ }
+
+ while (getline(&line, &linesize, f) != -1) {
+ linenum++;
+ r = get_matching_principals_from_line(path, linenum, line,
+ sign_key, principals);
+ free(line);
+ line = NULL;
+ if (r == SSH_ERR_KEY_NOT_FOUND)
+ continue;
+ else if (r == 0) {
+ /* success */
+ fclose(f);
+ return 0;
+ } else
+ break;
+ }
+ free(line);
+ /* Either we hit an error parsing or we simply didn't find the key */
+ if (ferror(f) != 0) {
+ oerrno = errno;
+ fclose(f);
+ error("Unable to read allowed keys file \"%s\": %s",
+ path, strerror(errno));
+ errno = oerrno;
+ return SSH_ERR_SYSTEM_ERROR;
+ }
+ fclose(f);
+ return r == 0 ? SSH_ERR_KEY_NOT_FOUND : r;
+}
+
+int
+sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey)
+{
+ struct sshkey *pk = NULL;
+ int r = SSH_ERR_SIGNATURE_INVALID;
+
+ if (pubkey == NULL)
+ return SSH_ERR_INTERNAL_ERROR;
+ if ((r = sshsig_parse_preamble(signature)) != 0)
+ return r;
+ if ((r = sshkey_froms(signature, &pk)) != 0)
+ return r;
+
+ *pubkey = pk;
+ pk = NULL;
+ return 0;
+}
diff --git a/sshsig.h b/sshsig.h
new file mode 100644
index 00000000..63cc1ad1
--- /dev/null
+++ b/sshsig.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2019 Google LLC
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SSHSIG_H
+#define SSHSIG_H
+
+struct sshbuf;
+struct sshkey;
+struct sshsigopt;
+struct sshkey_sig_details;
+
+typedef int sshsig_signer(struct sshkey *, u_char **, size_t *,
+ const u_char *, size_t, const char *, const char *, u_int, void *);
+
+/* Buffer-oriented API */
+
+/*
+ * Creates a detached SSH signature for a given buffer.
+ * Returns 0 on success or a negative SSH_ERR_* error code on failure.
+ * 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 *sig_namespace, struct sshbuf **out,
+ sshsig_signer *signer, void *signer_ctx);
+
+/*
+ * Verifies that a detached signature is valid and optionally returns key
+ * used to sign via argument.
+ * Returns 0 on success or a negative SSH_ERR_* error code on failure.
+ */
+int sshsig_verifyb(struct sshbuf *signature,
+ const struct sshbuf *message, const char *sig_namespace,
+ struct sshkey **sign_keyp, struct sshkey_sig_details **sig_details);
+
+/* File/FD-oriented API */
+
+/*
+ * Creates a detached SSH signature for a given file.
+ * Returns 0 on success or a negative SSH_ERR_* error code on failure.
+ * 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,
+ struct sshbuf **out, sshsig_signer *signer, void *signer_ctx);
+
+/*
+ * Verifies that a detached signature over a file is valid and optionally
+ * returns key used to sign via argument.
+ * Returns 0 on success or a negative SSH_ERR_* error code on failure.
+ */
+int sshsig_verify_fd(struct sshbuf *signature, int fd,
+ const char *sig_namespace, struct sshkey **sign_keyp,
+ struct sshkey_sig_details **sig_details);
+
+/* Utility functions */
+
+/*
+ * Return a base64 encoded "ASCII armoured" version of a raw signature.
+ */
+int sshsig_armor(const struct sshbuf *blob, struct sshbuf **out);
+
+/*
+ * Decode a base64 encoded armoured signature to a raw signature.
+ */
+int sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out);
+
+/*
+ * Checks whether a particular key/principal/namespace is permitted by
+ * 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);
+
+/* Parse zero or more allowed_keys signature options */
+struct sshsigopt *sshsigopt_parse(const char *opts,
+ const char *path, u_long linenum, const char **errstrp);
+
+/* Free signature options */
+void sshsigopt_free(struct sshsigopt *opts);
+
+/* Get public key from signature */
+int sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey);
+
+/* Find principal in allowed_keys file, given a sshkey. Returns
+ * 0 on success.
+ */
+int sshsig_find_principals(const char *path, const struct sshkey *sign_key,
+ char **principal);
+
+#endif /* SSHSIG_H */
diff --git a/start-ssh b/start-ssh
index 62d87dae..9a668fae 100644
--- a/start-ssh
+++ b/start-ssh
@@ -9,7 +9,7 @@ DSA_PUB_KEY=/data/ssh/ssh_host_dsa_key.pub
RSA_KEY=/data/ssh/ssh_host_rsa_key
RSA_PUB_KEY=/data/ssh/ssh_host_rsa_key.pub
AUTHORIZED_KEYS=/data/ssh/authorized_keys
-DEFAULT_AUTHORIZED_KEYS=/system/etc/security/authorized_keys.default
+DEFAULT_AUTHORIZED_KEYS=/vendor/etc/security/authorized_keys.default
if [ ! -f $DSA_KEY ]; then
/system/bin/ssh-keygen -t dsa -f $DSA_KEY -N ""
@@ -30,8 +30,8 @@ fi
if [ "1" == "$DEBUG" ] ; then
# run sshd in debug mode and capture output to logcat
- /system/bin/logwrapper /system/bin/sshd -f /system/etc/ssh/sshd_config -D -d
+ /system/bin/logwrapper /system/bin/sshd -f /vendor/etc/ssh/sshd_config -D -d
else
# don't daemonize - otherwise we can't stop the sshd service
- /system/bin/sshd -f /system/etc/ssh/sshd_config -D
+ /system/bin/sshd -f /vendor/etc/ssh/sshd_config -D
fi
diff --git a/ttymodes.c b/ttymodes.c
index 6f51b8a7..f0c2a5d3 100644
--- a/ttymodes.c
+++ b/ttymodes.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ttymodes.c,v 1.29 2008/11/02 00:16:16 stevesk Exp $ */
+/* $OpenBSD: ttymodes.c,v 1.34 2018/07/09 21:20:26 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -54,18 +54,16 @@
#include "packet.h"
#include "log.h"
-#include "ssh1.h"
#include "compat.h"
-#include "buffer.h"
+#include "sshbuf.h"
+#include "ssherr.h"
#define TTY_OP_END 0
/*
- * uint32 (u_int) follows speed in SSH1 and SSH2
+ * uint32 (u_int) follows speed.
*/
-#define TTY_OP_ISPEED_PROTO1 192
-#define TTY_OP_OSPEED_PROTO1 193
-#define TTY_OP_ISPEED_PROTO2 128
-#define TTY_OP_OSPEED_PROTO2 129
+#define TTY_OP_ISPEED 128
+#define TTY_OP_OSPEED 129
/*
* Converts POSIX speed_t to a baud rate. The values of the
@@ -278,28 +276,18 @@ special_char_decode(u_int c)
* being constructed.
*/
void
-tty_make_modes(int fd, struct termios *tiop)
+ssh_tty_make_modes(struct ssh *ssh, int fd, struct termios *tiop)
{
struct termios tio;
- int baud;
- Buffer buf;
- int tty_op_ospeed, tty_op_ispeed;
- void (*put_arg)(Buffer *, u_int);
-
- buffer_init(&buf);
- if (compat20) {
- tty_op_ospeed = TTY_OP_OSPEED_PROTO2;
- tty_op_ispeed = TTY_OP_ISPEED_PROTO2;
- put_arg = buffer_put_int;
- } else {
- tty_op_ospeed = TTY_OP_OSPEED_PROTO1;
- tty_op_ispeed = TTY_OP_ISPEED_PROTO1;
- put_arg = (void (*)(Buffer *, u_int)) buffer_put_char;
- }
+ struct sshbuf *buf;
+ int r, ibaud, obaud;
+
+ if ((buf = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
if (tiop == NULL) {
if (fd == -1) {
- debug("tty_make_modes: no fd or tio");
+ debug("%s: no fd or tio", __func__);
goto end;
}
if (tcgetattr(fd, &tio) == -1) {
@@ -310,21 +298,29 @@ tty_make_modes(int fd, struct termios *tiop)
tio = *tiop;
/* Store input and output baud rates. */
- baud = speed_to_baud(cfgetospeed(&tio));
- buffer_put_char(&buf, tty_op_ospeed);
- buffer_put_int(&buf, baud);
- baud = speed_to_baud(cfgetispeed(&tio));
- buffer_put_char(&buf, tty_op_ispeed);
- buffer_put_int(&buf, baud);
+ obaud = speed_to_baud(cfgetospeed(&tio));
+ ibaud = speed_to_baud(cfgetispeed(&tio));
+ if ((r = sshbuf_put_u8(buf, TTY_OP_OSPEED)) != 0 ||
+ (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));
/* Store values of mode flags. */
#define TTYCHAR(NAME, OP) \
- buffer_put_char(&buf, OP); \
- put_arg(&buf, special_char_encode(tio.c_cc[NAME]));
+ 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)); \
+
+#define SSH_TTYMODE_IUTF8 42 /* for SSH_BUG_UTF8TTYMODE */
#define TTYMODE(NAME, FIELD, OP) \
- buffer_put_char(&buf, OP); \
- put_arg(&buf, ((tio.FIELD & NAME) != 0));
+ if (OP == SSH_TTYMODE_IUTF8 && (datafellows & SSH_BUG_UTF8TTYMODE)) { \
+ debug3("%s: SSH_BUG_UTF8TTYMODE", __func__); \
+ } 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)); \
#include "ttymodes.h"
@@ -333,12 +329,10 @@ tty_make_modes(int fd, struct termios *tiop)
end:
/* Mark end of mode data. */
- buffer_put_char(&buf, TTY_OP_END);
- if (compat20)
- packet_put_string(buffer_ptr(&buf), buffer_len(&buf));
- else
- packet_put_raw(buffer_ptr(&buf), buffer_len(&buf));
- buffer_free(&buf);
+ 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));
+ sshbuf_free(buf);
}
/*
@@ -346,24 +340,23 @@ end:
* manner from a packet being read.
*/
void
-tty_parse_modes(int fd, int *n_bytes_ptr)
+ssh_tty_parse_modes(struct ssh *ssh, int fd)
{
struct termios tio;
- int opcode, baud;
- int n_bytes = 0;
- int failure = 0;
- u_int (*get_arg)(void);
- int arg_size;
-
- if (compat20) {
- *n_bytes_ptr = packet_get_int();
- if (*n_bytes_ptr == 0)
- return;
- get_arg = packet_get_int;
- arg_size = 4;
- } else {
- get_arg = packet_get_char;
- arg_size = 1;
+ struct sshbuf *buf;
+ const u_char *data;
+ u_char opcode;
+ u_int baud, u;
+ int r, failure = 0;
+ size_t len;
+
+ if ((r = sshpkt_get_string_direct(ssh, &data, &len)) != 0)
+ fatal("%s: packet error: %s", __func__, ssh_err(r));
+ if (len == 0)
+ return;
+ if ((buf = sshbuf_from(data, len)) == NULL) {
+ error("%s: sshbuf_from failed", __func__);
+ return;
}
/*
@@ -376,46 +369,48 @@ tty_parse_modes(int fd, int *n_bytes_ptr)
failure = -1;
}
- for (;;) {
- n_bytes += 1;
- opcode = packet_get_char();
+ while (sshbuf_len(buf) > 0) {
+ if ((r = sshbuf_get_u8(buf, &opcode)) != 0)
+ fatal("%s: packet error: %s", __func__, ssh_err(r));
switch (opcode) {
case TTY_OP_END:
goto set;
- /* XXX: future conflict possible */
- case TTY_OP_ISPEED_PROTO1:
- case TTY_OP_ISPEED_PROTO2:
- n_bytes += 4;
- baud = packet_get_int();
+ case TTY_OP_ISPEED:
+ if ((r = sshbuf_get_u32(buf, &baud)) != 0)
+ fatal("%s: packet error: %s",
+ __func__, ssh_err(r));
if (failure != -1 &&
cfsetispeed(&tio, baud_to_speed(baud)) == -1)
error("cfsetispeed failed for %d", baud);
break;
- /* XXX: future conflict possible */
- case TTY_OP_OSPEED_PROTO1:
- case TTY_OP_OSPEED_PROTO2:
- n_bytes += 4;
- baud = packet_get_int();
+ case TTY_OP_OSPEED:
+ if ((r = sshbuf_get_u32(buf, &baud)) != 0)
+ fatal("%s: packet error: %s",
+ __func__, ssh_err(r));
if (failure != -1 &&
cfsetospeed(&tio, baud_to_speed(baud)) == -1)
error("cfsetospeed failed for %d", baud);
break;
#define TTYCHAR(NAME, OP) \
- case OP: \
- n_bytes += arg_size; \
- tio.c_cc[NAME] = special_char_decode(get_arg()); \
- break;
+ case OP: \
+ if ((r = sshbuf_get_u32(buf, &u)) != 0) \
+ fatal("%s: packet error: %s", __func__, \
+ ssh_err(r)); \
+ tio.c_cc[NAME] = special_char_decode(u); \
+ break;
#define TTYMODE(NAME, FIELD, OP) \
- case OP: \
- n_bytes += arg_size; \
- if (get_arg()) \
- tio.FIELD |= NAME; \
- else \
- tio.FIELD &= ~NAME; \
- break;
+ case OP: \
+ if ((r = sshbuf_get_u32(buf, &u)) != 0) \
+ fatal("%s: packet error: %s", __func__, \
+ ssh_err(r)); \
+ if (u) \
+ tio.FIELD |= NAME; \
+ else \
+ tio.FIELD &= ~NAME; \
+ break;
#include "ttymodes.h"
@@ -425,60 +420,31 @@ tty_parse_modes(int fd, int *n_bytes_ptr)
default:
debug("Ignoring unsupported tty mode opcode %d (0x%x)",
opcode, opcode);
- if (!compat20) {
- /*
- * SSH1:
- * Opcodes 1 to 127 are defined to have
- * a one-byte argument.
- * Opcodes 128 to 159 are defined to have
- * an integer argument.
- */
- if (opcode > 0 && opcode < 128) {
- n_bytes += 1;
- (void) packet_get_char();
- break;
- } else if (opcode >= 128 && opcode < 160) {
- n_bytes += 4;
- (void) packet_get_int();
- break;
- } else {
- /*
- * It is a truly undefined opcode (160 to 255).
- * We have no idea about its arguments. So we
- * must stop parsing. Note that some data
- * may be left in the packet; hopefully there
- * is nothing more coming after the mode data.
- */
- logit("parse_tty_modes: unknown opcode %d",
- opcode);
- goto set;
- }
+ /*
+ * SSH2:
+ * Opcodes 1 to 159 are defined to have a uint32
+ * argument.
+ * Opcodes 160 to 255 are undefined and cause parsing
+ * to stop.
+ */
+ if (opcode > 0 && opcode < 160) {
+ if ((r = sshbuf_get_u32(buf, NULL)) != 0)
+ fatal("%s: packet error: %s", __func__,
+ ssh_err(r));
+ break;
} else {
- /*
- * SSH2:
- * Opcodes 1 to 159 are defined to have
- * a uint32 argument.
- * Opcodes 160 to 255 are undefined and
- * cause parsing to stop.
- */
- if (opcode > 0 && opcode < 160) {
- n_bytes += 4;
- (void) packet_get_int();
- break;
- } else {
- logit("parse_tty_modes: unknown opcode %d",
- opcode);
- goto set;
- }
+ logit("%s: unknown opcode %d", __func__,
+ opcode);
+ goto set;
}
}
}
set:
- if (*n_bytes_ptr != n_bytes) {
- *n_bytes_ptr = n_bytes;
- logit("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d",
- *n_bytes_ptr, n_bytes);
+ len = sshbuf_len(buf);
+ sshbuf_free(buf);
+ if (len > 0) {
+ logit("%s: %zu bytes left", __func__, len);
return; /* Don't process bytes passed */
}
if (failure == -1)
diff --git a/ttymodes.h b/ttymodes.h
index 4d848fe3..24f07560 100644
--- a/ttymodes.h
+++ b/ttymodes.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ttymodes.h,v 1.14 2006/03/25 22:22:43 djm Exp $ */
+/* $OpenBSD: ttymodes.h,v 1.16 2017/04/30 23:26:54 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -38,22 +38,13 @@
*/
/*
- * SSH1:
- * The tty mode description is a stream of bytes. The stream consists of
+ * The tty mode description is a string, consisting of
* opcode-arguments pairs. It is terminated by opcode TTY_OP_END (0).
- * Opcodes 1-127 have one-byte arguments. Opcodes 128-159 have integer
- * arguments. Opcodes 160-255 are not yet defined, and cause parsing to
- * stop (they should only be used after any other data).
+ * Opcodes 1-159 have uint32 arguments.
+ * Opcodes 160-255 are not yet defined and cause parsing to stop (they
+ * should only be used after any other data).
*
- * SSH2:
- * Differences between SSH1 and SSH2 terminal mode encoding include:
- * 1. Encoded terminal modes are represented as a string, and a stream
- * of bytes within that string.
- * 2. Opcode arguments are uint32 (1-159); 160-255 remain undefined.
- * 3. The values for TTY_OP_ISPEED and TTY_OP_OSPEED are different;
- * 128 and 129 vs. 192 and 193 respectively.
- *
- * The client puts in the stream any modes it knows about, and the
+ * The client puts in the string any modes it knows about, and the
* server ignores any modes it does not know about. This allows some degree
* of machine-independence, at least between systems that use a posix-like
* tty interface. The protocol can support other systems as well, but might
@@ -127,6 +118,9 @@ TTYMODE(IXOFF, c_iflag, 40)
#ifdef IMAXBEL
TTYMODE(IMAXBEL,c_iflag, 41)
#endif /* IMAXBEL */
+#ifdef IUTF8
+TTYMODE(IUTF8, c_iflag, 42)
+#endif /* IUTF8 */
TTYMODE(ISIG, c_lflag, 50)
TTYMODE(ICANON, c_lflag, 51)
diff --git a/uidswap.c b/uidswap.c
index 19743193..285c5aae 100644
--- a/uidswap.c
+++ b/uidswap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uidswap.c,v 1.37 2015/01/16 06:40:12 deraadt Exp $ */
+/* $OpenBSD: uidswap.c,v 1.42 2019/06/28 13:35:04 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -28,13 +28,18 @@
#include "uidswap.h"
#include "xmalloc.h"
-#ifdef ANDROID
-#include <private/android_filesystem_config.h>
-#if !defined(GCE_PLATFORM_SDK_VERSION) || (GCE_PLATFORM_SDK_VERSION > 17)
+#if defined(ANDROID)
+#define AID_GRAPHICS 1003
+#define AID_INPUT 1004
+#define AID_LOG 1007
+#define AID_MOUNT 1009
+#define AID_SDCARD_RW 1015
+#define AID_SHELL 2000
+#define AID_NET_BT_ADMIN 3001
+#define AID_NET_BT 3002
+#define AID_INET 3003
+#define AID_NET_BW_STATS 3006
#include <sys/capability.h>
-#else
-#include <linux/capability.h>
-#endif
#include <sys/prctl.h>
#endif
@@ -59,6 +64,7 @@ static gid_t saved_egid = 0;
/* Saved effective uid. */
static int privileged = 0;
static int temporarily_use_uid_effective = 0;
+static uid_t user_groups_uid;
static gid_t *saved_egroups = NULL, *user_groups = NULL;
static int saved_egroupslen = -1, user_groupslen = -1;
@@ -93,47 +99,50 @@ temporarily_use_uid(struct passwd *pw)
temporarily_use_uid_effective = 1;
saved_egroupslen = getgroups(0, NULL);
- if (saved_egroupslen < 0)
+ if (saved_egroupslen == -1)
fatal("getgroups: %.100s", strerror(errno));
if (saved_egroupslen > 0) {
- saved_egroups = xrealloc(saved_egroups,
+ saved_egroups = xreallocarray(saved_egroups,
saved_egroupslen, sizeof(gid_t));
- if (getgroups(saved_egroupslen, saved_egroups) < 0)
+ if (getgroups(saved_egroupslen, saved_egroups) == -1)
fatal("getgroups: %.100s", strerror(errno));
} else { /* saved_egroupslen == 0 */
free(saved_egroups);
+ saved_egroups = NULL;
}
/* set and save the user's groups */
- if (user_groupslen == -1) {
- if (initgroups(pw->pw_name, pw->pw_gid) < 0)
+ if (user_groupslen == -1 || user_groups_uid != pw->pw_uid) {
+ if (initgroups(pw->pw_name, pw->pw_gid) == -1)
fatal("initgroups: %s: %.100s", pw->pw_name,
strerror(errno));
user_groupslen = getgroups(0, NULL);
- if (user_groupslen < 0)
+ if (user_groupslen == -1)
fatal("getgroups: %.100s", strerror(errno));
if (user_groupslen > 0) {
- user_groups = xrealloc(user_groups,
+ user_groups = xreallocarray(user_groups,
user_groupslen, sizeof(gid_t));
- if (getgroups(user_groupslen, user_groups) < 0)
+ if (getgroups(user_groupslen, user_groups) == -1)
fatal("getgroups: %.100s", strerror(errno));
} else { /* user_groupslen == 0 */
free(user_groups);
+ user_groups = NULL;
}
+ user_groups_uid = pw->pw_uid;
}
/* Set the effective uid to the given (unprivileged) uid. */
- if (setgroups(user_groupslen, user_groups) < 0)
+ if (setgroups(user_groupslen, user_groups) == -1)
fatal("setgroups: %.100s", strerror(errno));
#ifndef SAVED_IDS_WORK_WITH_SETEUID
/* Propagate the privileged gid to all of our gids. */
- if (setgid(getegid()) < 0)
+ if (setgid(getegid()) == -1)
debug("setgid %u: %.100s", (u_int) getegid(), strerror(errno));
/* Propagate the privileged uid to all of our uids. */
- if (setuid(geteuid()) < 0)
+ if (setuid(geteuid()) == -1)
debug("setuid %u: %.100s", (u_int) geteuid(), strerror(errno));
#endif /* SAVED_IDS_WORK_WITH_SETEUID */
- if (setegid(pw->pw_gid) < 0)
+ if (setegid(pw->pw_gid) == -1)
fatal("setegid %u: %.100s", (u_int)pw->pw_gid,
strerror(errno));
if (seteuid(pw->pw_uid) == -1)
@@ -141,31 +150,6 @@ temporarily_use_uid(struct passwd *pw)
strerror(errno));
}
-void
-permanently_drop_suid(uid_t uid)
-{
-#ifndef HAVE_CYGWIN
- uid_t old_uid = getuid();
-#endif
-
- debug("permanently_drop_suid: %u", (u_int)uid);
- if (setresuid(uid, uid, uid) < 0)
- fatal("setresuid %u: %.100s", (u_int)uid, strerror(errno));
-
-#ifndef HAVE_CYGWIN
- /* Try restoration of UID if changed (test clearing of saved uid) */
- if (old_uid != uid &&
- (setuid(old_uid) != -1 || seteuid(old_uid) != -1))
- fatal("%s: was able to restore old [e]uid", __func__);
-#endif
-
- /* Verify UID drop was successful */
- if (getuid() != uid || geteuid() != uid) {
- fatal("%s: euid incorrect uid:%u euid:%u (should be %u)",
- __func__, (u_int)getuid(), (u_int)geteuid(), (u_int)uid);
- }
-}
-
/*
* Restores to the original (privileged) uid.
*/
@@ -183,9 +167,9 @@ restore_uid(void)
#ifdef SAVED_IDS_WORK_WITH_SETEUID
debug("restore_uid: %u/%u", (u_int)saved_euid, (u_int)saved_egid);
/* Set the effective uid back to the saved privileged uid. */
- if (seteuid(saved_euid) < 0)
+ if (seteuid(saved_euid) == -1)
fatal("seteuid %u: %.100s", (u_int)saved_euid, strerror(errno));
- if (setegid(saved_egid) < 0)
+ if (setegid(saved_egid) == -1)
fatal("setegid %u: %.100s", (u_int)saved_egid, strerror(errno));
#else /* SAVED_IDS_WORK_WITH_SETEUID */
/*
@@ -193,11 +177,13 @@ restore_uid(void)
* Propagate the real uid (usually more privileged) to effective uid
* as well.
*/
- setuid(getuid());
- setgid(getgid());
+ if (setuid(getuid()) == -1)
+ fatal("%s: setuid failed: %s", __func__, strerror(errno));
+ if (setgid(getgid()) == -1)
+ fatal("%s: setgid failed: %s", __func__, strerror(errno));
#endif /* SAVED_IDS_WORK_WITH_SETEUID */
- if (setgroups(saved_egroupslen, saved_egroups) < 0)
+ if (setgroups(saved_egroupslen, saved_egroups) == -1)
fatal("setgroups: %.100s", strerror(errno));
temporarily_use_uid_effective = 0;
}
@@ -209,7 +195,7 @@ restore_uid(void)
void
permanently_set_uid(struct passwd *pw)
{
-#ifndef HAVE_CYGWIN
+#ifndef NO_UID_RESTORATION_TEST
uid_t old_uid = getuid();
gid_t old_gid = getgid();
#endif
@@ -245,7 +231,7 @@ permanently_set_uid(struct passwd *pw)
}
#endif
- if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0)
+ if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
fatal("setresgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno));
#ifdef __APPLE__
@@ -253,15 +239,15 @@ permanently_set_uid(struct passwd *pw)
* OS X requires initgroups after setgid to opt back into
* memberd support for >16 supplemental groups.
*/
- if (initgroups(pw->pw_name, pw->pw_gid) < 0)
+ if (initgroups(pw->pw_name, pw->pw_gid) == -1)
fatal("initgroups %.100s %u: %.100s",
pw->pw_name, (u_int)pw->pw_gid, strerror(errno));
#endif
- if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0)
+ if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno));
-#ifndef HAVE_CYGWIN
+#ifndef NO_UID_RESTORATION_TEST
/* Try restoration of GID if changed (test clearing of saved gid) */
if (old_gid != pw->pw_gid && pw->pw_uid != 0 &&
(setgid(old_gid) != -1 || setegid(old_gid) != -1))
@@ -275,7 +261,7 @@ permanently_set_uid(struct passwd *pw)
(u_int)pw->pw_gid);
}
-#ifndef HAVE_CYGWIN
+#ifndef NO_UID_RESTORATION_TEST
/* Try restoration of UID if changed (test clearing of saved uid) */
if (old_uid != pw->pw_uid &&
(setuid(old_uid) != -1 || seteuid(old_uid) != -1))
@@ -289,7 +275,7 @@ permanently_set_uid(struct passwd *pw)
(u_int)pw->pw_uid);
}
-#ifdef ANDROID
+#if defined(ANDROID)
if (pw->pw_uid == AID_SHELL) {
/* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */
header.version = _LINUX_CAPABILITY_VERSION;
diff --git a/uidswap.h b/uidswap.h
index 1c1163d7..4ac91aa0 100644
--- a/uidswap.h
+++ b/uidswap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uidswap.h,v 1.13 2006/08/03 03:34:42 deraadt Exp $ */
+/* $OpenBSD: uidswap.h,v 1.14 2018/07/18 11:34:05 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -15,4 +15,3 @@
void temporarily_use_uid(struct passwd *);
void restore_uid(void);
void permanently_set_uid(struct passwd *);
-void permanently_drop_suid(uid_t);
diff --git a/umac.c b/umac.c
index 4964457b..3d4e285b 100644
--- a/umac.c
+++ b/umac.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: umac.c,v 1.11 2014/07/22 07:13:42 guenther Exp $ */
+/* $OpenBSD: umac.c,v 1.20 2020/03/13 03:17:07 djm Exp $ */
/* -----------------------------------------------------------------------
- *
+ *
* umac.c -- C Implementation UMAC Message Authentication
*
* Version 0.93b of rfc4418.txt -- 2006 July 18
@@ -10,7 +10,7 @@
* Please report bugs and suggestions to the UMAC webpage.
*
* Copyright (c) 1999-2006 Ted Krovetz
- *
+ *
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and with or without fee, is hereby
* granted provided that the above copyright notice appears in all copies
@@ -18,10 +18,10 @@
* holder not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission.
*
- * Comments should be directed to Ted Krovetz (tdk@acm.org)
- *
+ * Comments should be directed to Ted Krovetz (tdk@acm.org)
+ *
* ---------------------------------------------------------------------- */
-
+
/* ////////////////////// IMPORTANT NOTES /////////////////////////////////
*
* 1) This version does not work properly on messages larger than 16MB
@@ -39,7 +39,7 @@
* at http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ (search for
* "Barreto"). The only two files needed are rijndael-alg-fst.c and
* rijndael-alg-fst.h. Brian Gladman's version is distributed with the GNU
- * Public lisence at http://fp.gladman.plus.com/AES/index.htm. It
+ * Public license at http://fp.gladman.plus.com/AES/index.htm. It
* includes a fast IA-32 assembly version. The OpenSSL crypo library is
* the third.
*
@@ -48,12 +48,6 @@
*
/////////////////////////////////////////////////////////////////////// */
-/* In OpenSSH, this file is compiled twice, with different #defines set on the
- * command line. Since we don't want to stretch the Android build system, in
- * Android this file is duplicated as umac.c and umac128.c. The latter contains
- * the #defines (that were set in OpenSSH's Makefile) at the top of the
- * file. */
-
/* ---------------------------------------------------------------------- */
/* --- User Switches ---------------------------------------------------- */
/* ---------------------------------------------------------------------- */
@@ -71,7 +65,7 @@
/* #define AES_IMPLEMENTAION 1 1 = OpenSSL, 2 = Barreto, 3 = Gladman */
/* #define SSE2 0 Is SSE2 is available? */
/* #define RUN_TESTS 0 Run basic correctness/speed tests */
-/* #define UMAC_AE_SUPPORT 0 Enable auhthenticated encrytion */
+/* #define UMAC_AE_SUPPORT 0 Enable authenticated encryption */
/* ---------------------------------------------------------------------- */
/* -- Global Includes --------------------------------------------------- */
@@ -80,6 +74,7 @@
#include "includes.h"
#include <sys/types.h>
#include <string.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
@@ -193,11 +188,11 @@ static void kdf(void *bufp, aes_int_key key, UINT8 ndx, int nbytes)
UINT8 out_buf[AES_BLOCK_LEN];
UINT8 *dst_buf = (UINT8 *)bufp;
int i;
-
+
/* Setup the initial value */
in_buf[AES_BLOCK_LEN-9] = ndx;
in_buf[AES_BLOCK_LEN-1] = i = 1;
-
+
while (nbytes >= AES_BLOCK_LEN) {
aes_encryption(in_buf, out_buf, key);
memcpy(dst_buf,out_buf,AES_BLOCK_LEN);
@@ -209,10 +204,12 @@ static void kdf(void *bufp, aes_int_key key, UINT8 ndx, int nbytes)
aes_encryption(in_buf, out_buf, key);
memcpy(dst_buf,out_buf,nbytes);
}
+ explicit_bzero(in_buf, sizeof(in_buf));
+ explicit_bzero(out_buf, sizeof(out_buf));
}
/* The final UHASH result is XOR'd with the output of a pseudorandom
- * function. Here, we use AES to generate random output and
+ * function. Here, we use AES to generate random output and
* xor the appropriate bytes depending on the last bits of nonce.
* This scheme is optimized for sequential, increasing big-endian nonces.
*/
@@ -226,13 +223,14 @@ typedef struct {
static void pdf_init(pdf_ctx *pc, aes_int_key prf_key)
{
UINT8 buf[UMAC_KEY_LEN];
-
+
kdf(buf, prf_key, 0, UMAC_KEY_LEN);
aes_key_setup(buf, pc->prf_key);
-
+
/* Initialize pdf and cache */
memset(pc->nonce, 0, sizeof(pc->nonce));
aes_encryption(pc->nonce, pc->cache, pc->prf_key);
+ explicit_bzero(buf, sizeof(buf));
}
static void pdf_gen_xor(pdf_ctx *pc, const UINT8 nonce[8], UINT8 buf[8])
@@ -241,7 +239,7 @@ static void pdf_gen_xor(pdf_ctx *pc, const UINT8 nonce[8], UINT8 buf[8])
* of the AES output. If last time around we returned the ndx-1st
* element, then we may have the result in the cache already.
*/
-
+
#if (UMAC_OUTPUT_LEN == 4)
#define LOW_BIT_MASK 3
#elif (UMAC_OUTPUT_LEN == 8)
@@ -258,7 +256,7 @@ static void pdf_gen_xor(pdf_ctx *pc, const UINT8 nonce[8], UINT8 buf[8])
#endif
*(UINT32 *)t.tmp_nonce_lo = ((const UINT32 *)nonce)[1];
t.tmp_nonce_lo[3] &= ~LOW_BIT_MASK; /* zero last bit */
-
+
if ( (((UINT32 *)t.tmp_nonce_lo)[0] != ((UINT32 *)pc->nonce)[1]) ||
(((const UINT32 *)nonce)[0] != ((UINT32 *)pc->nonce)[0]) )
{
@@ -266,7 +264,7 @@ static void pdf_gen_xor(pdf_ctx *pc, const UINT8 nonce[8], UINT8 buf[8])
((UINT32 *)pc->nonce)[1] = ((UINT32 *)t.tmp_nonce_lo)[0];
aes_encryption(pc->nonce, pc->cache, pc->prf_key);
}
-
+
#if (UMAC_OUTPUT_LEN == 4)
*((UINT32 *)buf) ^= ((UINT32 *)pc->cache)[ndx];
#elif (UMAC_OUTPUT_LEN == 8)
@@ -287,28 +285,28 @@ static void pdf_gen_xor(pdf_ctx *pc, const UINT8 nonce[8], UINT8 buf[8])
/* ---------------------------------------------------------------------- */
/* The NH-based hash functions used in UMAC are described in the UMAC paper
- * and specification, both of which can be found at the UMAC website.
- * The interface to this implementation has two
+ * and specification, both of which can be found at the UMAC website.
+ * The interface to this implementation has two
* 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
- * 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
- * must be called. The single-buffer routine, nh(), is equivalent to
- * the sequence of calls nh_update() and nh_final(); however it is
- * optimized and should be prefered whenever the multiple-buffer interface
- * is not necessary. When using either interface, it is the client's
- * responsability to pass no more than L1_KEY_LEN bytes per hash result.
- *
- * The routine nh_init() initializes the nh_ctx data structure and
- * must be called once, before any other PDF routine.
+ * allows the message to be passed in a sequence of buffers. In the
+ * muliple-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
+ * must be called. The single-buffer routine, nh(), is equivalent to
+ * the sequence of calls nh_update() and nh_final(); however it is
+ * optimized and should be preferred whenever the multiple-buffer interface
+ * is not necessary. When using either interface, it is the client's
+ * responsibility to pass no more than L1_KEY_LEN bytes per hash result.
+ *
+ * The routine nh_init() initializes the nh_ctx data structure and
+ * must be called once, before any other PDF routine.
*/
-
+
/* The "nh_aux" routines do the actual NH hashing work. They
* expect buffers to be multiples of L1_PAD_BOUNDARY. These routines
- * produce output for all STREAMS NH iterations in one call,
+ * produce output for all STREAMS NH iterations in one call,
* allowing the parallel implementation of the streams.
*/
@@ -322,8 +320,8 @@ static void pdf_gen_xor(pdf_ctx *pc, const UINT8 nonce[8], UINT8 buf[8])
typedef struct {
UINT8 nh_key [L1_KEY_LEN + L1_KEY_SHIFT * (STREAMS - 1)]; /* NH Key */
UINT8 data [HASH_BUF_BYTES]; /* Incoming data buffer */
- int next_data_empty; /* Bookeeping variable for data buffer. */
- int bytes_hashed; /* Bytes (out of L1_KEY_LEN) incorperated. */
+ int next_data_empty; /* Bookkeeping variable for data buffer. */
+ int bytes_hashed; /* Bytes (out of L1_KEY_LEN) incorporated. */
UINT64 state[STREAMS]; /* on-line state */
} nh_ctx;
@@ -331,10 +329,10 @@ typedef struct {
#if (UMAC_OUTPUT_LEN == 4)
static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen)
-/* NH hashing primitive. Previous (partial) hash result is loaded and
+/* NH hashing primitive. Previous (partial) hash result is loaded and
* then stored via hp pointer. The length of the data pointed at by "dp",
* "dlen", is guaranteed to be divisible by L1_PAD_BOUNDARY (32). Key
-* is expected to be endian compensated in memory at key setup.
+* is expected to be endian compensated in memory at key setup.
*/
{
UINT64 h;
@@ -343,7 +341,7 @@ static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen)
const UINT32 *d = (const UINT32 *)dp;
UINT32 d0,d1,d2,d3,d4,d5,d6,d7;
UINT32 k0,k1,k2,k3,k4,k5,k6,k7;
-
+
h = *((UINT64 *)hp);
do {
d0 = LOAD_UINT32_LITTLE(d+0); d1 = LOAD_UINT32_LITTLE(d+1);
@@ -356,7 +354,7 @@ static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen)
h += MUL64((k1 + d1), (k5 + d5));
h += MUL64((k2 + d2), (k6 + d6));
h += MUL64((k3 + d3), (k7 + d7));
-
+
d += 8;
k += 8;
} while (--c);
@@ -424,7 +422,7 @@ static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen)
UINT32 d0,d1,d2,d3,d4,d5,d6,d7;
UINT32 k0,k1,k2,k3,k4,k5,k6,k7,
k8,k9,k10,k11,k12,k13,k14,k15;
-
+
h1 = *((UINT64 *)hp);
h2 = *((UINT64 *)hp + 1);
h3 = *((UINT64 *)hp + 2);
@@ -437,26 +435,26 @@ static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen)
d6 = LOAD_UINT32_LITTLE(d+6); d7 = LOAD_UINT32_LITTLE(d+7);
k8 = *(k+8); k9 = *(k+9); k10 = *(k+10); k11 = *(k+11);
k12 = *(k+12); k13 = *(k+13); k14 = *(k+14); k15 = *(k+15);
-
+
h1 += MUL64((k0 + d0), (k4 + d4));
h2 += MUL64((k4 + d0), (k8 + d4));
h3 += MUL64((k8 + d0), (k12 + d4));
-
+
h1 += MUL64((k1 + d1), (k5 + d5));
h2 += MUL64((k5 + d1), (k9 + d5));
h3 += MUL64((k9 + d1), (k13 + d5));
-
+
h1 += MUL64((k2 + d2), (k6 + d6));
h2 += MUL64((k6 + d2), (k10 + d6));
h3 += MUL64((k10 + d2), (k14 + d6));
-
+
h1 += MUL64((k3 + d3), (k7 + d7));
h2 += MUL64((k7 + d3), (k11 + d7));
h3 += MUL64((k11 + d3), (k15 + d7));
-
+
k0 = k8; k1 = k9; k2 = k10; k3 = k11;
k4 = k12; k5 = k13; k6 = k14; k7 = k15;
-
+
d += 8;
k += 8;
} while (--c);
@@ -480,7 +478,7 @@ static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen)
UINT32 k0,k1,k2,k3,k4,k5,k6,k7,
k8,k9,k10,k11,k12,k13,k14,k15,
k16,k17,k18,k19;
-
+
h1 = *((UINT64 *)hp);
h2 = *((UINT64 *)hp + 1);
h3 = *((UINT64 *)hp + 2);
@@ -495,31 +493,31 @@ static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen)
k8 = *(k+8); k9 = *(k+9); k10 = *(k+10); k11 = *(k+11);
k12 = *(k+12); k13 = *(k+13); k14 = *(k+14); k15 = *(k+15);
k16 = *(k+16); k17 = *(k+17); k18 = *(k+18); k19 = *(k+19);
-
+
h1 += MUL64((k0 + d0), (k4 + d4));
h2 += MUL64((k4 + d0), (k8 + d4));
h3 += MUL64((k8 + d0), (k12 + d4));
h4 += MUL64((k12 + d0), (k16 + d4));
-
+
h1 += MUL64((k1 + d1), (k5 + d5));
h2 += MUL64((k5 + d1), (k9 + d5));
h3 += MUL64((k9 + d1), (k13 + d5));
h4 += MUL64((k13 + d1), (k17 + d5));
-
+
h1 += MUL64((k2 + d2), (k6 + d6));
h2 += MUL64((k6 + d2), (k10 + d6));
h3 += MUL64((k10 + d2), (k14 + d6));
h4 += MUL64((k14 + d2), (k18 + d6));
-
+
h1 += MUL64((k3 + d3), (k7 + d7));
h2 += MUL64((k7 + d3), (k11 + d7));
h3 += MUL64((k11 + d3), (k15 + d7));
h4 += MUL64((k15 + d3), (k19 + d7));
-
+
k0 = k8; k1 = k9; k2 = k10; k3 = k11;
k4 = k12; k5 = k13; k6 = k14; k7 = k15;
k8 = k16; k9 = k17; k10 = k18; k11 = k19;
-
+
d += 8;
k += 8;
} while (--c);
@@ -544,7 +542,7 @@ static void nh_transform(nh_ctx *hc, const UINT8 *buf, UINT32 nbytes)
*/
{
UINT8 *key;
-
+
key = hc->nh_key + hc->bytes_hashed;
nh_aux(key, buf, hc->state, nbytes);
}
@@ -616,7 +614,7 @@ static void nh_update(nh_ctx *hc, const UINT8 *buf, UINT32 nbytes)
/* even multiple of HASH_BUF_BYTES. */
{
UINT32 i,j;
-
+
j = hc->next_data_empty;
if ((j + nbytes) >= HASH_BUF_BYTES) {
if (j) {
@@ -680,12 +678,12 @@ static void nh_final(nh_ctx *hc, UINT8 *result)
if (hc->next_data_empty != 0) {
nh_len = ((hc->next_data_empty + (L1_PAD_BOUNDARY - 1)) &
~(L1_PAD_BOUNDARY - 1));
- zero_pad(hc->data + hc->next_data_empty,
+ zero_pad(hc->data + hc->next_data_empty,
nh_len - hc->next_data_empty);
nh_transform(hc, hc->data, nh_len);
hc->bytes_hashed += hc->next_data_empty;
} else if (hc->bytes_hashed == 0) {
- nh_len = L1_PAD_BOUNDARY;
+ nh_len = L1_PAD_BOUNDARY;
zero_pad(hc->data, L1_PAD_BOUNDARY);
nh_transform(hc, hc->data, nh_len);
}
@@ -714,10 +712,10 @@ static void nh(nh_ctx *hc, const UINT8 *buf, UINT32 padded_len,
*/
{
UINT32 nbits;
-
+
/* Initialize the hash state */
nbits = (unpadded_len << 3);
-
+
((UINT64 *)result)[0] = nbits;
#if (UMAC_OUTPUT_LEN >= 8)
((UINT64 *)result)[1] = nbits;
@@ -728,7 +726,7 @@ static void nh(nh_ctx *hc, const UINT8 *buf, UINT32 padded_len,
#if (UMAC_OUTPUT_LEN == 16)
((UINT64 *)result)[3] = nbits;
#endif
-
+
nh_aux(hc->nh_key, buf, result, padded_len);
}
@@ -747,16 +745,16 @@ static void nh(nh_ctx *hc, const UINT8 *buf, UINT32 padded_len,
* buffers are presented sequentially. In the sequential interface, the
* UHASH client calls the routine uhash_update() as many times as necessary.
* When there is no more data to be fed to UHASH, the client calls
- * uhash_final() which
- * calculates the UHASH output. Before beginning another UHASH calculation
- * the uhash_reset() routine must be called. The all-at-once UHASH routine,
- * uhash(), is equivalent to the sequence of calls uhash_update() and
- * uhash_final(); however it is optimized and should be
- * used whenever the sequential interface is not necessary.
- *
- * The routine uhash_init() initializes the uhash_ctx data structure and
+ * uhash_final() which
+ * calculates the UHASH output. Before beginning another UHASH calculation
+ * the uhash_reset() routine must be called. The all-at-once UHASH routine,
+ * uhash(), is equivalent to the sequence of calls uhash_update() and
+ * uhash_final(); however it is optimized and should be
+ * used whenever the sequential interface is not necessary.
+ *
+ * The routine uhash_init() initializes the uhash_ctx data structure and
* must be called once, before any other UHASH routine.
- */
+ */
/* ---------------------------------------------------------------------- */
/* ----- Constants and uhash_ctx ---------------------------------------- */
@@ -805,13 +803,13 @@ static UINT64 poly64(UINT64 cur, UINT64 key, UINT64 data)
x_lo,
x_hi;
UINT64 X,T,res;
-
+
X = MUL64(key_hi, cur_lo) + MUL64(cur_hi, key_lo);
x_lo = (UINT32)X;
x_hi = (UINT32)(X >> 32);
-
+
res = (MUL64(key_hi, cur_hi) + x_hi) * 59 + MUL64(key_lo, cur_lo);
-
+
T = ((UINT64)x_lo << 32);
res += T;
if (res < T)
@@ -835,10 +833,10 @@ static void poly_hash(uhash_ctx_t hc, UINT32 data_in[])
{
int i;
UINT64 *data=(UINT64*)data_in;
-
+
for (i = 0; i < STREAMS; i++) {
if ((UINT32)(data[i] >> 32) == 0xfffffffful) {
- hc->poly_accum[i] = poly64(hc->poly_accum[i],
+ hc->poly_accum[i] = poly64(hc->poly_accum[i],
hc->poly_key_8[i], p64 - 1);
hc->poly_accum[i] = poly64(hc->poly_accum[i],
hc->poly_key_8[i], (data[i] - 59));
@@ -854,7 +852,7 @@ static void poly_hash(uhash_ctx_t hc, UINT32 data_in[])
/* The final step in UHASH is an inner-product hash. The poly hash
- * produces a result not neccesarily WORD_LEN bytes long. The inner-
+ * produces a result not necessarily WORD_LEN bytes long. The inner-
* product hash breaks the polyhash output into 16-bit chunks and
* multiplies each with a 36 bit key.
*/
@@ -865,7 +863,7 @@ static UINT64 ip_aux(UINT64 t, UINT64 *ipkp, UINT64 data)
t = t + ipkp[1] * (UINT64)(UINT16)(data >> 32);
t = t + ipkp[2] * (UINT64)(UINT16)(data >> 16);
t = t + ipkp[3] * (UINT64)(UINT16)(data);
-
+
return t;
}
@@ -873,7 +871,7 @@ static UINT32 ip_reduce_p36(UINT64 t)
{
/* Divisionless modular reduction */
UINT64 ret;
-
+
ret = (t & m36) + 5 * (t >> 36);
if (ret >= p36)
ret -= p36;
@@ -891,7 +889,7 @@ static void ip_short(uhash_ctx_t ahc, UINT8 *nh_res, u_char *res)
{
UINT64 t;
UINT64 *nhp = (UINT64 *)nh_res;
-
+
t = ip_aux(0,ahc->ip_keys, nhp[0]);
STORE_UINT32_BIG((UINT32 *)res+0, ip_reduce_p36(t) ^ ahc->ip_trans[0]);
#if (UMAC_OUTPUT_LEN >= 8)
@@ -922,7 +920,7 @@ static void ip_long(uhash_ctx_t ahc, u_char *res)
if (ahc->poly_accum[i] >= p64)
ahc->poly_accum[i] -= p64;
t = ip_aux(0,ahc->ip_keys+(i*4), ahc->poly_accum[i]);
- STORE_UINT32_BIG((UINT32 *)res+i,
+ STORE_UINT32_BIG((UINT32 *)res+i,
ip_reduce_p36(t) ^ ahc->ip_trans[i]);
}
}
@@ -961,13 +959,13 @@ static void uhash_init(uhash_ctx_t ahc, aes_int_key prf_key)
{
int i;
UINT8 buf[(8*STREAMS+4)*sizeof(UINT64)];
-
+
/* Zero the entire uhash context */
memset(ahc, 0, sizeof(uhash_ctx));
/* Initialize the L1 hash */
nh_init(&ahc->hash, prf_key);
-
+
/* Setup L2 hash variables */
kdf(buf, prf_key, 2, sizeof(buf)); /* Fill buffer with index 1 key */
for (i = 0; i < STREAMS; i++) {
@@ -981,22 +979,23 @@ static void uhash_init(uhash_ctx_t ahc, aes_int_key prf_key)
ahc->poly_key_8[i] &= ((UINT64)0x01ffffffu << 32) + 0x01ffffffu;
ahc->poly_accum[i] = 1; /* Our polyhash prepends a non-zero word */
}
-
+
/* Setup L3-1 hash variables */
kdf(buf, prf_key, 3, sizeof(buf)); /* Fill buffer with index 2 key */
for (i = 0; i < STREAMS; i++)
memcpy(ahc->ip_keys+4*i, buf+(8*i+4)*sizeof(UINT64),
4*sizeof(UINT64));
- endian_convert_if_le(ahc->ip_keys, sizeof(UINT64),
+ endian_convert_if_le(ahc->ip_keys, sizeof(UINT64),
sizeof(ahc->ip_keys));
for (i = 0; i < STREAMS*4; i++)
ahc->ip_keys[i] %= p36; /* Bring into Z_p36 */
-
+
/* Setup L3-2 hash variables */
/* Fill buffer with index 4 key */
kdf(ahc->ip_trans, prf_key, 4, STREAMS * sizeof(UINT32));
endian_convert_if_le(ahc->ip_trans, sizeof(UINT32),
STREAMS * sizeof(UINT32));
+ explicit_bzero(buf, sizeof(buf));
}
/* ---------------------------------------------------------------------- */
@@ -1008,7 +1007,7 @@ static uhash_ctx_t uhash_alloc(u_char key[])
uhash_ctx_t ctx;
u_char bytes_to_add;
aes_int_key prf_key;
-
+
ctx = (uhash_ctx_t)malloc(sizeof(uhash_ctx)+ALLOC_BOUNDARY);
if (ctx) {
if (ALLOC_BOUNDARY) {
@@ -1031,7 +1030,7 @@ static int uhash_free(uhash_ctx_t ctx)
{
/* Free memory allocated by uhash_alloc */
u_char bytes_to_sub;
-
+
if (ctx) {
if (ALLOC_BOUNDARY) {
bytes_to_sub = *((u_char *)ctx - 1);
@@ -1052,12 +1051,12 @@ static int uhash_update(uhash_ctx_t ctx, const u_char *input, long len)
UWORD bytes_hashed, bytes_remaining;
UINT64 result_buf[STREAMS];
UINT8 *nh_result = (UINT8 *)&result_buf;
-
+
if (ctx->msg_len + len <= L1_KEY_LEN) {
nh_update(&ctx->hash, (const UINT8 *)input, len);
ctx->msg_len += len;
} else {
-
+
bytes_hashed = ctx->msg_len % L1_KEY_LEN;
if (ctx->msg_len == L1_KEY_LEN)
bytes_hashed = L1_KEY_LEN;
@@ -1130,15 +1129,15 @@ static int uhash(uhash_ctx_t ahc, u_char *msg, long len, u_char *res)
UINT8 nh_result[STREAMS*sizeof(UINT64)];
UINT32 nh_len;
int extra_zeroes_needed;
-
+
/* If the message to be hashed is no longer than L1_HASH_LEN, we skip
* the polyhash.
*/
if (len <= L1_KEY_LEN) {
- if (len == 0) /* If zero length messages will not */
- nh_len = L1_PAD_BOUNDARY; /* be seen, comment out this case */
- else
- nh_len = ((len + (L1_PAD_BOUNDARY - 1)) & ~(L1_PAD_BOUNDARY - 1));
+ if (len == 0) /* If zero length messages will not */
+ nh_len = L1_PAD_BOUNDARY; /* be seen, comment out this case */
+ else
+ nh_len = ((len + (L1_PAD_BOUNDARY - 1)) & ~(L1_PAD_BOUNDARY - 1));
extra_zeroes_needed = nh_len - len;
zero_pad((UINT8 *)msg + len, extra_zeroes_needed);
nh(&ahc->hash, (UINT8 *)msg, nh_len, len, nh_result);
@@ -1163,7 +1162,7 @@ static int uhash(uhash_ctx_t ahc, u_char *msg, long len, u_char *res)
ip_long(ahc, res);
}
-
+
uhash_reset(ahc);
return 1;
}
@@ -1177,9 +1176,9 @@ static int uhash(uhash_ctx_t ahc, u_char *msg, long len, u_char *res)
/* The UMAC interface has two interfaces, an all-at-once interface where
* the entire message to be authenticated is passed to UMAC in one buffer,
- * and a sequential interface where the message is presented a little at a
+ * and a sequential interface where the message is presented a little at a
* time. The all-at-once is more optimaized than the sequential version and
- * should be preferred when the sequential interface is not required.
+ * should be preferred when the sequential interface is not required.
*/
struct umac_ctx {
uhash_ctx hash; /* Hash function for message compression */
@@ -1206,7 +1205,7 @@ int umac_delete(struct umac_ctx *ctx)
if (ctx) {
if (ALLOC_BOUNDARY)
ctx = (struct umac_ctx *)ctx->free_ptr;
- free(ctx);
+ freezero(ctx, sizeof(*ctx) + ALLOC_BOUNDARY);
}
return (1);
}
@@ -1214,14 +1213,14 @@ int umac_delete(struct umac_ctx *ctx)
/* ---------------------------------------------------------------------- */
struct umac_ctx *umac_new(const u_char key[])
-/* Dynamically allocate a umac_ctx struct, initialize variables,
+/* Dynamically allocate a umac_ctx struct, initialize variables,
* generate subkeys from key. Align to 16-byte boundary.
*/
{
struct umac_ctx *ctx, *octx;
size_t bytes_to_add;
aes_int_key prf_key;
-
+
octx = ctx = xcalloc(1, sizeof(*ctx) + ALLOC_BOUNDARY);
if (ctx) {
if (ALLOC_BOUNDARY) {
@@ -1233,8 +1232,9 @@ struct umac_ctx *umac_new(const u_char key[])
aes_key_setup(key, prf_key);
pdf_init(&ctx->pdf, prf_key);
uhash_init(&ctx->hash, prf_key);
+ explicit_bzero(prf_key, sizeof(prf_key));
}
-
+
return (ctx);
}
@@ -1245,7 +1245,7 @@ int umac_final(struct umac_ctx *ctx, u_char tag[], const u_char nonce[8])
{
uhash_final(&ctx->hash, (u_char *)tag);
pdf_gen_xor(&ctx->pdf, (const UINT8 *)nonce, (UINT8 *)tag);
-
+
return (1);
}
@@ -1263,14 +1263,14 @@ int umac_update(struct umac_ctx *ctx, const u_char *input, long len)
/* ---------------------------------------------------------------------- */
#if 0
-int umac(struct umac_ctx *ctx, u_char *input,
+int umac(struct umac_ctx *ctx, u_char *input,
long len, u_char tag[],
u_char nonce[8])
/* All-in-one version simply calls umac_update() and umac_final(). */
{
uhash(&ctx->hash, input, len, (u_char *)tag);
pdf_gen_xor(&ctx->pdf, (UINT8 *)nonce, (UINT8 *)tag);
-
+
return (1);
}
#endif
diff --git a/umac.h b/umac.h
index 7fb770f8..4651f0d5 100644
--- a/umac.h
+++ b/umac.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: umac.h,v 1.3 2013/07/22 12:20:02 djm Exp $ */
+/* $OpenBSD: umac.h,v 1.4 2019/06/07 14:18:48 dtucker Exp $ */
/* -----------------------------------------------------------------------
*
* umac.h -- C Implementation UMAC Message Authentication
@@ -39,7 +39,7 @@
* at http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ (search for
* "Barreto"). The only two files needed are rijndael-alg-fst.c and
* rijndael-alg-fst.h.
- * Brian Gladman's version is distributed with GNU Public lisence
+ * Brian Gladman's version is distributed with GNU Public license
* and can be found at http://fp.gladman.plus.com/AES/index.htm. It
* includes a fast IA-32 assembly version.
*
@@ -107,7 +107,7 @@ int uhash_update(uhash_ctx_t ctx,
long len);
int uhash_final(uhash_ctx_t ctx,
- u_char ouput[]);
+ u_char output[]);
int uhash(uhash_ctx_t ctx,
u_char *input,
diff --git a/umac128.c b/umac128.c
index 2d4166a3..f7179250 100644
--- a/umac128.c
+++ b/umac128.c
@@ -1,13 +1,10 @@
-/* In OpenSSH, umac.c is compiled twice, with different #defines set on the
- * command line. Since we don't want to stretch the Android build system, in
- * Android this file is duplicated as umac.c and umac128.c. The latter contains
- * the #defines (that were set in OpenSSH's Makefile) at the top of the
- * file and then #includes umac.c. */
+/* $OpenBSD: umac128.c,v 1.2 2018/02/08 04:12:32 dtucker Exp $ */
-#define UMAC_OUTPUT_LEN 16
-#define umac_new umac128_new
-#define umac_update umac128_update
-#define umac_final umac128_final
-#define umac_delete umac128_delete
+#define UMAC_OUTPUT_LEN 16
+#define umac_new umac128_new
+#define umac_update umac128_update
+#define umac_final umac128_final
+#define umac_delete umac128_delete
+#define umac_ctx umac128_ctx
#include "umac.c"
diff --git a/utf8.c b/utf8.c
new file mode 100644
index 00000000..7f63b25a
--- /dev/null
+++ b/utf8.c
@@ -0,0 +1,355 @@
+/* $OpenBSD: utf8.c,v 1.11 2020/05/01 06:28:52 djm Exp $ */
+/*
+ * Copyright (c) 2016 Ingo Schwarze <schwarze@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.
+ */
+
+/*
+ * Utility functions for multibyte-character handling,
+ * in particular to sanitize untrusted strings for terminal output.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#ifdef HAVE_LANGINFO_H
+# include <langinfo.h>
+#endif
+#include <limits.h>
+#include <locale.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
+# include <vis.h>
+#endif
+#ifdef HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+
+#include "utf8.h"
+
+static int dangerous_locale(void);
+static int grow_dst(char **, size_t *, size_t, char **, size_t);
+
+
+/*
+ * For US-ASCII and UTF-8 encodings, we can safely recover from
+ * encoding errors and from non-printable characters. For any
+ * other encodings, err to the side of caution and abort parsing:
+ * For state-dependent encodings, recovery is impossible.
+ * For arbitrary encodings, replacement of non-printable
+ * characters would be non-trivial and too fragile.
+ * The comments indicate what nl_langinfo(CODESET)
+ * returns for US-ASCII on various operating systems.
+ */
+
+static int
+dangerous_locale(void) {
+ char *loc;
+
+ loc = nl_langinfo(CODESET);
+ return strcmp(loc, "UTF-8") != 0 &&
+ strcmp(loc, "US-ASCII") != 0 && /* OpenBSD */
+ strcmp(loc, "ANSI_X3.4-1968") != 0 && /* Linux */
+ strcmp(loc, "ISO8859-1") != 0 && /* AIX */
+ strcmp(loc, "646") != 0 && /* Solaris, NetBSD */
+ strcmp(loc, "") != 0; /* Solaris 6 */
+}
+
+static int
+grow_dst(char **dst, size_t *sz, size_t maxsz, char **dp, size_t need)
+{
+ char *tp;
+ size_t tsz;
+
+ if (*dp + need < *dst + *sz)
+ return 0;
+ tsz = *sz + 128;
+ if (tsz > maxsz)
+ tsz = maxsz;
+ if ((tp = recallocarray(*dst, *sz, tsz, 1)) == NULL)
+ return -1;
+ *dp = tp + (*dp - *dst);
+ *dst = tp;
+ *sz = tsz;
+ return 0;
+}
+
+/*
+ * The following two functions limit the number of bytes written,
+ * including the terminating '\0', to sz. Unless wp is NULL,
+ * they limit the number of display columns occupied to *wp.
+ * Whichever is reached first terminates the output string.
+ * To stay close to the standard interfaces, they return the number of
+ * non-NUL bytes that would have been written if both were unlimited.
+ * If wp is NULL, newline, carriage return, and tab are allowed;
+ * otherwise, the actual number of columns occupied by what was
+ * written is returned in *wp.
+ */
+
+int
+vasnmprintf(char **str, size_t maxsz, int *wp, const char *fmt, va_list ap)
+{
+ char *src; /* Source string returned from vasprintf. */
+ char *sp; /* Pointer into src. */
+ char *dst; /* Destination string to be returned. */
+ char *dp; /* Pointer into dst. */
+ char *tp; /* Temporary pointer for dst. */
+ size_t sz; /* Number of bytes allocated for dst. */
+ wchar_t wc; /* Wide character at sp. */
+ int len; /* Number of bytes in the character at sp. */
+ int ret; /* Number of bytes needed to format src. */
+ int width; /* Display width of the character wc. */
+ int total_width, max_width, print;
+
+ src = NULL;
+ if ((ret = vasprintf(&src, fmt, ap)) <= 0)
+ goto fail;
+
+ sz = strlen(src) + 1;
+ if ((dst = malloc(sz)) == NULL) {
+ free(src);
+ ret = -1;
+ goto fail;
+ }
+
+ if (maxsz > INT_MAX)
+ maxsz = INT_MAX;
+
+ sp = src;
+ dp = dst;
+ ret = 0;
+ print = 1;
+ total_width = 0;
+ max_width = wp == NULL ? INT_MAX : *wp;
+ while (*sp != '\0') {
+ if ((len = mbtowc(&wc, sp, MB_CUR_MAX)) == -1) {
+ (void)mbtowc(NULL, NULL, MB_CUR_MAX);
+ if (dangerous_locale()) {
+ ret = -1;
+ break;
+ }
+ len = 1;
+ width = -1;
+ } else if (wp == NULL &&
+ (wc == L'\n' || wc == L'\r' || wc == L'\t')) {
+ /*
+ * Don't use width uninitialized; the actual
+ * value doesn't matter because total_width
+ * is only returned for wp != NULL.
+ */
+ width = 0;
+ } else if ((width = wcwidth(wc)) == -1 &&
+ dangerous_locale()) {
+ ret = -1;
+ break;
+ }
+
+ /* Valid, printable character. */
+
+ if (width >= 0) {
+ if (print && (dp - dst >= (int)maxsz - len ||
+ total_width > max_width - width))
+ print = 0;
+ if (print) {
+ if (grow_dst(&dst, &sz, maxsz,
+ &dp, len) == -1) {
+ ret = -1;
+ break;
+ }
+ total_width += width;
+ memcpy(dp, sp, len);
+ dp += len;
+ }
+ sp += len;
+ if (ret >= 0)
+ ret += len;
+ continue;
+ }
+
+ /* Escaping required. */
+
+ while (len > 0) {
+ if (print && (dp - dst >= (int)maxsz - 4 ||
+ total_width > max_width - 4))
+ print = 0;
+ if (print) {
+ if (grow_dst(&dst, &sz, maxsz,
+ &dp, 4) == -1) {
+ ret = -1;
+ break;
+ }
+ tp = vis(dp, *sp, VIS_OCTAL | VIS_ALL, 0);
+ width = tp - dp;
+ total_width += width;
+ dp = tp;
+ } else
+ width = 4;
+ len--;
+ sp++;
+ if (ret >= 0)
+ ret += width;
+ }
+ if (len > 0)
+ break;
+ }
+ free(src);
+ *dp = '\0';
+ *str = dst;
+ if (wp != NULL)
+ *wp = total_width;
+
+ /*
+ * If the string was truncated by the width limit but
+ * would have fit into the size limit, the only sane way
+ * to report the problem is using the return value, such
+ * that the usual idiom "if (ret < 0 || ret >= sz) error"
+ * works as expected.
+ */
+
+ if (ret < (int)maxsz && !print)
+ ret = -1;
+ return ret;
+
+fail:
+ if (wp != NULL)
+ *wp = 0;
+ if (ret == 0) {
+ *str = src;
+ return 0;
+ } else {
+ *str = NULL;
+ return -1;
+ }
+}
+
+int
+snmprintf(char *str, size_t sz, int *wp, const char *fmt, ...)
+{
+ va_list ap;
+ char *cp = NULL;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vasnmprintf(&cp, sz, wp, fmt, ap);
+ va_end(ap);
+ if (cp != NULL) {
+ (void)strlcpy(str, cp, sz);
+ free(cp);
+ } else
+ *str = '\0';
+ return ret;
+}
+
+int
+asmprintf(char **outp, size_t sz, int *wp, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ *outp = NULL;
+ va_start(ap, fmt);
+ ret = vasnmprintf(outp, sz, wp, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+/*
+ * To stay close to the standard interfaces, the following functions
+ * return the number of non-NUL bytes written.
+ */
+
+int
+vfmprintf(FILE *stream, const char *fmt, va_list ap)
+{
+ char *str = NULL;
+ int ret;
+
+ if ((ret = vasnmprintf(&str, INT_MAX, NULL, fmt, ap)) < 0) {
+ free(str);
+ return -1;
+ }
+ if (fputs(str, stream) == EOF)
+ ret = -1;
+ free(str);
+ return ret;
+}
+
+int
+fmprintf(FILE *stream, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vfmprintf(stream, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+int
+mprintf(const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vfmprintf(stdout, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+/*
+ * Set up libc for multibyte output in the user's chosen locale.
+ *
+ * XXX: we are known to have problems with Turkish (i/I confusion) so we
+ * deliberately fall back to the C locale for now. Longer term we should
+ * always prefer to select C.[encoding] if possible, but there's no
+ * standardisation in locales between systems, so we'll need to survey
+ * what's out there first.
+ */
+void
+msetlocale(void)
+{
+ const char *vars[] = { "LC_ALL", "LC_CTYPE", "LANG", NULL };
+ char *cp;
+ int i;
+
+ /*
+ * We can't yet cope with dotless/dotted I in Turkish locales,
+ * so fall back to the C locale for these.
+ */
+ for (i = 0; vars[i] != NULL; i++) {
+ if ((cp = getenv(vars[i])) == NULL)
+ continue;
+ if (strncasecmp(cp, "TR", 2) != 0)
+ break;
+ /*
+ * If we're in a UTF-8 locale then prefer to use
+ * the C.UTF-8 locale (or equivalent) if it exists.
+ */
+ if ((strcasestr(cp, "UTF-8") != NULL ||
+ strcasestr(cp, "UTF8") != NULL) &&
+ (setlocale(LC_CTYPE, "C.UTF-8") != NULL ||
+ setlocale(LC_CTYPE, "POSIX.UTF-8") != NULL))
+ return;
+ setlocale(LC_CTYPE, "C");
+ return;
+ }
+ /* We can handle this locale */
+ setlocale(LC_CTYPE, "");
+}
diff --git a/utf8.h b/utf8.h
new file mode 100644
index 00000000..9d6d9a32
--- /dev/null
+++ b/utf8.h
@@ -0,0 +1,28 @@
+/* $OpenBSD: utf8.h,v 1.3 2020/05/01 06:28:52 djm Exp $ */
+/*
+ * Copyright (c) 2016 Ingo Schwarze <schwarze@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.
+ */
+
+int vasnmprintf(char **, size_t, int *, const char *, va_list);
+int mprintf(const char *, ...)
+ __attribute__((format(printf, 1, 2)));
+int fmprintf(FILE *, const char *, ...)
+ __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)));
+int asmprintf(char **, size_t, int *, const char *, ...)
+ __attribute__((format(printf, 4, 5)));
+void msetlocale(void);
diff --git a/uuencode.c b/uuencode.c
deleted file mode 100644
index 294c7430..00000000
--- a/uuencode.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/* $OpenBSD: uuencode.c,v 1.27 2013/05/17 00:13:14 djm Exp $ */
-/*
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <resolv.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "xmalloc.h"
-#include "uuencode.h"
-
-/*
- * Encode binary 'src' of length 'srclength', writing base64-encoded text
- * to 'target' of size 'targsize'. Will always nul-terminate 'target'.
- * Returns the number of bytes stored in 'target' or -1 on error (inc.
- * 'targsize' too small).
- */
-int
-uuencode(const u_char *src, u_int srclength,
- char *target, size_t targsize)
-{
- return __b64_ntop(src, srclength, target, targsize);
-}
-
-/*
- * Decode base64-encoded 'src' into buffer 'target' of 'targsize' bytes.
- * Will skip leading and trailing whitespace. Returns the number of bytes
- * stored in 'target' or -1 on error (inc. targsize too small).
- */
-int
-uudecode(const char *src, u_char *target, size_t targsize)
-{
- int len;
- char *encoded, *p;
-
- /* copy the 'readonly' source */
- encoded = xstrdup(src);
- /* skip whitespace and data */
- for (p = encoded; *p == ' ' || *p == '\t'; p++)
- ;
- for (; *p != '\0' && *p != ' ' && *p != '\t'; p++)
- ;
- /* and remove trailing whitespace because __b64_pton needs this */
- *p = '\0';
- len = __b64_pton(encoded, target, targsize);
- free(encoded);
- return len;
-}
-
-void
-dump_base64(FILE *fp, const u_char *data, u_int len)
-{
- char *buf;
- int i, n;
-
- if (len > 65536) {
- fprintf(fp, "dump_base64: len > 65536\n");
- return;
- }
- buf = xmalloc(2*len);
- n = uuencode(data, len, buf, 2*len);
- for (i = 0; i < n; i++) {
- fprintf(fp, "%c", buf[i]);
- if (i % 70 == 69)
- fprintf(fp, "\n");
- }
- if (i % 70 != 69)
- fprintf(fp, "\n");
- free(buf);
-}
diff --git a/uuencode.h b/uuencode.h
deleted file mode 100644
index 4d988812..00000000
--- a/uuencode.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* $OpenBSD: uuencode.h,v 1.14 2010/08/31 11:54:45 djm Exp $ */
-
-/*
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-int uuencode(const u_char *, u_int, char *, size_t);
-int uudecode(const char *, u_char *, size_t);
-void dump_base64(FILE *, const u_char *, u_int);
diff --git a/version.h b/version.h
index dfe3ee99..a2eca3ec 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
-/* $OpenBSD: version.h,v 1.72 2015/03/04 18:53:53 djm Exp $ */
+/* $OpenBSD: version.h,v 1.87 2020/05/06 20:58:01 djm Exp $ */
-#define SSH_VERSION "OpenSSH_6.8"
+#define SSH_VERSION "OpenSSH_8.3"
#define SSH_PORTABLE "p1"
#define SSH_RELEASE SSH_VERSION SSH_PORTABLE
diff --git a/xmalloc.c b/xmalloc.c
index cd59dc2e..b48d33bb 100644
--- a/xmalloc.c
+++ b/xmalloc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xmalloc.c,v 1.31 2015/02/06 23:21:59 millert Exp $ */
+/* $OpenBSD: xmalloc.c,v 1.36 2019/11/12 22:32:48 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -17,7 +17,7 @@
#include <stdarg.h>
#ifdef HAVE_STDINT_H
-#include <stdint.h>
+# include <stdint.h>
#endif
#include <stdio.h>
#include <stdlib.h>
@@ -26,6 +26,10 @@
#include "xmalloc.h"
#include "log.h"
+#if defined(__OpenBSD__)
+char *malloc_options = "S";
+#endif /* __OpenBSD__ */
+
void *
xmalloc(size_t size)
{
@@ -56,22 +60,26 @@ xcalloc(size_t nmemb, size_t size)
}
void *
-xrealloc(void *ptr, size_t nmemb, size_t size)
+xreallocarray(void *ptr, size_t nmemb, size_t size)
{
void *new_ptr;
- size_t new_size = nmemb * size;
- if (new_size == 0)
- fatal("xrealloc: zero size");
- if (SIZE_MAX / nmemb < size)
- fatal("xrealloc: nmemb * size > SIZE_MAX");
- if (ptr == NULL)
- new_ptr = malloc(new_size);
- else
- new_ptr = realloc(ptr, new_size);
+ new_ptr = reallocarray(ptr, nmemb, size);
+ if (new_ptr == NULL)
+ fatal("xreallocarray: out of memory (%zu elements of %zu bytes)",
+ nmemb, size);
+ return new_ptr;
+}
+
+void *
+xrecallocarray(void *ptr, size_t onmemb, size_t nmemb, size_t size)
+{
+ void *new_ptr;
+
+ new_ptr = recallocarray(ptr, onmemb, nmemb, size);
if (new_ptr == NULL)
- fatal("xrealloc: out of memory (new_size %zu bytes)",
- new_size);
+ fatal("xrecallocarray: out of memory (%zu elements of %zu bytes)",
+ nmemb, size);
return new_ptr;
}
@@ -88,17 +96,24 @@ xstrdup(const char *str)
}
int
+xvasprintf(char **ret, const char *fmt, va_list ap)
+{
+ int i;
+
+ i = vasprintf(ret, fmt, ap);
+ if (i < 0 || *ret == NULL)
+ fatal("xvasprintf: could not allocate memory");
+ return i;
+}
+
+int
xasprintf(char **ret, const char *fmt, ...)
{
va_list ap;
int i;
va_start(ap, fmt);
- i = vasprintf(ret, fmt, ap);
+ i = xvasprintf(ret, fmt, ap);
va_end(ap);
-
- if (i < 0 || *ret == NULL)
- fatal("xasprintf: could not allocate memory");
-
- return (i);
+ return i;
}
diff --git a/xmalloc.h b/xmalloc.h
index 261dfd61..abaf7ada 100644
--- a/xmalloc.h
+++ b/xmalloc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: xmalloc.h,v 1.14 2013/05/17 00:13:14 djm Exp $ */
+/* $OpenBSD: xmalloc.h,v 1.19 2019/11/12 22:32:48 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -18,8 +18,11 @@
void *xmalloc(size_t);
void *xcalloc(size_t, size_t);
-void *xrealloc(void *, size_t, size_t);
+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)));
+int xvasprintf(char **, const char *, va_list)
+ __attribute__((__nonnull__ (2)));
diff --git a/xmss_commons.c b/xmss_commons.c
new file mode 100644
index 00000000..8d6b80b6
--- /dev/null
+++ b/xmss_commons.c
@@ -0,0 +1,36 @@
+/* $OpenBSD: xmss_commons.c,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */
+/*
+xmss_commons.c 20160722
+Andreas Hülsing
+Joost Rijneveld
+Public domain.
+*/
+
+#include "includes.h"
+#ifdef WITH_XMSS
+
+#include "xmss_commons.h"
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+void to_byte(unsigned char *out, unsigned long long in, uint32_t bytes)
+{
+ int32_t i;
+ for (i = bytes-1; i >= 0; i--) {
+ out[i] = in & 0xff;
+ in = in >> 8;
+ }
+}
+
+#if 0
+void hexdump(const unsigned char *a, size_t len)
+{
+ size_t i;
+ for (i = 0; i < len; i++)
+ printf("%02x", a[i]);
+}
+#endif
+#endif /* WITH_XMSS */
diff --git a/xmss_commons.h b/xmss_commons.h
new file mode 100644
index 00000000..a98e4799
--- /dev/null
+++ b/xmss_commons.h
@@ -0,0 +1,21 @@
+#ifdef WITH_XMSS
+/* $OpenBSD: xmss_commons.h,v 1.3 2018/02/26 03:56:44 dtucker Exp $ */
+/*
+xmss_commons.h 20160722
+Andreas Hülsing
+Joost Rijneveld
+Public domain.
+*/
+#ifndef XMSS_COMMONS_H
+#define XMSS_COMMONS_H
+
+#include <stdlib.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#endif
+void to_byte(unsigned char *output, unsigned long long in, uint32_t bytes);
+#if 0
+void hexdump(const unsigned char *a, size_t len);
+#endif
+#endif /* WITH_XMSS */
diff --git a/xmss_fast.c b/xmss_fast.c
new file mode 100644
index 00000000..421b39a3
--- /dev/null
+++ b/xmss_fast.c
@@ -0,0 +1,1106 @@
+/* $OpenBSD: xmss_fast.c,v 1.3 2018/03/22 07:06:11 markus Exp $ */
+/*
+xmss_fast.c version 20160722
+Andreas Hülsing
+Joost Rijneveld
+Public domain.
+*/
+
+#include "includes.h"
+#ifdef WITH_XMSS
+
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#include "xmss_fast.h"
+#include "crypto_api.h"
+#include "xmss_wots.h"
+#include "xmss_hash.h"
+
+#include "xmss_commons.h"
+#include "xmss_hash_address.h"
+// For testing
+#include "stdio.h"
+
+
+
+/**
+ * Used for pseudorandom keygeneration,
+ * generates the seed for the WOTS keypair at address addr
+ *
+ * takes n byte sk_seed and returns n byte seed using 32 byte address addr.
+ */
+static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, uint32_t addr[8])
+{
+ unsigned char bytes[32];
+ // Make sure that chain addr, hash addr, and key bit are 0!
+ setChainADRS(addr,0);
+ setHashADRS(addr,0);
+ setKeyAndMask(addr,0);
+ // Generate pseudorandom value
+ addr_to_byte(bytes, addr);
+ prf(seed, bytes, sk_seed, n);
+}
+
+/**
+ * Initialize xmss params struct
+ * parameter names are the same as in the draft
+ * parameter k is K as used in the BDS algorithm
+ */
+int xmss_set_params(xmss_params *params, int n, int h, int w, int k)
+{
+ if (k >= h || k < 2 || (h - k) % 2) {
+ fprintf(stderr, "For BDS traversal, H - K must be even, with H > K >= 2!\n");
+ return 1;
+ }
+ params->h = h;
+ params->n = n;
+ params->k = k;
+ wots_params wots_par;
+ wots_set_params(&wots_par, n, w);
+ params->wots_par = wots_par;
+ return 0;
+}
+
+/**
+ * Initialize BDS state struct
+ * parameter names are the same as used in the description of the BDS traversal
+ */
+void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, unsigned char *stacklevels, unsigned char *auth, unsigned char *keep, treehash_inst *treehash, unsigned char *retain, int next_leaf)
+{
+ state->stack = stack;
+ state->stackoffset = stackoffset;
+ state->stacklevels = stacklevels;
+ state->auth = auth;
+ state->keep = keep;
+ state->treehash = treehash;
+ state->retain = retain;
+ state->next_leaf = next_leaf;
+}
+
+/**
+ * Initialize xmssmt_params struct
+ * parameter names are the same as in the draft
+ *
+ * Especially h is the total tree height, i.e. the XMSS trees have height h/d
+ */
+int xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w, int k)
+{
+ if (h % d) {
+ fprintf(stderr, "d must divide h without remainder!\n");
+ return 1;
+ }
+ params->h = h;
+ params->d = d;
+ params->n = n;
+ params->index_len = (h + 7) / 8;
+ xmss_params xmss_par;
+ if (xmss_set_params(&xmss_par, n, (h/d), w, k)) {
+ return 1;
+ }
+ params->xmss_par = xmss_par;
+ return 0;
+}
+
+/**
+ * Computes a leaf from a WOTS public key using an L-tree.
+ */
+static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8])
+{
+ unsigned int l = params->wots_par.len;
+ unsigned int n = params->n;
+ uint32_t i = 0;
+ uint32_t height = 0;
+ uint32_t bound;
+
+ //ADRS.setTreeHeight(0);
+ setTreeHeight(addr, height);
+
+ while (l > 1) {
+ bound = l >> 1; //floor(l / 2);
+ for (i = 0; i < bound; i++) {
+ //ADRS.setTreeIndex(i);
+ setTreeIndex(addr, i);
+ //wots_pk[i] = RAND_HASH(pk[2i], pk[2i + 1], SEED, ADRS);
+ hash_h(wots_pk+i*n, wots_pk+i*2*n, pub_seed, addr, n);
+ }
+ //if ( l % 2 == 1 ) {
+ if (l & 1) {
+ //pk[floor(l / 2) + 1] = pk[l];
+ memcpy(wots_pk+(l>>1)*n, wots_pk+(l-1)*n, n);
+ //l = ceil(l / 2);
+ l=(l>>1)+1;
+ }
+ else {
+ //l = ceil(l / 2);
+ l=(l>>1);
+ }
+ //ADRS.setTreeHeight(ADRS.getTreeHeight() + 1);
+ height++;
+ setTreeHeight(addr, height);
+ }
+ //return pk[0];
+ memcpy(leaf, wots_pk, n);
+}
+
+/**
+ * Computes the leaf at a given address. First generates the WOTS key pair, then computes leaf using l_tree. As this happens position independent, we only require that addr encodes the right ltree-address.
+ */
+static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, uint32_t ltree_addr[8], uint32_t ots_addr[8])
+{
+ unsigned char seed[params->n];
+ unsigned char pk[params->wots_par.keysize];
+
+ get_seed(seed, sk_seed, params->n, ots_addr);
+ wots_pkgen(pk, seed, &(params->wots_par), pub_seed, ots_addr);
+
+ l_tree(leaf, pk, params, pub_seed, ltree_addr);
+}
+
+static int treehash_minheight_on_stack(bds_state* state, const xmss_params *params, const treehash_inst *treehash) {
+ unsigned int r = params->h, i;
+ for (i = 0; i < treehash->stackusage; i++) {
+ if (state->stacklevels[state->stackoffset - i - 1] < r) {
+ r = state->stacklevels[state->stackoffset - i - 1];
+ }
+ }
+ return r;
+}
+
+/**
+ * Merkle's TreeHash algorithm. The address only needs to initialize the first 78 bits of addr. Everything else will be set by treehash.
+ * Currently only used for key generation.
+ *
+ */
+static void treehash_setup(unsigned char *node, int height, int index, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8])
+{
+ unsigned int idx = index;
+ unsigned int n = params->n;
+ unsigned int h = params->h;
+ unsigned int k = params->k;
+ // use three different addresses because at this point we use all three formats in parallel
+ uint32_t ots_addr[8];
+ uint32_t ltree_addr[8];
+ uint32_t node_addr[8];
+ // only copy layer and tree address parts
+ memcpy(ots_addr, addr, 12);
+ // type = ots
+ setType(ots_addr, 0);
+ memcpy(ltree_addr, addr, 12);
+ setType(ltree_addr, 1);
+ memcpy(node_addr, addr, 12);
+ setType(node_addr, 2);
+
+ uint32_t lastnode, i;
+ unsigned char stack[(height+1)*n];
+ unsigned int stacklevels[height+1];
+ unsigned int stackoffset=0;
+ unsigned int nodeh;
+
+ lastnode = idx+(1<<height);
+
+ for (i = 0; i < h-k; i++) {
+ state->treehash[i].h = i;
+ state->treehash[i].completed = 1;
+ state->treehash[i].stackusage = 0;
+ }
+
+ i = 0;
+ for (; idx < lastnode; idx++) {
+ setLtreeADRS(ltree_addr, idx);
+ setOTSADRS(ots_addr, idx);
+ gen_leaf_wots(stack+stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr);
+ stacklevels[stackoffset] = 0;
+ stackoffset++;
+ if (h - k > 0 && i == 3) {
+ memcpy(state->treehash[0].node, stack+stackoffset*n, n);
+ }
+ while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2])
+ {
+ nodeh = stacklevels[stackoffset-1];
+ if (i >> nodeh == 1) {
+ memcpy(state->auth + nodeh*n, stack+(stackoffset-1)*n, n);
+ }
+ else {
+ if (nodeh < h - k && i >> nodeh == 3) {
+ memcpy(state->treehash[nodeh].node, stack+(stackoffset-1)*n, n);
+ }
+ else if (nodeh >= h - k) {
+ memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((i >> nodeh) - 3) >> 1)) * n, stack+(stackoffset-1)*n, n);
+ }
+ }
+ setTreeHeight(node_addr, stacklevels[stackoffset-1]);
+ setTreeIndex(node_addr, (idx >> (stacklevels[stackoffset-1]+1)));
+ hash_h(stack+(stackoffset-2)*n, stack+(stackoffset-2)*n, pub_seed,
+ node_addr, n);
+ stacklevels[stackoffset-2]++;
+ stackoffset--;
+ }
+ i++;
+ }
+
+ for (i = 0; i < n; i++)
+ node[i] = stack[i];
+}
+
+static void treehash_update(treehash_inst *treehash, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) {
+ int n = params->n;
+
+ uint32_t ots_addr[8];
+ uint32_t ltree_addr[8];
+ uint32_t node_addr[8];
+ // only copy layer and tree address parts
+ memcpy(ots_addr, addr, 12);
+ // type = ots
+ setType(ots_addr, 0);
+ memcpy(ltree_addr, addr, 12);
+ setType(ltree_addr, 1);
+ memcpy(node_addr, addr, 12);
+ setType(node_addr, 2);
+
+ setLtreeADRS(ltree_addr, treehash->next_idx);
+ setOTSADRS(ots_addr, treehash->next_idx);
+
+ unsigned char nodebuffer[2 * n];
+ unsigned int nodeheight = 0;
+ gen_leaf_wots(nodebuffer, sk_seed, params, pub_seed, ltree_addr, ots_addr);
+ while (treehash->stackusage > 0 && state->stacklevels[state->stackoffset-1] == nodeheight) {
+ memcpy(nodebuffer + n, nodebuffer, n);
+ memcpy(nodebuffer, state->stack + (state->stackoffset-1)*n, n);
+ setTreeHeight(node_addr, nodeheight);
+ setTreeIndex(node_addr, (treehash->next_idx >> (nodeheight+1)));
+ hash_h(nodebuffer, nodebuffer, pub_seed, node_addr, n);
+ nodeheight++;
+ treehash->stackusage--;
+ state->stackoffset--;
+ }
+ if (nodeheight == treehash->h) { // this also implies stackusage == 0
+ memcpy(treehash->node, nodebuffer, n);
+ treehash->completed = 1;
+ }
+ else {
+ memcpy(state->stack + state->stackoffset*n, nodebuffer, n);
+ treehash->stackusage++;
+ state->stacklevels[state->stackoffset] = nodeheight;
+ state->stackoffset++;
+ treehash->next_idx++;
+ }
+}
+
+/**
+ * Computes a root node given a leaf and an authapth
+ */
+static void validate_authpath(unsigned char *root, const unsigned char *leaf, unsigned long leafidx, const unsigned char *authpath, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8])
+{
+ unsigned int n = params->n;
+
+ uint32_t i, j;
+ unsigned char buffer[2*n];
+
+ // If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left.
+ // Otherwise, it is the other way around
+ if (leafidx & 1) {
+ for (j = 0; j < n; j++)
+ buffer[n+j] = leaf[j];
+ for (j = 0; j < n; j++)
+ buffer[j] = authpath[j];
+ }
+ else {
+ for (j = 0; j < n; j++)
+ buffer[j] = leaf[j];
+ for (j = 0; j < n; j++)
+ buffer[n+j] = authpath[j];
+ }
+ authpath += n;
+
+ for (i=0; i < params->h-1; i++) {
+ setTreeHeight(addr, i);
+ leafidx >>= 1;
+ setTreeIndex(addr, leafidx);
+ if (leafidx&1) {
+ hash_h(buffer+n, buffer, pub_seed, addr, n);
+ for (j = 0; j < n; j++)
+ buffer[j] = authpath[j];
+ }
+ else {
+ hash_h(buffer, buffer, pub_seed, addr, n);
+ for (j = 0; j < n; j++)
+ buffer[j+n] = authpath[j];
+ }
+ authpath += n;
+ }
+ setTreeHeight(addr, (params->h-1));
+ leafidx >>= 1;
+ setTreeIndex(addr, leafidx);
+ hash_h(root, buffer, pub_seed, addr, n);
+}
+
+/**
+ * Performs one treehash update on the instance that needs it the most.
+ * Returns 1 if such an instance was not found
+ **/
+static char bds_treehash_update(bds_state *state, unsigned int updates, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) {
+ uint32_t i, j;
+ unsigned int level, l_min, low;
+ unsigned int h = params->h;
+ unsigned int k = params->k;
+ unsigned int used = 0;
+
+ for (j = 0; j < updates; j++) {
+ l_min = h;
+ level = h - k;
+ for (i = 0; i < h - k; i++) {
+ if (state->treehash[i].completed) {
+ low = h;
+ }
+ else if (state->treehash[i].stackusage == 0) {
+ low = i;
+ }
+ else {
+ low = treehash_minheight_on_stack(state, params, &(state->treehash[i]));
+ }
+ if (low < l_min) {
+ level = i;
+ l_min = low;
+ }
+ }
+ if (level == h - k) {
+ break;
+ }
+ treehash_update(&(state->treehash[level]), state, sk_seed, params, pub_seed, addr);
+ used++;
+ }
+ return updates - used;
+}
+
+/**
+ * Updates the state (typically NEXT_i) by adding a leaf and updating the stack
+ * Returns 1 if all leaf nodes have already been processed
+ **/
+static char bds_state_update(bds_state *state, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) {
+ uint32_t ltree_addr[8];
+ uint32_t node_addr[8];
+ uint32_t ots_addr[8];
+
+ int n = params->n;
+ int h = params->h;
+ int k = params->k;
+
+ int nodeh;
+ int idx = state->next_leaf;
+ if (idx == 1 << h) {
+ return 1;
+ }
+
+ // only copy layer and tree address parts
+ memcpy(ots_addr, addr, 12);
+ // type = ots
+ setType(ots_addr, 0);
+ memcpy(ltree_addr, addr, 12);
+ setType(ltree_addr, 1);
+ memcpy(node_addr, addr, 12);
+ setType(node_addr, 2);
+
+ setOTSADRS(ots_addr, idx);
+ setLtreeADRS(ltree_addr, idx);
+
+ gen_leaf_wots(state->stack+state->stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr);
+
+ state->stacklevels[state->stackoffset] = 0;
+ state->stackoffset++;
+ if (h - k > 0 && idx == 3) {
+ memcpy(state->treehash[0].node, state->stack+state->stackoffset*n, n);
+ }
+ while (state->stackoffset>1 && state->stacklevels[state->stackoffset-1] == state->stacklevels[state->stackoffset-2]) {
+ nodeh = state->stacklevels[state->stackoffset-1];
+ if (idx >> nodeh == 1) {
+ memcpy(state->auth + nodeh*n, state->stack+(state->stackoffset-1)*n, n);
+ }
+ else {
+ if (nodeh < h - k && idx >> nodeh == 3) {
+ memcpy(state->treehash[nodeh].node, state->stack+(state->stackoffset-1)*n, n);
+ }
+ else if (nodeh >= h - k) {
+ memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((idx >> nodeh) - 3) >> 1)) * n, state->stack+(state->stackoffset-1)*n, n);
+ }
+ }
+ setTreeHeight(node_addr, state->stacklevels[state->stackoffset-1]);
+ setTreeIndex(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+1)));
+ hash_h(state->stack+(state->stackoffset-2)*n, state->stack+(state->stackoffset-2)*n, pub_seed, node_addr, n);
+
+ state->stacklevels[state->stackoffset-2]++;
+ state->stackoffset--;
+ }
+ state->next_leaf++;
+ return 0;
+}
+
+/**
+ * Returns the auth path for node leaf_idx and computes the auth path for the
+ * next leaf node, using the algorithm described by Buchmann, Dahmen and Szydlo
+ * in "Post Quantum Cryptography", Springer 2009.
+ */
+static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, uint32_t addr[8])
+{
+ unsigned int i;
+ unsigned int n = params->n;
+ unsigned int h = params->h;
+ unsigned int k = params->k;
+
+ unsigned int tau = h;
+ unsigned int startidx;
+ unsigned int offset, rowidx;
+ unsigned char buf[2 * n];
+
+ uint32_t ots_addr[8];
+ uint32_t ltree_addr[8];
+ uint32_t node_addr[8];
+ // only copy layer and tree address parts
+ memcpy(ots_addr, addr, 12);
+ // type = ots
+ setType(ots_addr, 0);
+ memcpy(ltree_addr, addr, 12);
+ setType(ltree_addr, 1);
+ memcpy(node_addr, addr, 12);
+ setType(node_addr, 2);
+
+ for (i = 0; i < h; i++) {
+ if (! ((leaf_idx >> i) & 1)) {
+ tau = i;
+ break;
+ }
+ }
+
+ if (tau > 0) {
+ memcpy(buf, state->auth + (tau-1) * n, n);
+ // we need to do this before refreshing state->keep to prevent overwriting
+ memcpy(buf + n, state->keep + ((tau-1) >> 1) * n, n);
+ }
+ if (!((leaf_idx >> (tau + 1)) & 1) && (tau < h - 1)) {
+ memcpy(state->keep + (tau >> 1)*n, state->auth + tau*n, n);
+ }
+ if (tau == 0) {
+ setLtreeADRS(ltree_addr, leaf_idx);
+ setOTSADRS(ots_addr, leaf_idx);
+ gen_leaf_wots(state->auth, sk_seed, params, pub_seed, ltree_addr, ots_addr);
+ }
+ else {
+ setTreeHeight(node_addr, (tau-1));
+ setTreeIndex(node_addr, leaf_idx >> tau);
+ hash_h(state->auth + tau * n, buf, pub_seed, node_addr, n);
+ for (i = 0; i < tau; i++) {
+ if (i < h - k) {
+ memcpy(state->auth + i * n, state->treehash[i].node, n);
+ }
+ else {
+ offset = (1 << (h - 1 - i)) + i - h;
+ rowidx = ((leaf_idx >> i) - 1) >> 1;
+ memcpy(state->auth + i * n, state->retain + (offset + rowidx) * n, n);
+ }
+ }
+
+ for (i = 0; i < ((tau < h - k) ? tau : (h - k)); i++) {
+ startidx = leaf_idx + 1 + 3 * (1 << i);
+ if (startidx < 1U << h) {
+ state->treehash[i].h = i;
+ state->treehash[i].next_idx = startidx;
+ state->treehash[i].completed = 0;
+ state->treehash[i].stackusage = 0;
+ }
+ }
+ }
+}
+
+/*
+ * Generates a XMSS key pair for a given parameter set.
+ * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
+ * Format pk: [root || PUB_SEED] omitting algo oid.
+ */
+int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_params *params)
+{
+ unsigned int n = params->n;
+ // Set idx = 0
+ sk[0] = 0;
+ sk[1] = 0;
+ sk[2] = 0;
+ sk[3] = 0;
+ // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte)
+ randombytes(sk+4, 3*n);
+ // Copy PUB_SEED to public key
+ memcpy(pk+n, sk+4+2*n, n);
+
+ uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+ // Compute root
+ treehash_setup(pk, params->h, 0, state, sk+4, params, sk+4+2*n, addr);
+ // copy root to sk
+ memcpy(sk+4+3*n, pk, n);
+ return 0;
+}
+
+/**
+ * Signs a message.
+ * Returns
+ * 1. an array containing the signature followed by the message AND
+ * 2. an updated secret key!
+ *
+ */
+int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmss_params *params)
+{
+ unsigned int h = params->h;
+ unsigned int n = params->n;
+ unsigned int k = params->k;
+ uint16_t i = 0;
+
+ // Extract SK
+ unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3];
+ unsigned char sk_seed[n];
+ memcpy(sk_seed, sk+4, n);
+ unsigned char sk_prf[n];
+ memcpy(sk_prf, sk+4+n, n);
+ unsigned char pub_seed[n];
+ memcpy(pub_seed, sk+4+2*n, n);
+
+ // index as 32 bytes string
+ unsigned char idx_bytes_32[32];
+ to_byte(idx_bytes_32, idx, 32);
+
+ unsigned char hash_key[3*n];
+
+ // Update SK
+ sk[0] = ((idx + 1) >> 24) & 255;
+ sk[1] = ((idx + 1) >> 16) & 255;
+ sk[2] = ((idx + 1) >> 8) & 255;
+ sk[3] = (idx + 1) & 255;
+ // -- Secret key for this non-forward-secure version is now updated.
+ // -- A productive implementation should use a file handle instead and write the updated secret key at this point!
+
+ // Init working params
+ unsigned char R[n];
+ unsigned char msg_h[n];
+ unsigned char ots_seed[n];
+ uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+ // ---------------------------------
+ // Message Hashing
+ // ---------------------------------
+
+ // Message Hash:
+ // First compute pseudorandom value
+ prf(R, idx_bytes_32, sk_prf, n);
+ // Generate hash key (R || root || idx)
+ memcpy(hash_key, R, n);
+ memcpy(hash_key+n, sk+4+3*n, n);
+ to_byte(hash_key+2*n, idx, n);
+ // Then use it for message digest
+ h_msg(msg_h, msg, msglen, hash_key, 3*n, n);
+
+ // Start collecting signature
+ *sig_msg_len = 0;
+
+ // Copy index to signature
+ sig_msg[0] = (idx >> 24) & 255;
+ sig_msg[1] = (idx >> 16) & 255;
+ sig_msg[2] = (idx >> 8) & 255;
+ sig_msg[3] = idx & 255;
+
+ sig_msg += 4;
+ *sig_msg_len += 4;
+
+ // Copy R to signature
+ for (i = 0; i < n; i++)
+ sig_msg[i] = R[i];
+
+ sig_msg += n;
+ *sig_msg_len += n;
+
+ // ----------------------------------
+ // Now we start to "really sign"
+ // ----------------------------------
+
+ // Prepare Address
+ setType(ots_addr, 0);
+ setOTSADRS(ots_addr, idx);
+
+ // Compute seed for OTS key pair
+ get_seed(ots_seed, sk_seed, n, ots_addr);
+
+ // Compute WOTS signature
+ wots_sign(sig_msg, msg_h, ots_seed, &(params->wots_par), pub_seed, ots_addr);
+
+ sig_msg += params->wots_par.keysize;
+ *sig_msg_len += params->wots_par.keysize;
+
+ // the auth path was already computed during the previous round
+ memcpy(sig_msg, state->auth, h*n);
+
+ if (idx < (1U << h) - 1) {
+ bds_round(state, idx, sk_seed, params, pub_seed, ots_addr);
+ bds_treehash_update(state, (h - k) >> 1, sk_seed, params, pub_seed, ots_addr);
+ }
+
+/* TODO: save key/bds state here! */
+
+ sig_msg += params->h*n;
+ *sig_msg_len += params->h*n;
+
+ //Whipe secret elements?
+ //zerobytes(tsk, CRYPTO_SECRETKEYBYTES);
+
+
+ memcpy(sig_msg, msg, msglen);
+ *sig_msg_len += msglen;
+
+ return 0;
+}
+
+/**
+ * Verifies a given message signature pair under a given public key.
+ */
+int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params)
+{
+ unsigned int n = params->n;
+
+ unsigned long long i, m_len;
+ unsigned long idx=0;
+ unsigned char wots_pk[params->wots_par.keysize];
+ unsigned char pkhash[n];
+ unsigned char root[n];
+ unsigned char msg_h[n];
+ unsigned char hash_key[3*n];
+
+ unsigned char pub_seed[n];
+ memcpy(pub_seed, pk+n, n);
+
+ // Init addresses
+ uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+ setType(ots_addr, 0);
+ setType(ltree_addr, 1);
+ setType(node_addr, 2);
+
+ // Extract index
+ idx = ((unsigned long)sig_msg[0] << 24) | ((unsigned long)sig_msg[1] << 16) | ((unsigned long)sig_msg[2] << 8) | sig_msg[3];
+ printf("verify:: idx = %lu\n", idx);
+
+ // Generate hash key (R || root || idx)
+ memcpy(hash_key, sig_msg+4,n);
+ memcpy(hash_key+n, pk, n);
+ to_byte(hash_key+2*n, idx, n);
+
+ sig_msg += (n+4);
+ sig_msg_len -= (n+4);
+
+ // hash message
+ unsigned long long tmp_sig_len = params->wots_par.keysize+params->h*n;
+ m_len = sig_msg_len - tmp_sig_len;
+ h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n);
+
+ //-----------------------
+ // Verify signature
+ //-----------------------
+
+ // Prepare Address
+ setOTSADRS(ots_addr, idx);
+ // Check WOTS signature
+ wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->wots_par), pub_seed, ots_addr);
+
+ sig_msg += params->wots_par.keysize;
+ sig_msg_len -= params->wots_par.keysize;
+
+ // Compute Ltree
+ setLtreeADRS(ltree_addr, idx);
+ l_tree(pkhash, wots_pk, params, pub_seed, ltree_addr);
+
+ // Compute root
+ validate_authpath(root, pkhash, idx, sig_msg, params, pub_seed, node_addr);
+
+ sig_msg += params->h*n;
+ sig_msg_len -= params->h*n;
+
+ for (i = 0; i < n; i++)
+ if (root[i] != pk[i])
+ goto fail;
+
+ *msglen = sig_msg_len;
+ for (i = 0; i < *msglen; i++)
+ msg[i] = sig_msg[i];
+
+ return 0;
+
+
+fail:
+ *msglen = sig_msg_len;
+ for (i = 0; i < *msglen; i++)
+ msg[i] = 0;
+ *msglen = -1;
+ return -1;
+}
+
+/*
+ * Generates a XMSSMT key pair for a given parameter set.
+ * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
+ * Format pk: [root || PUB_SEED] omitting algo oid.
+ */
+int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs, xmssmt_params *params)
+{
+ unsigned int n = params->n;
+ unsigned int i;
+ unsigned char ots_seed[params->n];
+ // Set idx = 0
+ for (i = 0; i < params->index_len; i++) {
+ sk[i] = 0;
+ }
+ // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte)
+ randombytes(sk+params->index_len, 3*n);
+ // Copy PUB_SEED to public key
+ memcpy(pk+n, sk+params->index_len+2*n, n);
+
+ // Set address to point on the single tree on layer d-1
+ uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ setLayerADRS(addr, (params->d-1));
+ // Set up state and compute wots signatures for all but topmost tree root
+ for (i = 0; i < params->d - 1; i++) {
+ // Compute seed for OTS key pair
+ treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr);
+ setLayerADRS(addr, (i+1));
+ get_seed(ots_seed, sk+params->index_len, n, addr);
+ wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, pk, ots_seed, &(params->xmss_par.wots_par), pk+n, addr);
+ }
+ treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr);
+ memcpy(sk+params->index_len+3*n, pk, n);
+ return 0;
+}
+
+/**
+ * Signs a message.
+ * Returns
+ * 1. an array containing the signature followed by the message AND
+ * 2. an updated secret key!
+ *
+ */
+int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params)
+{
+ unsigned int n = params->n;
+
+ unsigned int tree_h = params->xmss_par.h;
+ unsigned int h = params->h;
+ unsigned int k = params->xmss_par.k;
+ unsigned int idx_len = params->index_len;
+ uint64_t idx_tree;
+ uint32_t idx_leaf;
+ uint64_t i, j;
+ int needswap_upto = -1;
+ unsigned int updates;
+
+ unsigned char sk_seed[n];
+ unsigned char sk_prf[n];
+ unsigned char pub_seed[n];
+ // Init working params
+ unsigned char R[n];
+ unsigned char msg_h[n];
+ unsigned char hash_key[3*n];
+ unsigned char ots_seed[n];
+ uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ unsigned char idx_bytes_32[32];
+ bds_state tmp;
+
+ // Extract SK
+ unsigned long long idx = 0;
+ for (i = 0; i < idx_len; i++) {
+ idx |= ((unsigned long long)sk[i]) << 8*(idx_len - 1 - i);
+ }
+
+ memcpy(sk_seed, sk+idx_len, n);
+ memcpy(sk_prf, sk+idx_len+n, n);
+ memcpy(pub_seed, sk+idx_len+2*n, n);
+
+ // Update SK
+ for (i = 0; i < idx_len; i++) {
+ sk[i] = ((idx + 1) >> 8*(idx_len - 1 - i)) & 255;
+ }
+ // -- Secret key for this non-forward-secure version is now updated.
+ // -- A productive implementation should use a file handle instead and write the updated secret key at this point!
+
+
+ // ---------------------------------
+ // Message Hashing
+ // ---------------------------------
+
+ // Message Hash:
+ // First compute pseudorandom value
+ to_byte(idx_bytes_32, idx, 32);
+ prf(R, idx_bytes_32, sk_prf, n);
+ // Generate hash key (R || root || idx)
+ memcpy(hash_key, R, n);
+ memcpy(hash_key+n, sk+idx_len+3*n, n);
+ to_byte(hash_key+2*n, idx, n);
+
+ // Then use it for message digest
+ h_msg(msg_h, msg, msglen, hash_key, 3*n, n);
+
+ // Start collecting signature
+ *sig_msg_len = 0;
+
+ // Copy index to signature
+ for (i = 0; i < idx_len; i++) {
+ sig_msg[i] = (idx >> 8*(idx_len - 1 - i)) & 255;
+ }
+
+ sig_msg += idx_len;
+ *sig_msg_len += idx_len;
+
+ // Copy R to signature
+ for (i = 0; i < n; i++)
+ sig_msg[i] = R[i];
+
+ sig_msg += n;
+ *sig_msg_len += n;
+
+ // ----------------------------------
+ // Now we start to "really sign"
+ // ----------------------------------
+
+ // Handle lowest layer separately as it is slightly different...
+
+ // Prepare Address
+ setType(ots_addr, 0);
+ idx_tree = idx >> tree_h;
+ idx_leaf = (idx & ((1 << tree_h)-1));
+ setLayerADRS(ots_addr, 0);
+ setTreeADRS(ots_addr, idx_tree);
+ setOTSADRS(ots_addr, idx_leaf);
+
+ // Compute seed for OTS key pair
+ get_seed(ots_seed, sk_seed, n, ots_addr);
+
+ // Compute WOTS signature
+ wots_sign(sig_msg, msg_h, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr);
+
+ sig_msg += params->xmss_par.wots_par.keysize;
+ *sig_msg_len += params->xmss_par.wots_par.keysize;
+
+ memcpy(sig_msg, states[0].auth, tree_h*n);
+ sig_msg += tree_h*n;
+ *sig_msg_len += tree_h*n;
+
+ // prepare signature of remaining layers
+ for (i = 1; i < params->d; i++) {
+ // put WOTS signature in place
+ memcpy(sig_msg, wots_sigs + (i-1)*params->xmss_par.wots_par.keysize, params->xmss_par.wots_par.keysize);
+
+ sig_msg += params->xmss_par.wots_par.keysize;
+ *sig_msg_len += params->xmss_par.wots_par.keysize;
+
+ // put AUTH nodes in place
+ memcpy(sig_msg, states[i].auth, tree_h*n);
+ sig_msg += tree_h*n;
+ *sig_msg_len += tree_h*n;
+ }
+
+ updates = (tree_h - k) >> 1;
+
+ setTreeADRS(addr, (idx_tree + 1));
+ // mandatory update for NEXT_0 (does not count towards h-k/2) if NEXT_0 exists
+ if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << h)) {
+ bds_state_update(&states[params->d], sk_seed, &(params->xmss_par), pub_seed, addr);
+ }
+
+ for (i = 0; i < params->d; i++) {
+ // check if we're not at the end of a tree
+ if (! (((idx + 1) & ((1ULL << ((i+1)*tree_h)) - 1)) == 0)) {
+ idx_leaf = (idx >> (tree_h * i)) & ((1 << tree_h)-1);
+ idx_tree = (idx >> (tree_h * (i+1)));
+ setLayerADRS(addr, i);
+ setTreeADRS(addr, idx_tree);
+ if (i == (unsigned int) (needswap_upto + 1)) {
+ bds_round(&states[i], idx_leaf, sk_seed, &(params->xmss_par), pub_seed, addr);
+ }
+ updates = bds_treehash_update(&states[i], updates, sk_seed, &(params->xmss_par), pub_seed, addr);
+ setTreeADRS(addr, (idx_tree + 1));
+ // if a NEXT-tree exists for this level;
+ if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << (h - tree_h * i))) {
+ if (i > 0 && updates > 0 && states[params->d + i].next_leaf < (1ULL << h)) {
+ bds_state_update(&states[params->d + i], sk_seed, &(params->xmss_par), pub_seed, addr);
+ updates--;
+ }
+ }
+ }
+ else if (idx < (1ULL << h) - 1) {
+ memcpy(&tmp, states+params->d + i, sizeof(bds_state));
+ memcpy(states+params->d + i, states + i, sizeof(bds_state));
+ memcpy(states + i, &tmp, sizeof(bds_state));
+
+ setLayerADRS(ots_addr, (i+1));
+ setTreeADRS(ots_addr, ((idx + 1) >> ((i+2) * tree_h)));
+ setOTSADRS(ots_addr, (((idx >> ((i+1) * tree_h)) + 1) & ((1 << tree_h)-1)));
+
+ get_seed(ots_seed, sk+params->index_len, n, ots_addr);
+ wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, states[i].stack, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr);
+
+ states[params->d + i].stackoffset = 0;
+ states[params->d + i].next_leaf = 0;
+
+ updates--; // WOTS-signing counts as one update
+ needswap_upto = i;
+ for (j = 0; j < tree_h-k; j++) {
+ states[i].treehash[j].completed = 1;
+ }
+ }
+ }
+
+ //Whipe secret elements?
+ //zerobytes(tsk, CRYPTO_SECRETKEYBYTES);
+
+ memcpy(sig_msg, msg, msglen);
+ *sig_msg_len += msglen;
+
+ return 0;
+}
+
+/**
+ * Verifies a given message signature pair under a given public key.
+ */
+int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params)
+{
+ unsigned int n = params->n;
+
+ unsigned int tree_h = params->xmss_par.h;
+ unsigned int idx_len = params->index_len;
+ uint64_t idx_tree;
+ uint32_t idx_leaf;
+
+ unsigned long long i, m_len;
+ unsigned long long idx=0;
+ unsigned char wots_pk[params->xmss_par.wots_par.keysize];
+ unsigned char pkhash[n];
+ unsigned char root[n];
+ unsigned char msg_h[n];
+ unsigned char hash_key[3*n];
+
+ unsigned char pub_seed[n];
+ memcpy(pub_seed, pk+n, n);
+
+ // Init addresses
+ uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+ // Extract index
+ for (i = 0; i < idx_len; i++) {
+ idx |= ((unsigned long long)sig_msg[i]) << (8*(idx_len - 1 - i));
+ }
+ printf("verify:: idx = %llu\n", idx);
+ sig_msg += idx_len;
+ sig_msg_len -= idx_len;
+
+ // Generate hash key (R || root || idx)
+ memcpy(hash_key, sig_msg,n);
+ memcpy(hash_key+n, pk, n);
+ to_byte(hash_key+2*n, idx, n);
+
+ sig_msg += n;
+ sig_msg_len -= n;
+
+
+ // hash message (recall, R is now on pole position at sig_msg
+ unsigned long long tmp_sig_len = (params->d * params->xmss_par.wots_par.keysize) + (params->h * n);
+ m_len = sig_msg_len - tmp_sig_len;
+ h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n);
+
+
+ //-----------------------
+ // Verify signature
+ //-----------------------
+
+ // Prepare Address
+ idx_tree = idx >> tree_h;
+ idx_leaf = (idx & ((1 << tree_h)-1));
+ setLayerADRS(ots_addr, 0);
+ setTreeADRS(ots_addr, idx_tree);
+ setType(ots_addr, 0);
+
+ memcpy(ltree_addr, ots_addr, 12);
+ setType(ltree_addr, 1);
+
+ memcpy(node_addr, ltree_addr, 12);
+ setType(node_addr, 2);
+
+ setOTSADRS(ots_addr, idx_leaf);
+
+ // Check WOTS signature
+ wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->xmss_par.wots_par), pub_seed, ots_addr);
+
+ sig_msg += params->xmss_par.wots_par.keysize;
+ sig_msg_len -= params->xmss_par.wots_par.keysize;
+
+ // Compute Ltree
+ setLtreeADRS(ltree_addr, idx_leaf);
+ l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr);
+
+ // Compute root
+ validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr);
+
+ sig_msg += tree_h*n;
+ sig_msg_len -= tree_h*n;
+
+ for (i = 1; i < params->d; i++) {
+ // Prepare Address
+ idx_leaf = (idx_tree & ((1 << tree_h)-1));
+ idx_tree = idx_tree >> tree_h;
+
+ setLayerADRS(ots_addr, i);
+ setTreeADRS(ots_addr, idx_tree);
+ setType(ots_addr, 0);
+
+ memcpy(ltree_addr, ots_addr, 12);
+ setType(ltree_addr, 1);
+
+ memcpy(node_addr, ltree_addr, 12);
+ setType(node_addr, 2);
+
+ setOTSADRS(ots_addr, idx_leaf);
+
+ // Check WOTS signature
+ wots_pkFromSig(wots_pk, sig_msg, root, &(params->xmss_par.wots_par), pub_seed, ots_addr);
+
+ sig_msg += params->xmss_par.wots_par.keysize;
+ sig_msg_len -= params->xmss_par.wots_par.keysize;
+
+ // Compute Ltree
+ setLtreeADRS(ltree_addr, idx_leaf);
+ l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr);
+
+ // Compute root
+ validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr);
+
+ sig_msg += tree_h*n;
+ sig_msg_len -= tree_h*n;
+
+ }
+
+ for (i = 0; i < n; i++)
+ if (root[i] != pk[i])
+ goto fail;
+
+ *msglen = sig_msg_len;
+ for (i = 0; i < *msglen; i++)
+ msg[i] = sig_msg[i];
+
+ return 0;
+
+
+fail:
+ *msglen = sig_msg_len;
+ for (i = 0; i < *msglen; i++)
+ msg[i] = 0;
+ *msglen = -1;
+ return -1;
+}
+#endif /* WITH_XMSS */
diff --git a/xmss_fast.h b/xmss_fast.h
new file mode 100644
index 00000000..2ffba705
--- /dev/null
+++ b/xmss_fast.h
@@ -0,0 +1,111 @@
+#ifdef WITH_XMSS
+/* $OpenBSD: xmss_fast.h,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */
+/*
+xmss_fast.h version 20160722
+Andreas Hülsing
+Joost Rijneveld
+Public domain.
+*/
+
+#include "xmss_wots.h"
+
+#ifndef XMSS_H
+#define XMSS_H
+typedef struct{
+ unsigned int level;
+ unsigned long long subtree;
+ unsigned int subleaf;
+} leafaddr;
+
+typedef struct{
+ wots_params wots_par;
+ unsigned int n;
+ unsigned int h;
+ unsigned int k;
+} xmss_params;
+
+typedef struct{
+ xmss_params xmss_par;
+ unsigned int n;
+ unsigned int h;
+ unsigned int d;
+ unsigned int index_len;
+} xmssmt_params;
+
+typedef struct{
+ unsigned int h;
+ unsigned int next_idx;
+ unsigned int stackusage;
+ unsigned char completed;
+ unsigned char *node;
+} treehash_inst;
+
+typedef struct {
+ unsigned char *stack;
+ unsigned int stackoffset;
+ unsigned char *stacklevels;
+ unsigned char *auth;
+ unsigned char *keep;
+ treehash_inst *treehash;
+ unsigned char *retain;
+ unsigned int next_leaf;
+} bds_state;
+
+/**
+ * Initialize BDS state struct
+ * parameter names are the same as used in the description of the BDS traversal
+ */
+void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, unsigned char *stacklevels, unsigned char *auth, unsigned char *keep, treehash_inst *treehash, unsigned char *retain, int next_leaf);
+/**
+ * Initializes parameter set.
+ * Needed, for any of the other methods.
+ */
+int xmss_set_params(xmss_params *params, int n, int h, int w, int k);
+/**
+ * Initialize xmssmt_params struct
+ * parameter names are the same as in the draft
+ *
+ * Especially h is the total tree height, i.e. the XMSS trees have height h/d
+ */
+int xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w, int k);
+/**
+ * Generates a XMSS key pair for a given parameter set.
+ * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
+ * Format pk: [root || PUB_SEED] omitting algo oid.
+ */
+int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_params *params);
+/**
+ * Signs a message.
+ * Returns
+ * 1. an array containing the signature followed by the message AND
+ * 2. an updated secret key!
+ *
+ */
+int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg,unsigned long long msglen, const xmss_params *params);
+/**
+ * Verifies a given message signature pair under a given public key.
+ *
+ * Note: msg and msglen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sig_msg which has the form (sig||msg).
+ */
+int xmss_sign_open(unsigned char *msg,unsigned long long *msglen, const unsigned char *sig_msg,unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params);
+
+/*
+ * Generates a XMSSMT key pair for a given parameter set.
+ * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
+ * Format pk: [root || PUB_SEED] omitting algo oid.
+ */
+int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs, xmssmt_params *params);
+/**
+ * Signs a message.
+ * Returns
+ * 1. an array containing the signature followed by the message AND
+ * 2. an updated secret key!
+ *
+ */
+int xmssmt_sign(unsigned char *sk, bds_state *state, unsigned char *wots_sigs, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params);
+/**
+ * Verifies a given message signature pair under a given public key.
+ */
+int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params);
+#endif
+#endif /* WITH_XMSS */
diff --git a/xmss_hash.c b/xmss_hash.c
new file mode 100644
index 00000000..50a57794
--- /dev/null
+++ b/xmss_hash.c
@@ -0,0 +1,140 @@
+/* $OpenBSD: xmss_hash.c,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */
+/*
+hash.c version 20160722
+Andreas Hülsing
+Joost Rijneveld
+Public domain.
+*/
+
+#include "includes.h"
+#ifdef WITH_XMSS
+
+#include "xmss_hash_address.h"
+#include "xmss_commons.h"
+#include "xmss_hash.h"
+
+#include <stddef.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <openssl/sha.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+
+int core_hash_SHA2(unsigned char *, const unsigned int, const unsigned char *,
+ unsigned int, const unsigned char *, unsigned long long, unsigned int);
+
+unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]){
+#if IS_LITTLE_ENDIAN==1
+ int i = 0;
+ for(i=0;i<8;i++)
+ to_byte(bytes+i*4, addr[i],4);
+ return bytes;
+#else
+ memcpy(bytes, addr, 32);
+ return bytes;
+#endif
+}
+
+int core_hash_SHA2(unsigned char *out, const unsigned int type, const unsigned char *key, unsigned int keylen, const unsigned char *in, unsigned long long inlen, unsigned int n){
+ unsigned long long i = 0;
+ unsigned char buf[inlen + n + keylen];
+
+ // Input is (toByte(X, 32) || KEY || M)
+
+ // set toByte
+ to_byte(buf, type, n);
+
+ for (i=0; i < keylen; i++) {
+ buf[i+n] = key[i];
+ }
+
+ for (i=0; i < inlen; i++) {
+ buf[keylen + n + i] = in[i];
+ }
+
+ if (n == 32) {
+ SHA256(buf, inlen + keylen + n, out);
+ return 0;
+ }
+ else {
+ if (n == 64) {
+ SHA512(buf, inlen + keylen + n, out);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/**
+ * Implements PRF
+ */
+int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen)
+{
+ return core_hash_SHA2(out, 3, key, keylen, in, 32, keylen);
+}
+
+/*
+ * Implemts H_msg
+ */
+int h_msg(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *key, const unsigned int keylen, const unsigned int n)
+{
+ if (keylen != 3*n){
+ // H_msg takes 3n-bit keys, but n does not match the keylength of keylen
+ return -1;
+ }
+ return core_hash_SHA2(out, 2, key, keylen, in, inlen, n);
+}
+
+/**
+ * We assume the left half is in in[0]...in[n-1]
+ */
+int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n)
+{
+
+ unsigned char buf[2*n];
+ unsigned char key[n];
+ unsigned char bitmask[2*n];
+ unsigned char byte_addr[32];
+ unsigned int i;
+
+ setKeyAndMask(addr, 0);
+ addr_to_byte(byte_addr, addr);
+ prf(key, byte_addr, pub_seed, n);
+ // Use MSB order
+ setKeyAndMask(addr, 1);
+ addr_to_byte(byte_addr, addr);
+ prf(bitmask, byte_addr, pub_seed, n);
+ setKeyAndMask(addr, 2);
+ addr_to_byte(byte_addr, addr);
+ prf(bitmask+n, byte_addr, pub_seed, n);
+ for (i = 0; i < 2*n; i++) {
+ buf[i] = in[i] ^ bitmask[i];
+ }
+ return core_hash_SHA2(out, 1, key, n, buf, 2*n, n);
+}
+
+int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n)
+{
+ unsigned char buf[n];
+ unsigned char key[n];
+ unsigned char bitmask[n];
+ unsigned char byte_addr[32];
+ unsigned int i;
+
+ setKeyAndMask(addr, 0);
+ addr_to_byte(byte_addr, addr);
+ prf(key, byte_addr, pub_seed, n);
+
+ setKeyAndMask(addr, 1);
+ addr_to_byte(byte_addr, addr);
+ prf(bitmask, byte_addr, pub_seed, n);
+
+ for (i = 0; i < n; i++) {
+ buf[i] = in[i] ^ bitmask[i];
+ }
+ return core_hash_SHA2(out, 0, key, n, buf, n, n);
+}
+#endif /* WITH_XMSS */
diff --git a/xmss_hash.h b/xmss_hash.h
new file mode 100644
index 00000000..d19c6215
--- /dev/null
+++ b/xmss_hash.h
@@ -0,0 +1,22 @@
+#ifdef WITH_XMSS
+/* $OpenBSD: xmss_hash.h,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */
+/*
+hash.h version 20160722
+Andreas Hülsing
+Joost Rijneveld
+Public domain.
+*/
+
+#ifndef HASH_H
+#define HASH_H
+
+#define IS_LITTLE_ENDIAN 1
+
+unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]);
+int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen);
+int h_msg(unsigned char *out,const unsigned char *in,unsigned long long inlen, const unsigned char *key, const unsigned int keylen, const unsigned int n);
+int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n);
+int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n);
+
+#endif
+#endif /* WITH_XMSS */
diff --git a/xmss_hash_address.c b/xmss_hash_address.c
new file mode 100644
index 00000000..2702c456
--- /dev/null
+++ b/xmss_hash_address.c
@@ -0,0 +1,66 @@
+/* $OpenBSD: xmss_hash_address.c,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */
+/*
+hash_address.c version 20160722
+Andreas Hülsing
+Joost Rijneveld
+Public domain.
+*/
+#include "includes.h"
+#ifdef WITH_XMSS
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include "xmss_hash_address.h" /* prototypes */
+
+void setLayerADRS(uint32_t adrs[8], uint32_t layer){
+ adrs[0] = layer;
+}
+
+void setTreeADRS(uint32_t adrs[8], uint64_t tree){
+ adrs[1] = (uint32_t) (tree >> 32);
+ adrs[2] = (uint32_t) tree;
+}
+
+void setType(uint32_t adrs[8], uint32_t type){
+ adrs[3] = type;
+ int i;
+ for(i = 4; i < 8; i++){
+ adrs[i] = 0;
+ }
+}
+
+void setKeyAndMask(uint32_t adrs[8], uint32_t keyAndMask){
+ adrs[7] = keyAndMask;
+}
+
+// OTS
+
+void setOTSADRS(uint32_t adrs[8], uint32_t ots){
+ adrs[4] = ots;
+}
+
+void setChainADRS(uint32_t adrs[8], uint32_t chain){
+ adrs[5] = chain;
+}
+
+void setHashADRS(uint32_t adrs[8], uint32_t hash){
+ adrs[6] = hash;
+}
+
+// L-tree
+
+void setLtreeADRS(uint32_t adrs[8], uint32_t ltree){
+ adrs[4] = ltree;
+}
+
+// Hash Tree & L-tree
+
+void setTreeHeight(uint32_t adrs[8], uint32_t treeHeight){
+ adrs[5] = treeHeight;
+}
+
+void setTreeIndex(uint32_t adrs[8], uint32_t treeIndex){
+ adrs[6] = treeIndex;
+}
+#endif /* WITH_XMSS */
diff --git a/xmss_hash_address.h b/xmss_hash_address.h
new file mode 100644
index 00000000..66bb4cc4
--- /dev/null
+++ b/xmss_hash_address.h
@@ -0,0 +1,40 @@
+#ifdef WITH_XMSS
+/* $OpenBSD: xmss_hash_address.h,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */
+/*
+hash_address.h version 20160722
+Andreas Hülsing
+Joost Rijneveld
+Public domain.
+*/
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+void setLayerADRS(uint32_t adrs[8], uint32_t layer);
+
+void setTreeADRS(uint32_t adrs[8], uint64_t tree);
+
+void setType(uint32_t adrs[8], uint32_t type);
+
+void setKeyAndMask(uint32_t adrs[8], uint32_t keyAndMask);
+
+// OTS
+
+void setOTSADRS(uint32_t adrs[8], uint32_t ots);
+
+void setChainADRS(uint32_t adrs[8], uint32_t chain);
+
+void setHashADRS(uint32_t adrs[8], uint32_t hash);
+
+// L-tree
+
+void setLtreeADRS(uint32_t adrs[8], uint32_t ltree);
+
+// Hash Tree & L-tree
+
+void setTreeHeight(uint32_t adrs[8], uint32_t treeHeight);
+
+void setTreeIndex(uint32_t adrs[8], uint32_t treeIndex);
+
+#endif /* WITH_XMSS */
diff --git a/xmss_wots.c b/xmss_wots.c
new file mode 100644
index 00000000..993e661f
--- /dev/null
+++ b/xmss_wots.c
@@ -0,0 +1,192 @@
+/* $OpenBSD: xmss_wots.c,v 1.3 2018/04/10 00:10:49 djm Exp $ */
+/*
+wots.c version 20160722
+Andreas Hülsing
+Joost Rijneveld
+Public domain.
+*/
+
+#include "includes.h"
+#ifdef WITH_XMSS
+
+#include <stdlib.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <limits.h>
+#include "xmss_commons.h"
+#include "xmss_hash.h"
+#include "xmss_wots.h"
+#include "xmss_hash_address.h"
+
+
+/* libm-free version of log2() for wots */
+static inline int
+wots_log2(uint32_t v)
+{
+ int b;
+
+ for (b = sizeof (v) * CHAR_BIT - 1; b >= 0; b--) {
+ if ((1U << b) & v) {
+ return b;
+ }
+ }
+ return 0;
+}
+
+void
+wots_set_params(wots_params *params, int n, int w)
+{
+ params->n = n;
+ params->w = w;
+ params->log_w = wots_log2(params->w);
+ params->len_1 = (CHAR_BIT * n) / params->log_w;
+ params->len_2 = (wots_log2(params->len_1 * (w - 1)) / params->log_w) + 1;
+ params->len = params->len_1 + params->len_2;
+ params->keysize = params->len * params->n;
+}
+
+/**
+ * Helper method for pseudorandom key generation
+ * Expands an n-byte array into a len*n byte array
+ * this is done using PRF
+ */
+static void expand_seed(unsigned char *outseeds, const unsigned char *inseed, const wots_params *params)
+{
+ uint32_t i = 0;
+ unsigned char ctr[32];
+ for(i = 0; i < params->len; i++){
+ to_byte(ctr, i, 32);
+ prf((outseeds + (i*params->n)), ctr, inseed, params->n);
+ }
+}
+
+/**
+ * Computes the chaining function.
+ * out and in have to be n-byte arrays
+ *
+ * interprets in as start-th value of the chain
+ * addr has to contain the address of the chain
+ */
+static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8])
+{
+ uint32_t i, j;
+ for (j = 0; j < params->n; j++)
+ out[j] = in[j];
+
+ for (i = start; i < (start+steps) && i < params->w; i++) {
+ setHashADRS(addr, i);
+ hash_f(out, out, pub_seed, addr, params->n);
+ }
+}
+
+/**
+ * base_w algorithm as described in draft.
+ *
+ *
+ */
+static void base_w(int *output, const int out_len, const unsigned char *input, const wots_params *params)
+{
+ int in = 0;
+ int out = 0;
+ uint32_t total = 0;
+ int bits = 0;
+ int consumed = 0;
+
+ for (consumed = 0; consumed < out_len; consumed++) {
+ if (bits == 0) {
+ total = input[in];
+ in++;
+ bits += 8;
+ }
+ bits -= params->log_w;
+ output[out] = (total >> bits) & (params->w - 1);
+ out++;
+ }
+}
+
+void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8])
+{
+ uint32_t i;
+ expand_seed(pk, sk, params);
+ for (i=0; i < params->len; i++) {
+ setChainADRS(addr, i);
+ gen_chain(pk+i*params->n, pk+i*params->n, 0, params->w-1, params, pub_seed, addr);
+ }
+}
+
+
+int wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8])
+{
+ //int basew[params->len];
+ int csum = 0;
+ uint32_t i = 0;
+ int *basew = calloc(params->len, sizeof(int));
+ if (basew == NULL)
+ return -1;
+
+ base_w(basew, params->len_1, msg, params);
+
+ for (i=0; i < params->len_1; i++) {
+ csum += params->w - 1 - basew[i];
+ }
+
+ csum = csum << (8 - ((params->len_2 * params->log_w) % 8));
+
+ int len_2_bytes = ((params->len_2 * params->log_w) + 7) / 8;
+
+ unsigned char csum_bytes[len_2_bytes];
+ to_byte(csum_bytes, csum, len_2_bytes);
+
+ int csum_basew[params->len_2];
+ base_w(csum_basew, params->len_2, csum_bytes, params);
+
+ for (i = 0; i < params->len_2; i++) {
+ basew[params->len_1 + i] = csum_basew[i];
+ }
+
+ expand_seed(sig, sk, params);
+
+ for (i = 0; i < params->len; i++) {
+ setChainADRS(addr, i);
+ gen_chain(sig+i*params->n, sig+i*params->n, 0, basew[i], params, pub_seed, addr);
+ }
+ free(basew);
+ return 0;
+}
+
+int wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8])
+{
+ int csum = 0;
+ uint32_t i = 0;
+ int *basew = calloc(params->len, sizeof(int));
+ if (basew == NULL)
+ return -1;
+
+ base_w(basew, params->len_1, msg, params);
+
+ for (i=0; i < params->len_1; i++) {
+ csum += params->w - 1 - basew[i];
+ }
+
+ csum = csum << (8 - ((params->len_2 * params->log_w) % 8));
+
+ int len_2_bytes = ((params->len_2 * params->log_w) + 7) / 8;
+
+ unsigned char csum_bytes[len_2_bytes];
+ to_byte(csum_bytes, csum, len_2_bytes);
+
+ int csum_basew[params->len_2];
+ base_w(csum_basew, params->len_2, csum_bytes, params);
+
+ for (i = 0; i < params->len_2; i++) {
+ basew[params->len_1 + i] = csum_basew[i];
+ }
+ for (i=0; i < params->len; i++) {
+ setChainADRS(addr, i);
+ gen_chain(pk+i*params->n, sig+i*params->n, basew[i], params->w-1-basew[i], params, pub_seed, addr);
+ }
+ free(basew);
+ return 0;
+}
+#endif /* WITH_XMSS */
diff --git a/xmss_wots.h b/xmss_wots.h
new file mode 100644
index 00000000..1eebf3b2
--- /dev/null
+++ b/xmss_wots.h
@@ -0,0 +1,64 @@
+#ifdef WITH_XMSS
+/* $OpenBSD: xmss_wots.h,v 1.3 2018/02/26 12:14:53 dtucker Exp $ */
+/*
+wots.h version 20160722
+Andreas Hülsing
+Joost Rijneveld
+Public domain.
+*/
+
+#ifndef WOTS_H
+#define WOTS_H
+
+#ifdef HAVE_STDINT_H
+#include "stdint.h"
+#endif
+
+/**
+ * WOTS parameter set
+ *
+ * Meaning as defined in draft-irtf-cfrg-xmss-hash-based-signatures-02
+ */
+typedef struct {
+ uint32_t len_1;
+ uint32_t len_2;
+ uint32_t len;
+ uint32_t n;
+ uint32_t w;
+ uint32_t log_w;
+ uint32_t keysize;
+} wots_params;
+
+/**
+ * Set the WOTS parameters,
+ * only m, n, w are required as inputs,
+ * len, len_1, and len_2 are computed from those.
+ *
+ * Assumes w is a power of 2
+ */
+void wots_set_params(wots_params *params, int n, int w);
+
+/**
+ * WOTS key generation. Takes a 32byte seed for the secret key, expands it to a full WOTS secret key and computes the corresponding public key.
+ * For this it takes the seed pub_seed which is used to generate bitmasks and hash keys and the address of this WOTS key pair addr
+ *
+ * params, must have been initialized before using wots_set params for params ! This is not done in this function
+ *
+ * Places the computed public key at address pk.
+ */
+void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]);
+
+/**
+ * Takes a m-byte message and the 32-byte seed for the secret key to compute a signature that is placed at "sig".
+ *
+ */
+int wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]);
+
+/**
+ * Takes a WOTS signature, a m-byte message and computes a WOTS public key that it places at pk.
+ *
+ */
+int wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]);
+
+#endif
+#endif /* WITH_XMSS */